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
/// \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.
}
} // 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.
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) {
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;
// 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();
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;
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.