diff options
author | Dmitri Gribenko <gribozavr@gmail.com> | 2012-08-16 18:19:43 +0000 |
---|---|---|
committer | Dmitri Gribenko <gribozavr@gmail.com> | 2012-08-16 18:19:43 +0000 |
commit | 1599eac40a3b28de0824013dc2fb90551dfa01b0 (patch) | |
tree | 1da207820664fe5e46d1d8664c84518ca12fb00d | |
parent | 27762243921cd0b8105b7ee5b7c614590363082f (diff) |
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
-rw-r--r-- | include/clang/AST/ASTContext.h | 16 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 23 | ||||
-rw-r--r-- | test/Sema/warn-documentation.cpp | 16 |
3 files changed, 51 insertions, 4 deletions
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<const RawComment *, 2, Kind> 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<int>::test_attach38(int aaa, int bbb) {} template<typename T> void test_attach37<T>::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 <typename T> +struct test_attach38 { + /*! + \param a First param + \param b Second param + */ + template <typename B> + void test_attach39(T a, B b); +}; + +template <> +template <typename B> +void test_attach38<int>::test_attach39(int, B); // PR13411, reduced. We used to crash on this. |