From: Dmitri Gribenko Date: Thu, 16 Aug 2012 18:19:43 +0000 (+0000) Subject: Attaching comments to declarations: parse the comment in context of the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1599eac40a3b28de0824013dc2fb90551dfa01b0;p=clang Attaching comments to declarations: parse the comment in context of the declaration it was attached to. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162033 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7b44d10f64..cad3ad2b5f 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -474,8 +474,17 @@ public: Data.setPointer(RC); } + const Decl *getOriginalDecl() const LLVM_READONLY { + return OriginalDecl; + } + + void setOriginalDecl(const Decl *Orig) { + OriginalDecl = Orig; + } + private: llvm::PointerIntPair Data; + const Decl *OriginalDecl; }; /// \brief Mapping from declarations to comments attached to any @@ -504,7 +513,12 @@ public: /// \brief Return the documentation comment attached to a given declaration. /// Returns NULL if no comment is attached. - const RawComment *getRawCommentForAnyRedecl(const Decl *D) const; + /// + /// \param OriginalDecl if not NULL, is set to declaration AST node that had + /// the comment, if the comment we found comes from a redeclaration. + const RawComment *getRawCommentForAnyRedecl( + const Decl *D, + const Decl **OriginalDecl = NULL) const; /// Return parsed documentation comment attached to a given declaration. /// Returns NULL if no comment is attached. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d12effcd3c..c02132329e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -209,7 +209,9 @@ const Decl *adjustDeclToTemplate(const Decl *D) { } } // unnamed namespace -const RawComment *ASTContext::getRawCommentForAnyRedecl(const Decl *D) const { +const RawComment *ASTContext::getRawCommentForAnyRedecl( + const Decl *D, + const Decl **OriginalDecl) const { D = adjustDeclToTemplate(D); // Check whether we have cached a comment for this declaration already. @@ -218,13 +220,17 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(const Decl *D) const { RedeclComments.find(D); if (Pos != RedeclComments.end()) { const RawCommentAndCacheFlags &Raw = Pos->second; - if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) + if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { + if (OriginalDecl) + *OriginalDecl = Raw.getOriginalDecl(); return Raw.getRaw(); + } } } // Search for comments attached to declarations in the redeclaration chain. const RawComment *RC = NULL; + const Decl *OriginalDeclForRC = NULL; for (Decl::redecl_iterator I = D->redecls_begin(), E = D->redecls_end(); I != E; ++I) { @@ -234,16 +240,19 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(const Decl *D) const { const RawCommentAndCacheFlags &Raw = Pos->second; if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { RC = Raw.getRaw(); + OriginalDeclForRC = Raw.getOriginalDecl(); break; } } else { RC = getRawCommentForDeclNoCache(*I); + OriginalDeclForRC = *I; RawCommentAndCacheFlags Raw; if (RC) { Raw.setRaw(RC); Raw.setKind(RawCommentAndCacheFlags::FromDecl); } else Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl); + Raw.setOriginalDecl(*I); RedeclComments[*I] = Raw; if (RC) break; @@ -253,10 +262,14 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(const Decl *D) const { // If we found a comment, it should be a documentation comment. assert(!RC || RC->isDocumentation()); + if (OriginalDecl) + *OriginalDecl = OriginalDeclForRC; + // Update cache for every declaration in the redeclaration chain. RawCommentAndCacheFlags Raw; Raw.setRaw(RC); Raw.setKind(RawCommentAndCacheFlags::FromRedecl); + Raw.setOriginalDecl(OriginalDeclForRC); for (Decl::redecl_iterator I = D->redecls_begin(), E = D->redecls_end(); @@ -277,10 +290,14 @@ comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const { if (Pos != ParsedComments.end()) return Pos->second; - const RawComment *RC = getRawCommentForAnyRedecl(D); + const Decl *OriginalDecl; + const RawComment *RC = getRawCommentForAnyRedecl(D, &OriginalDecl); if (!RC) return NULL; + if (D != OriginalDecl) + return getCommentForDecl(OriginalDecl); + comments::FullComment *FC = RC->parse(*this, D); ParsedComments[Canonical] = FC; return FC; diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp index a361d57baa..d99520b673 100644 --- a/test/Sema/warn-documentation.cpp +++ b/test/Sema/warn-documentation.cpp @@ -641,6 +641,22 @@ void test_attach37::test_attach38(int aaa, int bbb) {} template void test_attach37::test_attach39(int aaa, int bbb) {} +// We used to emit warning that parameter 'a' is not found because we parsed +// the comment in context of the redeclaration which does not have parameter +// names. +template +struct test_attach38 { + /*! + \param a First param + \param b Second param + */ + template + void test_attach39(T a, B b); +}; + +template <> +template +void test_attach38::test_attach39(int, B); // PR13411, reduced. We used to crash on this.