Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -776,6 +776,10 @@ /// without looking into cache. RawComment *getRawCommentForDeclNoCache(const Decl *D) const; + /// \brief Return the documentation comment attached to a given declaration, + /// adding it to the cache if necessary. + RawCommentAndCacheFlags &getRawCommentForDeclCached(const Decl *D) const; + public: RawCommentList &getRawCommentList() { return Comments; @@ -796,7 +800,8 @@ getRawCommentForAnyRedecl(const Decl *D, const Decl **OriginalDecl = nullptr) const; - /// Return parsed documentation comment attached to a given declaration. + /// Return parsed documentation comment attached to a given declaration, its + /// redeclarations, or its bases. /// Returns nullptr if no comment is attached. /// /// \param PP the Preprocessor used with this TU. Could be nullptr if Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -379,53 +379,54 @@ return D; } -const RawComment *ASTContext::getRawCommentForAnyRedecl( - const Decl *D, - const Decl **OriginalDecl) const { +ASTContext::RawCommentAndCacheFlags & +ASTContext::getRawCommentForDeclCached(const Decl *D) const { D = adjustDeclToTemplate(D); // Check whether we have cached a comment for this declaration already. - { - llvm::DenseMap::iterator Pos = - RedeclComments.find(D); - if (Pos != RedeclComments.end()) { - const RawCommentAndCacheFlags &Raw = Pos->second; - if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { - if (OriginalDecl) - *OriginalDecl = Raw.getOriginalDecl(); - return Raw.getRaw(); - } - } + auto ItInserted = RedeclComments.insert({D, RawCommentAndCacheFlags()}); + RawCommentAndCacheFlags& Raw = ItInserted.first->second; + if (!ItInserted.second) + return Raw; + + // 'Raw' is a new entry in the cache. Populate it with any comments for the + // local definition. + Raw.setOriginalDecl(D); + const RawComment *RC = getRawCommentForDeclNoCache(D); + if (!RC) { + Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl); + return Raw; + } + + // If we found a comment, it should be a documentation comment. + assert(RC->isDocumentation() || LangOpts.CommentOpts.ParseAllComments); + // Call order swapped to work around ICE in VS2015 RTM (Release Win32) + // https://connect.microsoft.com/VisualStudio/feedback/details/1741530 + Raw.setKind(RawCommentAndCacheFlags::FromDecl); + Raw.setRaw(RC); + return Raw; +} + +const RawComment * +ASTContext::getRawCommentForAnyRedecl(const Decl *D, + const Decl **OriginalDecl) const { + RawCommentAndCacheFlags &OrigRaw = getRawCommentForDeclCached(D); + if (OrigRaw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { + if (OriginalDecl) + *OriginalDecl = OrigRaw.getOriginalDecl(); + return OrigRaw.getRaw(); } // Search for comments attached to declarations in the redeclaration chain. const RawComment *RC = nullptr; + const Decl *OriginalDeclForRC = nullptr; for (auto I : D->redecls()) { - llvm::DenseMap::iterator Pos = - RedeclComments.find(I); - if (Pos != RedeclComments.end()) { - 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) { - // Call order swapped to work around ICE in VS2015 RTM (Release Win32) - // https://connect.microsoft.com/VisualStudio/feedback/details/1741530 - Raw.setKind(RawCommentAndCacheFlags::FromDecl); - Raw.setRaw(RC); - } else - Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl); - Raw.setOriginalDecl(I); - RedeclComments[I] = Raw; - if (RC) - break; + RawCommentAndCacheFlags &Raw = getRawCommentForDeclCached(I); + if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { + RC = Raw.getRaw(); + OriginalDeclForRC = Raw.getOriginalDecl(); + break; } } @@ -487,9 +488,9 @@ return RC ? RC->parse(*this, nullptr, D) : nullptr; } -comments::FullComment *ASTContext::getCommentForDecl( - const Decl *D, - const Preprocessor *PP) const { +comments::FullComment * +ASTContext::getCommentForDecl(const Decl *D, + const Preprocessor *PP) const { if (D->isInvalidDecl()) return nullptr; D = adjustDeclToTemplate(D);