Comment Sema: refactor handling of 'ParmVarDecl's and save them in Sema members.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160634 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index be8179d..f8b35d0 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -38,8 +38,22 @@
 
   DiagnosticsEngine &Diags;
 
+  /// Declaration this comment is attached to.
   const Decl *ThisDecl;
 
+  /// Parameters that can be referenced by \\param if \c ThisDecl is something
+  /// that we consider a "function".
+  /// Contains a valid value if \c IsThisDeclInspected is true.
+  ArrayRef<const ParmVarDecl *> ParamVars;
+
+  /// True if we extracted all important information from \c ThisDecl into
+  /// \c Sema members.
+  unsigned IsThisDeclInspected : 1;
+
+  /// Is \c ThisDecl something that we consider a "function".
+  /// Contains a valid value if \c IsThisDeclInspected is true.
+  unsigned IsFunctionDecl : 1;
+
   DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
     return Diags.Report(Loc, DiagID);
   }
@@ -140,16 +154,21 @@
 
   void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
 
+  bool isFunctionDecl();
+  ArrayRef<const ParmVarDecl *> getParamVars();
+
+  /// Extract all important semantic information from \c ThisDecl into
+  /// \c Sema members.
+  void inspectThisDecl();
+
   /// Returns index of a function parameter with a given name.
   unsigned resolveParmVarReference(StringRef Name,
-                                   const ParmVarDecl * const *ParamVars,
-                                   unsigned NumParams);
+                                   ArrayRef<const ParmVarDecl *> ParamVars);
 
   /// Returns index of a function parameter with the name closest to a given
   /// typo.
   unsigned correctTypoInParmVarReference(StringRef Typo,
-                                         const ParmVarDecl * const *ParamVars,
-                                         unsigned NumParams);
+                                         ArrayRef<const ParmVarDecl *> ParamVars);
 
   bool isBlockCommand(StringRef Name);
   bool isParamCommand(StringRef Name);
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index 6c37452..bfc9b91 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -19,7 +19,8 @@
 
 Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
            DiagnosticsEngine &Diags) :
-    Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), ThisDecl(NULL) {
+    Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), ThisDecl(NULL),
+    IsThisDeclInspected(false) {
 }
 
 void Sema::setDecl(const Decl *D) {
@@ -58,8 +59,7 @@
   ParamCommandComment *Command =
       new (Allocator) ParamCommandComment(LocBegin, LocEnd, Name);
 
-  if (!ThisDecl ||
-      !(isa<FunctionDecl>(ThisDecl) || isa<ObjCMethodDecl>(ThisDecl)))
+  if (!isFunctionDecl())
     Diag(Command->getLocation(),
          diag::warn_doc_param_not_attached_to_a_function_decl)
       << Command->getCommandNameRange();
@@ -142,25 +142,15 @@
                                          Arg);
   Command->setArgs(llvm::makeArrayRef(A, 1));
 
-  if (!ThisDecl)
-    return Command;
-
-  const ParmVarDecl * const *ParamVars;
-  unsigned NumParams;
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
-    ParamVars = FD->param_begin();
-    NumParams = FD->getNumParams();
-  } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
-    ParamVars = MD->param_begin();
-    NumParams = MD->param_size();
-  } else {
+  if (!isFunctionDecl()) {
     // We already warned that this \\param is not attached to a function decl.
     return Command;
   }
 
+  ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
+
   // Check that referenced parameter name is in the function decl.
-  const unsigned ResolvedParamIndex = resolveParmVarReference(Arg, ParamVars,
-                                                              NumParams);
+  const unsigned ResolvedParamIndex = resolveParmVarReference(Arg, ParamVars);
   if (ResolvedParamIndex != ParamCommandComment::InvalidParamIndex) {
     Command->setParamIndex(ResolvedParamIndex);
     return Command;
@@ -171,14 +161,13 @@
     << Arg << ArgRange;
 
   unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
-  if (NumParams == 1) {
+  if (ParamVars.size() == 1) {
     // If function has only one parameter then only that parameter
     // can be documented.
     CorrectedParamIndex = 0;
   } else {
     // Do typo correction.
-    CorrectedParamIndex = correctTypoInParmVarReference(Arg, ParamVars,
-                                                        NumParams);
+    CorrectedParamIndex = correctTypoInParmVarReference(Arg, ParamVars);
   }
   if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
     const ParmVarDecl *CorrectedPVD = ParamVars[CorrectedParamIndex];
@@ -362,6 +351,7 @@
 
 FullComment *Sema::actOnFullComment(
                               ArrayRef<BlockContentComment *> Blocks) {
+  SmallVector<ParamCommandComment *, 8> Params;
   return new (Allocator) FullComment(Blocks);
 }
 
@@ -379,10 +369,44 @@
   }
 }
 
+bool Sema::isFunctionDecl() {
+  if (IsThisDeclInspected)
+    return IsFunctionDecl;
+
+  inspectThisDecl();
+  return IsFunctionDecl;
+}
+
+ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
+  if (IsThisDeclInspected)
+    return ParamVars;
+
+  inspectThisDecl();
+  return ParamVars;
+}
+
+void Sema::inspectThisDecl() {
+  if (!ThisDecl) {
+    IsFunctionDecl = false;
+    ParamVars = ArrayRef<const ParmVarDecl *>();
+  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
+    IsFunctionDecl = true;
+    ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
+                                              FD->getNumParams());
+  } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
+    IsFunctionDecl = true;
+    ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
+                                              MD->param_size());
+  } else {
+    IsFunctionDecl = false;
+    ParamVars = ArrayRef<const ParmVarDecl *>();
+  }
+  IsThisDeclInspected = true;
+}
+
 unsigned Sema::resolveParmVarReference(StringRef Name,
-                                       const ParmVarDecl * const *ParamVars,
-                                       unsigned NumParams) {
-  for (unsigned i = 0; i != NumParams; ++i) {
+                                       ArrayRef<const ParmVarDecl *> ParamVars) {
+  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
     const IdentifierInfo *II = ParamVars[i]->getIdentifier();
     if (II && II->getName() == Name)
       return i;
@@ -392,12 +416,11 @@
 
 unsigned Sema::correctTypoInParmVarReference(
                                     StringRef Typo,
-                                    const ParmVarDecl * const *ParamVars,
-                                    unsigned NumParams) {
+                                    ArrayRef<const ParmVarDecl *> ParamVars) {
   const unsigned MaxEditDistance = (Typo.size() + 2) / 3;
   unsigned BestPVDIndex = 0;
   unsigned BestEditDistance = MaxEditDistance + 1;
-  for (unsigned i = 0; i != NumParams; ++i) {
+  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
     const IdentifierInfo *II = ParamVars[i]->getIdentifier();
     if (II) {
       StringRef Name = II->getName();