aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitri Gribenko <gribozavr@gmail.com>2012-08-16 18:19:43 +0000
committerDmitri Gribenko <gribozavr@gmail.com>2012-08-16 18:19:43 +0000
commit1599eac40a3b28de0824013dc2fb90551dfa01b0 (patch)
tree1da207820664fe5e46d1d8664c84518ca12fb00d
parent27762243921cd0b8105b7ee5b7c614590363082f (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.h16
-rw-r--r--lib/AST/ASTContext.cpp23
-rw-r--r--test/Sema/warn-documentation.cpp16
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.