[cfe-commits] r161722 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/RawCommentList.h lib/AST/ASTContext.cpp lib/AST/RawCommentList.cpp lib/Sema/SemaCodeComplete.cpp test/Index/complete-documentation.cpp tools/libclang/CIndex.cpp

Dmitri Gribenko gribozavr at gmail.com
Fri Aug 10 17:51:43 PDT 2012


Author: gribozavr
Date: Fri Aug 10 19:51:43 2012
New Revision: 161722

URL: http://llvm.org/viewvc/llvm-project?rev=161722&view=rev
Log:
Attaching comments to declarations: find comment attached to any redeclaration

Not only look for the comment near the declaration itself, but also walk the
redeclaration chain: the previous declaration might have had a documentation
comment.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/RawCommentList.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/RawCommentList.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-documentation.cpp
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Aug 10 19:51:43 2012
@@ -433,14 +433,57 @@
   /// \brief True if comments are already loaded from ExternalASTSource.
   mutable bool CommentsLoaded;
 
-  typedef std::pair<const RawComment *, comments::FullComment *>
-      RawAndParsedComment;
+  class RawCommentAndCacheFlags {
+  public:
+    enum Kind {
+      /// We searched for a comment attached to the particular declaration, but
+      /// didn't find any.
+      ///
+      /// getRaw() == 0.
+      NoCommentInDecl = 0,
+
+      /// We have found a comment attached to this particular declaration.
+      ///
+      /// getRaw() != 0.
+      FromDecl,
+
+      /// This declaration does not have an attached comment, and we have
+      /// searched the redeclaration chain.
+      ///
+      /// If getRaw() == 0, the whole redeclaration chain does not have any
+      /// comments.
+      ///
+      /// If getRaw() != 0, it is a comment propagated from other
+      /// redeclaration.
+      FromRedecl
+    };
+
+    Kind getKind() const LLVM_READONLY {
+      return Data.getInt();
+    }
+
+    void setKind(Kind K) {
+      Data.setInt(K);
+    }
+
+    const RawComment *getRaw() const LLVM_READONLY {
+      return Data.getPointer();
+    }
+
+    void setRaw(const RawComment *RC) {
+      Data.setPointer(RC);
+    }
+
+  private:
+    llvm::PointerIntPair<const RawComment *, 2, Kind> Data;
+  };
 
-  /// \brief Mapping from declarations to their comments.
+  /// \brief Mapping from declarations to comments attached to any
+  /// redeclaration.
   ///
   /// Raw comments are owned by Comments list.  This mapping is populated
   /// lazily.
-  mutable llvm::DenseMap<const Decl *, RawAndParsedComment> DeclComments;
+  mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
 
   /// \brief Return the documentation comment attached to a given declaration,
   /// without looking into cache.
@@ -457,7 +500,7 @@
 
   /// \brief Return the documentation comment attached to a given declaration.
   /// Returns NULL if no comment is attached.
-  const RawComment *getRawCommentForDecl(const Decl *D) const;
+  const RawComment *getRawCommentForAnyRedecl(const Decl *D) const;
 
   /// Return parsed documentation comment attached to a given declaration.
   /// Returns NULL if no comment is attached.

Modified: cfe/trunk/include/clang/AST/RawCommentList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RawCommentList.h?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RawCommentList.h (original)
+++ cfe/trunk/include/clang/AST/RawCommentList.h Fri Aug 10 19:51:43 2012
@@ -17,6 +17,11 @@
 
 class ASTContext;
 class ASTReader;
+class Decl;
+
+namespace comments {
+  class FullComment;
+} // end namespace comments
 
 class RawComment {
 public:
@@ -48,12 +53,18 @@
     return Kind == RCK_Merged;
   }
 
+  /// Is this comment attached to any declaration?
   bool isAttached() const LLVM_READONLY {
-    return IsAttached;
+    return !DeclOrParsedComment.isNull();
   }
 
-  void setAttached() {
-    IsAttached = true;
+  /// Return the declaration that this comment is attached to.
+  const Decl *getDecl() const;
+
+  /// Set the declaration that this comment is attached to.
+  void setDecl(const Decl *D) {
+    assert(DeclOrParsedComment.isNull());
+    DeclOrParsedComment = D;
   }
 
   /// Returns true if it is a comment that should be put after a member:
@@ -107,20 +118,28 @@
     return extractBriefText(Context);
   }
 
