Comment AST: add DeclInfo to store information about the declaration.  Sema was
already extracting most of this, but discarding at the end of semantic analysis.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161140 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index 089e7cd..32c96a5 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -19,6 +19,10 @@
 #include "llvm/ADT/StringRef.h"
 
 namespace clang {
+class Decl;
+class ParmVarDecl;
+class TemplateParameterList;
+
 namespace comments {
 
 /// Any part of the comment.
@@ -906,14 +910,61 @@
   }
 };
 
+/// Information about the declaration, useful to clients of FullComment.
+struct DeclInfo {
+  /// Declaration the comment is attached to.  Should not be NULL.
+  const Decl *ThisDecl;
+
+  /// Parameters that can be referenced by \\param if \c ThisDecl is something
+  /// that we consider a "function".
+  ArrayRef<const ParmVarDecl *> ParamVars;
+
+  /// Template parameters that can be referenced by \\tparam if \c ThisDecl is
+  /// a template.
+  const TemplateParameterList *TemplateParameters;
+
+  /// If false, only \c ThisDecl is valid.
+  unsigned IsFilled : 1;
+
+  /// Is \c ThisDecl something that we consider a "function".
+  unsigned IsFunctionDecl : 1;
+
+  /// Is \c ThisDecl something that we consider a "class".
+  unsigned IsClassDecl : 1;
+
+  /// Is \c ThisDecl a template declaration.
+  unsigned IsTemplateDecl : 1;
+
+  /// Is \c ThisDecl a template specialization.
+  unsigned IsTemplateSpecialization : 1;
+
+  /// Is \c ThisDecl a template partial specialization.
+  /// Never true if \c IsFunctionDecl is true.
+  unsigned IsTemplatePartialSpecialization : 1;
+
+  /// Is \c ThisDecl a non-static member function of C++ class or
+  /// instance method of ObjC class.
+  /// Can be true only if \c IsFunctionDecl is true.
+  unsigned IsInstanceMethod : 1;
+
+  /// Is \c ThisDecl a static member function of C++ class or
+  /// class method of ObjC class.
+  /// Can be true only if \c IsFunctionDecl is true.
+  unsigned IsClassMethod : 1;
+
+  void fill();
+};
+
 /// A full comment attached to a declaration, contains block content.
 class FullComment : public Comment {
   llvm::ArrayRef<BlockContentComment *> Blocks;
 
+  DeclInfo *ThisDeclInfo;
+
 public:
-  FullComment(llvm::ArrayRef<BlockContentComment *> Blocks) :
+  FullComment(llvm::ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
       Comment(FullCommentKind, SourceLocation(), SourceLocation()),
-      Blocks(Blocks) {
+      Blocks(Blocks), ThisDeclInfo(D) {
     if (Blocks.empty())
       return;
 
@@ -935,6 +986,16 @@
   child_iterator child_end() const {
     return reinterpret_cast<child_iterator>(Blocks.end());
   }
+
+  const Decl *getDecl() const LLVM_READONLY {
+    return ThisDeclInfo->ThisDecl;
+  }
+
+  const DeclInfo *getDeclInfo() const LLVM_READONLY {
+    if (!ThisDeclInfo->IsFilled)
+      ThisDeclInfo->fill();
+    return ThisDeclInfo;
+  }
 };
 
 } // end namespace comments
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index c51439b..77fa85a 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -24,9 +24,6 @@
 
 namespace clang {
 class Decl;
-class FunctionDecl;
-class ParmVarDecl;
-class TemplateParameterList;
 class SourceMgr;
 
 namespace comments {
@@ -43,45 +40,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;
+  /// Information about the declaration this comment is attached to.
+  DeclInfo *ThisDeclInfo;
 
   /// Comment AST nodes that correspond to \c ParamVars for which we have
   /// found a \\param command or NULL if no documentation was found so far.
   ///
-  /// Has correct size and contains valid values if \c IsThisDeclInspected is
+  /// Has correct size and contains valid values if \c DeclInfo->IsFilled is
   /// true.
   llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
 
-  /// Template parameters that can be referenced by \\tparam if \c ThisDecl is
-  /// a template.
-  ///
-  /// Contains a valid value if \c IsThisDeclInspected is true.
-  const TemplateParameterList *TemplateParameters;
-
   /// Comment AST nodes that correspond to parameter names in
   /// \c TemplateParameters.
   ///
-  /// Contains a valid value if \c IsThisDeclInspected is true.
+  /// Contains a valid value if \c DeclInfo->IsFilled is true.
   llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
 
-  /// 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;
-
-  /// Is \c ThisDecl a template declaration.
-  /// Contains a valid value if \c IsThisDeclInspected is true.
-  unsigned IsTemplateDecl : 1;
-
   DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
     return Diags.Report(Loc, DiagID);
   }
@@ -212,8 +186,8 @@
 
   ArrayRef<const ParmVarDecl *> getParamVars();
 
-  /// Extract all important semantic information from \c ThisDecl into
-  /// \c Sema members.
+  /// Extract all important semantic information from
+  /// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members.
   void inspectThisDecl();
 
   /// Returns index of a function parameter with a given name.
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp
index 82dbed4..15b80c6 100644
--- a/lib/AST/Comment.cpp
+++ b/lib/AST/Comment.cpp
@@ -8,6 +8,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/Comment.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -134,5 +137,66 @@
   llvm_unreachable("unknown PassDirection");
 }
 
+void DeclInfo::fill() {
+  assert(!IsFilled);
+
+  // Set defaults.
+  IsFunctionDecl = false;
+  IsTemplateDecl = false;
+  IsTemplateSpecialization = false;
+  IsTemplatePartialSpecialization = false;
+  IsInstanceMethod = false;
+  IsClassMethod = false;
+  ParamVars = ArrayRef<const ParmVarDecl *>();
+  TemplateParameters = NULL;
+
+  if (!ThisDecl) {
+    // Defaults are OK.
+  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
+    IsFunctionDecl = true;
+    ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
+                                              FD->getNumParams());
+    unsigned NumLists = FD->getNumTemplateParameterLists();
+    if (NumLists != 0) {
+      IsTemplateDecl = true;
+      IsTemplateSpecialization = true;
+      TemplateParameters =
+          FD->getTemplateParameterList(NumLists - 1);
+    }
+
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+      IsInstanceMethod = MD->isInstance();
+      IsClassMethod = !IsInstanceMethod;
+    }
+  } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
+    IsFunctionDecl = true;
+    ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
+                                              MD->param_size());
+    IsInstanceMethod = MD->isInstanceMethod();
+    IsClassMethod = !IsInstanceMethod;
+  } else if (const FunctionTemplateDecl *FTD =
+                 dyn_cast<FunctionTemplateDecl>(ThisDecl)) {
+    IsFunctionDecl = true;
+    IsTemplateDecl = true;
+    const FunctionDecl *FD = FTD->getTemplatedDecl();
+    ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
+                                              FD->getNumParams());
+    TemplateParameters = FTD->getTemplateParameters();
+  } else if (const ClassTemplateDecl *CTD =
+                 dyn_cast<ClassTemplateDecl>(ThisDecl)) {
+    IsTemplateDecl = true;
+    TemplateParameters = CTD->getTemplateParameters();
+  } else if (const ClassTemplatePartialSpecializationDecl *CTPSD =
+                 dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) {
+    IsTemplateDecl = true;
+    IsTemplatePartialSpecialization = true;
+    TemplateParameters = CTPSD->getTemplateParameters();
+  } else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) {
+    IsTemplateDecl = true;
+    IsTemplateSpecialization = true;
+  }
+  IsFilled = true;
+}
+
 } // end namespace comments
 } // end namespace clang
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index 7b42c86..3566091 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -10,7 +10,6 @@
 #include "clang/AST/CommentSema.h"
 #include "clang/AST/CommentDiagnostic.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -20,12 +19,16 @@
 
 Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
            DiagnosticsEngine &Diags) :
