Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -791,6 +791,11 @@ Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc); } + /// \brief Return the RawComment attached to a given declaration, if present. + /// Does not check redeclarations or bases. + /// Returns nullptr if no comment is attached. + const RawComment *getRawCommentForDecl(const Decl *D) const; + /// \brief Return the documentation comment attached to a given declaration. /// Returns nullptr if no comment is attached. /// @@ -806,13 +811,13 @@ /// /// \param PP the Preprocessor used with this TU. Could be nullptr if /// preprocessor is not available. - comments::FullComment *getCommentForDecl(const Decl *D, - const Preprocessor *PP) const; + comments::FullComment * + getParsedCommentForAnyRedecl(const Decl *D, const Preprocessor *PP) const; - /// Return parsed documentation comment attached to a given declaration. - /// Returns nullptr if no comment is attached. Does not look at any - /// redeclarations of the declaration. - comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const; + /// \brief Return parsed documentation comment attached to a given + /// declaration, and not update the cache. Returns nullptr if no comment + /// is attached. Does not look at any redeclarations of the declaration. + comments::FullComment *getParsedCommentForDeclUncached(const Decl *D) const; comments::FullComment *cloneFullComment(comments::FullComment *FC, const Decl *D) const; Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -407,6 +407,20 @@ return Raw; } +const RawComment * +ASTContext::getRawCommentForDecl(const Decl *D) const { + const RawCommentAndCacheFlags &Raw = getRawCommentForDeclCached(D); + const RawComment *RC = Raw.getRaw(); + if (RC) { + // Make sure this cache entry wasn't updated by getRawCommentForAnyRedecl. + if (Raw.getOriginalDecl() != D) + return nullptr; + return RC; + } + assert(Raw.getKind() == RawCommentAndCacheFlags::NoCommentInDecl); + return nullptr; +} + const RawComment * ASTContext::getRawCommentForAnyRedecl(const Decl *D, const Decl **OriginalDecl) const { @@ -483,14 +497,15 @@ return CFC; } -comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const { +comments::FullComment * +ASTContext::getParsedCommentForDeclUncached(const Decl *D) const { const RawComment *RC = getRawCommentForDeclNoCache(D); return RC ? RC->parse(*this, nullptr, D) : nullptr; } comments::FullComment * -ASTContext::getCommentForDecl(const Decl *D, - const Preprocessor *PP) const { +ASTContext::getParsedCommentForAnyRedecl(const Decl *D, + const Preprocessor *PP) const { if (D->isInvalidDecl()) return nullptr; D = adjustDeclToTemplate(D); @@ -517,13 +532,15 @@ const ObjCMethodDecl *OMD = dyn_cast(D); if (OMD && OMD->isPropertyAccessor()) if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) - if (comments::FullComment *FC = getCommentForDecl(PDecl, PP)) + if (comments::FullComment *FC = + getParsedCommentForAnyRedecl(PDecl, PP)) return cloneFullComment(FC, D); if (OMD) addRedeclaredMethods(OMD, Overridden); getOverriddenMethods(dyn_cast(D), Overridden); for (unsigned i = 0, e = Overridden.size(); i < e; i++) - if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) + if (comments::FullComment *FC = + getParsedCommentForAnyRedecl(Overridden[i], PP)) return cloneFullComment(FC, D); } else if (const TypedefNameDecl *TD = dyn_cast(D)) { @@ -532,19 +549,19 @@ QualType QT = TD->getUnderlyingType(); if (const TagType *TT = QT->getAs()) if (const Decl *TD = TT->getDecl()) - if (comments::FullComment *FC = getCommentForDecl(TD, PP)) + if (comments::FullComment *FC = getParsedCommentForAnyRedecl(TD, PP)) return cloneFullComment(FC, D); } else if (const ObjCInterfaceDecl *IC = dyn_cast(D)) { while (IC->getSuperClass()) { IC = IC->getSuperClass(); - if (comments::FullComment *FC = getCommentForDecl(IC, PP)) + if (comments::FullComment *FC = getParsedCommentForAnyRedecl(IC, PP)) return cloneFullComment(FC, D); } } else if (const ObjCCategoryDecl *CD = dyn_cast(D)) { if (const ObjCInterfaceDecl *IC = CD->getClassInterface()) - if (comments::FullComment *FC = getCommentForDecl(IC, PP)) + if (comments::FullComment *FC = getParsedCommentForAnyRedecl(IC, PP)) return cloneFullComment(FC, D); } else if (const CXXRecordDecl *RD = dyn_cast(D)) { @@ -560,8 +577,9 @@ if (const CXXRecordDecl *NonVirtualBase = Ty->getAsCXXRecordDecl()) { if (!(NonVirtualBase= NonVirtualBase->getDefinition())) continue; - - if (comments::FullComment *FC = getCommentForDecl((NonVirtualBase), PP)) + + if (comments::FullComment *FC = + getParsedCommentForAnyRedecl((NonVirtualBase), PP)) return cloneFullComment(FC, D); } } @@ -575,7 +593,8 @@ if (const CXXRecordDecl *VirtualBase = Ty->getAsCXXRecordDecl()) { if (!(VirtualBase= VirtualBase->getDefinition())) continue; - if (comments::FullComment *FC = getCommentForDecl((VirtualBase), PP)) + if (comments::FullComment *FC = + getParsedCommentForAnyRedecl((VirtualBase), PP)) return cloneFullComment(FC, D); } } @@ -588,7 +607,7 @@ // because comments can contain references to parameter names which can be // different across redeclarations. if (D != OriginalDecl) - return getCommentForDecl(OriginalDecl, PP); + return getParsedCommentForAnyRedecl(OriginalDecl, PP); comments::FullComment *FC = RC->parse(*this, PP, D); ParsedComments[Canonical] = FC; Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -1078,7 +1078,7 @@ dumpAttr(*I); if (const FullComment *Comment = - D->getASTContext().getLocalCommentForDeclUncached(D)) + D->getASTContext().getParsedCommentForDeclUncached(D)) dumpFullComment(Comment); // Decls within functions are visited by the body. Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -11915,7 +11915,7 @@ // the lookahead in the lexer: we've consumed the semicolon and looked // ahead through comments. for (unsigned i = 0, e = Group.size(); i != e; ++i) - Context.getCommentForDecl(Group[i], &PP); + Context.getParsedCommentForAnyRedecl(Group[i], &PP); } } Index: tools/libclang/CXComment.cpp =================================================================== --- tools/libclang/CXComment.cpp +++ tools/libclang/CXComment.cpp @@ -34,7 +34,8 @@ const Decl *D = getCursorDecl(C); const ASTContext &Context = getCursorContext(C); - const FullComment *FC = Context.getCommentForDecl(D, /*PP=*/nullptr); + const FullComment *FC = + Context.getParsedCommentForAnyRedecl(D, /*PP=*/nullptr); return createCXComment(FC, getCursorTU(C)); } @@ -403,4 +404,3 @@ ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext()); return cxstring::createDup(XML.str()); } -