+  /// Returns a \c FullComment AST node, parsing the comment if needed.
+  comments::FullComment *getParsed(const ASTContext &Context) const {
+    if (comments::FullComment *FC =
+            DeclOrParsedComment.dyn_cast<comments::FullComment *>())
+      return FC;
+
+    return parse(Context);
+  }
+
 private:
   SourceRange Range;
 
   mutable StringRef RawText;
   mutable const char *BriefText;
+  mutable llvm::PointerUnion<const Decl *, comments::FullComment *>
+      DeclOrParsedComment;
 
   mutable bool RawTextValid : 1;   ///< True if RawText is valid
   mutable bool BriefTextValid : 1; ///< True if BriefText is valid
 
   unsigned Kind : 3;
 
-  /// True if comment is attached to a declaration in ASTContext.
-  bool IsAttached : 1;
-
   bool IsTrailingComment : 1;
   bool IsAlmostTrailingComment : 1;
 
@@ -133,7 +152,7 @@
   RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
              bool IsAlmostTrailingComment) :
     Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
-    IsAttached(false), IsTrailingComment(IsTrailingComment),
+    IsTrailingComment(IsTrailingComment),
     IsAlmostTrailingComment(IsAlmostTrailingComment),
     BeginLineValid(false), EndLineValid(false)
   { }
@@ -142,6 +161,8 @@
 
   const char *extractBriefText(const ASTContext &Context) const;
 
+  comments::FullComment *parse(const ASTContext &Context) const;
+
   friend class ASTReader;
 };
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Aug 10 19:51:43 2012
@@ -13,11 +13,7 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Comment.h"
 #include "clang/AST/CommentCommandTraits.h"
-#include "clang/AST/CommentLexer.h"
-#include "clang/AST/CommentSema.h"
-#include "clang/AST/CommentParser.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
@@ -149,6 +145,7 @@
         SourceMgr.getLineNumber(DeclLocDecomp.first, DeclLocDecomp.second)
           == SourceMgr.getLineNumber(CommentBeginDecomp.first,
                                      CommentBeginDecomp.second)) {
+      (*Comment)->setDecl(D);
       return *Comment;
     }
   }
@@ -188,59 +185,74 @@
   if (Text.find_first_of(",;{}#@") != StringRef::npos)
     return NULL;
 
+   (*Comment)->setDecl(D);
   return *Comment;
 }
 
-const RawComment *ASTContext::getRawCommentForDecl(const Decl *D) const {
-  // Check whether we have cached a comment string for this declaration
-  // already.
-  llvm::DenseMap<const Decl *, RawAndParsedComment>::iterator Pos
-      = DeclComments.find(D);
-  if (Pos != DeclComments.end()) {
-    RawAndParsedComment C = Pos->second;
-    return C.first;
+const RawComment *ASTContext::getRawCommentForAnyRedecl(const Decl *D) const {
+  // Check whether we have cached a comment for this declaration already.
+  {
+    llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos =
+        RedeclComments.find(D);
+    if (Pos != RedeclComments.end()) {
+      const RawCommentAndCacheFlags &Raw = Pos->second;
+      if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl)
+        return Raw.getRaw();
+    }
+  }
+
+  // Search for comments attached to declarations in the redeclaration chain.
+  const RawComment *RC = NULL;
+  for (Decl::redecl_iterator I = D->redecls_begin(),
+                             E = D->redecls_end();
+       I != E; ++I) {
+    llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos =
+        RedeclComments.find(*I);
+    if (Pos != RedeclComments.end()) {
+      const RawCommentAndCacheFlags &Raw = Pos->second;
+      if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) {
+        RC = Raw.getRaw();
+        break;
+      }
+    } else {
+      RC = getRawCommentForDeclNoCache(*I);
+      RawCommentAndCacheFlags Raw;
+      if (RC) {
+        Raw.setRaw(RC);
+        Raw.setKind(RawCommentAndCacheFlags::FromDecl);
+      } else
+        Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl);
+      RedeclComments[*I] = Raw;
+      if (RC)
+        break;
+    }
   }
 
-  RawComment *RC = getRawCommentForDeclNoCache(D);
   // If we found a comment, it should be a documentation comment.
   assert(!RC || RC->isDocumentation());