-    Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), ThisDecl(NULL),
-    IsThisDeclInspected(false) {
+    Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags),
+    ThisDeclInfo(NULL) {
 }
 
 void Sema::setDecl(const Decl *D) {
-  ThisDecl = D;
+  if (!D)
+    return;
+
+  ThisDeclInfo = new (Allocator) DeclInfo;
+  ThisDeclInfo->ThisDecl = D;
 }
 
 ParagraphComment *Sema::actOnParagraphComment(
@@ -234,6 +237,8 @@
     return Command;
   }
 
+  const TemplateParameterList *TemplateParameters =
+      ThisDeclInfo->TemplateParameters;
   SmallVector<unsigned, 2> Position;
   if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
     Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
@@ -449,7 +454,7 @@
 
 FullComment *Sema::actOnFullComment(
                               ArrayRef<BlockContentComment *> Blocks) {
-  return new (Allocator) FullComment(Blocks);
+  return new (Allocator) FullComment(Blocks, ThisDeclInfo);
 }
 
 void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
@@ -467,80 +472,30 @@
 }
 
 bool Sema::isFunctionDecl() {
-  if (!IsThisDeclInspected)
+  if (!ThisDeclInfo)
+    return false;
+  if (!ThisDeclInfo->IsFilled)
     inspectThisDecl();
-  return IsFunctionDecl;
+  return ThisDeclInfo->IsFunctionDecl;
 }
 
 bool Sema::isTemplateDecl() {
-  if (!IsThisDeclInspected)
+  if (!ThisDeclInfo)
+    return false;
+  if (!ThisDeclInfo->IsFilled)
     inspectThisDecl();
-  return IsTemplateDecl;
+  return ThisDeclInfo->IsTemplateDecl;
 }
 
 ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