-  DeclComments[D] =
-      RawAndParsedComment(RC, static_cast<comments::FullComment *>(NULL));
-  if (RC)
-    RC->setAttached();
+
+  // Update cache for every declaration in the redeclaration chain.
+  RawCommentAndCacheFlags Raw;
+  Raw.setRaw(RC);
+  Raw.setKind(RawCommentAndCacheFlags::FromRedecl);
+
+  for (Decl::redecl_iterator I = D->redecls_begin(),
+                             E = D->redecls_end();
+       I != E; ++I) {
+    RawCommentAndCacheFlags &R = RedeclComments[*I];
+    if (R.getKind() == RawCommentAndCacheFlags::NoCommentInDecl)
+      R = Raw;
+  }
+
   return RC;
 }
 
 comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const {
-  llvm::DenseMap<const Decl *, RawAndParsedComment>::iterator Pos
-      = DeclComments.find(D);
-  const RawComment *RC;
-  if (Pos != DeclComments.end()) {
-    RawAndParsedComment C = Pos->second;
-    if (comments::FullComment *FC = C.second)
-      return FC;
-    RC = C.first;
-  } else
-    RC = getRawCommentForDecl(D);
-
+  const RawComment *RC = getRawCommentForAnyRedecl(D);
   if (!RC)
     return NULL;
 
-  const StringRef RawText = RC->getRawText(SourceMgr);
-  comments::CommandTraits Traits;
-  comments::Lexer L(getAllocator(), Traits,
-                    RC->getSourceRange().getBegin(), comments::CommentOptions(),
-                    RawText.begin(), RawText.end());
-
-  comments::Sema S(getAllocator(), getSourceManager(), getDiagnostics(),
-                   Traits);
-  S.setDecl(D);
-  comments::Parser P(L, S, getAllocator(), getSourceManager(),
-                     getDiagnostics(), Traits);
-
-  comments::FullComment *FC = P.parseFullComment();
-  DeclComments[D].second = FC;
-  return FC;
+  return RC->getParsed(*this);
 }
 
 void 

Modified: cfe/trunk/lib/AST/RawCommentList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RawCommentList.cpp?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RawCommentList.cpp (original)
+++ cfe/trunk/lib/AST/RawCommentList.cpp Fri Aug 10 19:51:43 2012
@@ -9,8 +9,11 @@
 
 #include "clang/AST/RawCommentList.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Comment.h"
 #include "clang/AST/CommentLexer.h"
 #include "clang/AST/CommentBriefParser.h"
+#include "clang/AST/CommentSema.h"
+#include "clang/AST/CommentParser.h"
 #include "clang/AST/CommentCommandTraits.h"
 #include "llvm/ADT/STLExtras.h"
 
@@ -62,7 +65,7 @@
 RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR,
                        bool Merged) :
     Range(SR), RawTextValid(false), BriefTextValid(false),
-    IsAttached(false), IsAlmostTrailingComment(false),
+    IsAlmostTrailingComment(false),
     BeginLineValid(false), EndLineValid(false) {
   // Extract raw comment text, if possible.
   if (SR.getBegin() == SR.getEnd() || getRawText(SourceMgr).empty()) {
@@ -84,6 +87,16 @@
   }
 }
 
+const Decl *RawComment::getDecl() const {
+  if (DeclOrParsedComment.isNull())
+    return NULL;
+
+  if (const Decl *D = DeclOrParsedComment.dyn_cast<const Decl *>())
+    return D;
+
+  return DeclOrParsedComment.get<comments::FullComment *>()->getDecl();
+}
+
 unsigned RawComment::getBeginLine(const SourceManager &SM) const {
   if (BeginLineValid)
     return BeginLine;
@@ -156,6 +169,25 @@
   return BriefTextPtr;
 }
 
+comments::FullComment *RawComment::parse(const ASTContext &Context) const {
+  // Make sure that RawText is valid.
+  getRawText(Context.getSourceManager());
+
+  comments::CommandTraits Traits;
+  comments::Lexer L(Context.getAllocator(), Traits,
+                    getSourceRange().getBegin(), comments::CommentOptions(),
+                    RawText.begin(), RawText.end());
+  comments::Sema S(Context.getAllocator(), Context.getSourceManager(),
+                   Context.getDiagnostics(), Traits);
+  S.setDecl(getDecl());
+  comments::Parser P(L, S, Context.getAllocator(), Context.getSourceManager(),
+                     Context.getDiagnostics(), Traits);
+
+  comments::FullComment *FC = P.parseFullComment();
+  DeclOrParsedComment = FC;
+  return FC;
+}
+
 namespace {
 bool containsOnlyWhitespace(StringRef Str) {
   return Str.find_first_not_of(" \t\f\v\r\n") == StringRef::npos;

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Aug 10 19:51:43 2012
@@ -2543,7 +2543,7 @@
 
   if (IncludeBriefComments) {
     // Add documentation comment, if it exists.
-    if (const RawComment *RC = Ctx.getRawCommentForDecl(ND)) {
+    if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
       Result.addBriefComment(RC->getBriefText(Ctx));
     }
   }

Modified: cfe/trunk/test/Index/complete-documentation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-documentation.cpp?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-documentation.cpp (original)
+++ cfe/trunk/test/Index/complete-documentation.cpp Fri Aug 10 19:51:43 2012
@@ -17,17 +17,35 @@
 namespace T5 {
 }
 
-void test() {
+struct T6 {
+ /// \brief Fff.
+ void T7();
+
+ /// \brief Ggg.
+ void T8();
+};
+
+void T6::T7() {
+}
+
+void test1() {
 
   T2 t2;
-  t2.
+  t2.T4;
+
+  T6 t6;
+  t6.T8();
 }
 
-// RUN: env CINDEXTEST_COMPLETION_BRIEF_COMMENTS=1 c-index-test -code-completion-at=%s:21:1 %s | FileCheck -check-prefix=CC1 %s
+// RUN: env CINDEXTEST_COMPLETION_BRIEF_COMMENTS=1 c-index-test -code-completion-at=%s:32:1 %s | FileCheck -check-prefix=CC1 %s
 // CHECK-CC1: FunctionDecl:{ResultType void}{TypedText T1}{{.*}}(brief comment: Aaa.)
 // CHECK-CC1: ClassDecl:{TypedText T2}{{.*}}(brief comment: Bbb.)
 // CHECK-CC1: Namespace:{TypedText T5}{{.*}}(brief comment: Eee.)
 
-// RUN: env CINDEXTEST_COMPLETION_BRIEF_COMMENTS=1 c-index-test -code-completion-at=%s:23:6 %s | FileCheck -check-prefix=CC2 %s
+// RUN: env CINDEXTEST_COMPLETION_BRIEF_COMMENTS=1 c-index-test -code-completion-at=%s:34:6 %s | FileCheck -check-prefix=CC2 %s
 // CHECK-CC2: CXXMethod:{ResultType void}{TypedText T3}{{.*}}(brief comment: Ccc.)
 // CHECK-CC2: FieldDecl:{ResultType int}{TypedText T4}{{.*}}(brief comment: Ddd.)
+
+// RUN: env CINDEXTEST_COMPLETION_BRIEF_COMMENTS=1 c-index-test -code-completion-at=%s:37:6 %s | FileCheck -check-prefix=CC3 %s
+// CHECK-CC3: CXXMethod:{ResultType void}{TypedText T7}{LeftParen (}{RightParen )} (34) (parent: StructDecl 'T6')(brief comment: Fff.)
+// CHECK-CC3: CXXMethod:{ResultType void}{TypedText T8}{LeftParen (}{RightParen )} (34) (parent: StructDecl 'T6')(brief comment: Ggg.)

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=161722&r1=161721&r2=161722&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Fri Aug 10 19:51:43 2012
@@ -5689,7 +5689,7 @@
 
   const Decl *D = getCursorDecl(C);
   ASTContext &Context = getCursorContext(C);
-  const RawComment *RC = Context.getRawCommentForDecl(D);
+  const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
   if (!RC)
     return clang_getNullRange();
 
@@ -5702,7 +5702,7 @@
 
   const Decl *D = getCursorDecl(C);
   ASTContext &Context = getCursorContext(C);
-  const RawComment *RC = Context.getRawCommentForDecl(D);
+  const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
   StringRef RawText = RC ? RC->getRawText(Context.getSourceManager()) :
                            StringRef();
 
@@ -5717,7 +5717,7 @@
 
   const Decl *D = getCursorDecl(C);
   const ASTContext &Context = getCursorContext(C);
-  const RawComment *RC = Context.getRawCommentForDecl(D);
+  const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
 
   if (RC) {
     StringRef BriefText = RC->getBriefText(Context);





More information about the cfe-commits mailing list