-  if (!IsThisDeclInspected)
+  if (!ThisDeclInfo->IsFilled)
     inspectThisDecl();
-  return ParamVars;
+  return ThisDeclInfo->ParamVars;
 }
 
 void Sema::inspectThisDecl() {
-  assert(!IsThisDeclInspected);
-  if (!ThisDecl) {
-    IsFunctionDecl = false;
-    IsTemplateDecl = false;
-    ParamVars = ArrayRef<const ParmVarDecl *>();
-    TemplateParameters = NULL;
-  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
-    IsFunctionDecl = true;
-    IsTemplateDecl = false;
-    ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
-                                              FD->getNumParams());
-    TemplateParameters = NULL;
-    unsigned NumLists = FD->getNumTemplateParameterLists();
-    if (NumLists != 0) {
-      IsTemplateDecl = true;
-      TemplateParameters = FD->getTemplateParameterList(NumLists - 1);
-    }
-  } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
-    IsFunctionDecl = true;
-    IsTemplateDecl = false;
-    ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
-                                              MD->param_size());
-    TemplateParameters = NULL;
-  } else if (const FunctionTemplateDecl *FTD =
-                 dyn_cast<FunctionTemplateDecl>(ThisDecl)) {
-    IsFunctionDecl = true;
-    IsTemplateDecl = true;
-    const FunctionDecl *FD = FTD->getTemplatedDecl();
-    ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
-                                              FD->getNumParams());
-    TemplateParameters = FTD->getTemplateParameters();
-  } else if (const ClassTemplateDecl *CTD =
-                 dyn_cast<ClassTemplateDecl>(ThisDecl)) {
-    IsFunctionDecl = false;
-    IsTemplateDecl = true;
-    ParamVars = ArrayRef<const ParmVarDecl *>();
-    TemplateParameters = CTD->getTemplateParameters();
-  } else if (const ClassTemplatePartialSpecializationDecl *CTPSD =
-                 dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) {
-    IsFunctionDecl = false;
-    IsTemplateDecl = true;
-    ParamVars = ArrayRef<const ParmVarDecl *>();
-    TemplateParameters = CTPSD->getTemplateParameters();
-  } else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) {
-    IsFunctionDecl = false;
-    IsTemplateDecl = true;
-    ParamVars = ArrayRef<const ParmVarDecl *>();
-    TemplateParameters = NULL;
-  } else {
-    IsFunctionDecl = false;
-    IsTemplateDecl = false;
-    ParamVars = ArrayRef<const ParmVarDecl *>();
-    TemplateParameters = NULL;
-  }
-  ParamVarDocs.resize(ParamVars.size(), NULL);
-  IsThisDeclInspected = true;
+  ThisDeclInfo->fill();
+  ParamVarDocs.resize(ThisDeclInfo->ParamVars.size(), NULL);
 }
 
 unsigned Sema::resolveParmVarReference(StringRef Name,