diff options
author | Dmitri Gribenko <gribozavr@gmail.com> | 2012-07-11 21:38:39 +0000 |
---|---|---|
committer | Dmitri Gribenko <gribozavr@gmail.com> | 2012-07-11 21:38:39 +0000 |
commit | a5ef44ff5d93a3be6ca67782828157a71894cf0c (patch) | |
tree | f19f1a744483b5cfef3a471957125fa76b7ed36a | |
parent | ff398965a5abfaf5bc47bc022876f56a28e5b9a7 (diff) |
Enable comment parsing and semantic analysis to emit diagnostics. A few
diagnostics implemented -- see testcases.
I created a new TableGen file for comment diagnostics,
DiagnosticCommentKinds.td, because comment diagnostics don't logically
fit into AST diagnostics file. But I don't feel strongly about it.
This also implements support for self-closing HTML tags in comment
lexer and parser (for example, <br />).
In order to issue precise diagnostics CommentSema needs to know the
declaration the comment is attached to. There is no easy way to find a decl by
comment, so we match comments and decls in lockstep: after parsing one
declgroup we check if we have any new, not yet attached comments. If we do --
then we do the usual comment-finding process.
It is interesting that this automatically handles trailing comments.
We pick up not only comments that precede the declaration, but also
comments that *follow* the declaration -- thanks to the lookahead in
the lexer: after parsing the declgroup we've consumed the semicolon
and looked ahead through comments.
Added -Wdocumentation-html flag for semantic HTML errors to allow the user to
disable only HTML warnings (but not HTML parse errors, which we emit as
warnings in -Wdocumentation).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160078 91177308-0d34-0410-b5e6-96231b3b80d8
38 files changed, 1147 insertions, 149 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 4dc0a447bd..5283d6dadc 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -392,6 +392,11 @@ public: SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } + + llvm::BumpPtrAllocator &getAllocator() const { + return BumpAlloc; + } + void *Allocate(unsigned Size, unsigned Align = 8) const { return BumpAlloc.Allocate(Size, Align); } @@ -436,9 +441,13 @@ public: /// \brief Return the documentation comment attached to a given declaration, /// without looking into cache. - const RawComment *getRawCommentForDeclNoCache(const Decl *D) const; + RawComment *getRawCommentForDeclNoCache(const Decl *D) const; public: + RawCommentList &getRawCommentList() { + return Comments; + } + void addComment(const RawComment &RC) { Comments.addComment(RC, BumpAlloc); } diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index e631f38b05..16719dfd23 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -50,6 +50,16 @@ protected: }; enum { NumInlineContentCommentBitfields = 9 }; + class HTMLOpenTagCommentBitfields { + friend class HTMLOpenTagComment; + + unsigned : NumInlineContentCommentBitfields; + + /// True if this tag is self-closing (e. g., <br />). This is based on tag + /// spelling in comment (plain <br> would not set this flag). + unsigned IsSelfClosing : 1; + }; + class ParamCommandCommentBitfields { friend class ParamCommandComment; @@ -66,6 +76,7 @@ protected: union { CommentBitfields CommentBits; InlineContentCommentBitfields InlineContentCommentBits; + HTMLOpenTagCommentBitfields HTMLOpenTagCommentBits; ParamCommandCommentBitfields ParamCommandCommentBits; }; @@ -107,8 +118,6 @@ public: static bool classof(const Comment *) { return true; } - typedef Comment * const *child_iterator; - SourceRange getSourceRange() const LLVM_READONLY { return Range; } SourceLocation getLocStart() const LLVM_READONLY { @@ -121,9 +130,13 @@ public: SourceLocation getLocation() const LLVM_READONLY { return Loc; } + typedef Comment * const *child_iterator; + child_iterator child_begin() const; child_iterator child_end() const; + // TODO: const child iterator + unsigned child_count() const { return child_end() - child_begin(); } @@ -180,6 +193,8 @@ public: child_iterator child_end() const { return NULL; } StringRef getText() const LLVM_READONLY { return Text; } + + bool isWhitespace() const; }; /// A command with word-like arguments that is considered inline content. @@ -325,8 +340,9 @@ public: LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), TagName, LocBegin.getLocWithOffset(1), - LocBegin.getLocWithOffset(1 + TagName.size())) - { } + LocBegin.getLocWithOffset(1 + TagName.size())) { + HTMLOpenTagCommentBits.IsSelfClosing = false; + } static bool classof(const Comment *C) { return C->getCommentKind() == HTMLOpenTagCommentKind; @@ -362,6 +378,14 @@ public: void setGreaterLoc(SourceLocation GreaterLoc) { Range.setEnd(GreaterLoc); } + + bool isSelfClosing() const { + return HTMLOpenTagCommentBits.IsSelfClosing; + } + + void setSelfClosing() { + HTMLOpenTagCommentBits.IsSelfClosing = true; + } }; /// A closing HTML tag. @@ -438,6 +462,8 @@ public: child_iterator child_end() const { return reinterpret_cast<child_iterator>(Content.end()); } + + bool isWhitespace() const; }; /// A command that has zero or more word-like arguments (number of word-like @@ -520,6 +546,11 @@ public: void setArgs(llvm::ArrayRef<Argument> A) { Args = A; + if (Args.size() > 0) { + SourceLocation NewLocEnd = Args.back().Range.getEnd(); + if (NewLocEnd.isValid()) + setSourceRange(SourceRange(getLocStart(), NewLocEnd)); + } } ParagraphComment *getParagraph() const LLVM_READONLY { @@ -536,18 +567,18 @@ public: /// Doxygen \\param command. class ParamCommandComment : public BlockCommandComment { -public: - enum PassDirection { - In, - Out, - InOut - }; +private: + /// Parameter index in the function declaration. + unsigned ParamIndex; public: + enum { InvalidParamIndex = ~0U }; + ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Name) : - BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name) { + BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name), + ParamIndex(InvalidParamIndex) { ParamCommandCommentBits.Direction = In; ParamCommandCommentBits.IsDirectionExplicit = false; } @@ -558,6 +589,14 @@ public: static bool classof(const ParamCommandComment *) { return true; } + enum PassDirection { + In, + Out, + InOut + }; + + static const char *getDirectionAsString(PassDirection D); + PassDirection getDirection() const LLVM_READONLY { return static_cast<PassDirection>(ParamCommandCommentBits.Direction); } @@ -582,6 +621,19 @@ public: SourceRange getParamNameRange() const { return Args[0].Range; } + + bool isParamIndexValid() const LLVM_READONLY { + return ParamIndex != InvalidParamIndex; + } + + unsigned getParamIndex() const LLVM_READONLY { + return ParamIndex; + } + + void setParamIndex(unsigned Index) { + ParamIndex = Index; + assert(isParamIndexValid()); + } }; /// A line of text contained in a verbatim block. diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h new file mode 100644 index 0000000000..6e89410579 --- /dev/null +++ b/include/clang/AST/CommentDiagnostic.h @@ -0,0 +1,29 @@ +//===--- CommentDiagnostic.h - Diagnostics for the AST library --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H +#define LLVM_CLANG_COMMENTDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, +#define COMMENTSTART +#include "clang/Basic/DiagnosticCommentKinds.inc" +#undef DIAG + NUM_BUILTIN_COMMENT_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index 6683788227..1ff793701d 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -43,6 +43,7 @@ enum TokenKind { html_equals, // = html_quoted_string, // "blah\"blah" or 'blah\'blah' html_greater, // > + html_slash_greater, // /> html_tag_close // </tag }; } // end namespace tok diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index e75d7978b7..d78705a808 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -14,12 +14,15 @@ #ifndef LLVM_CLANG_AST_COMMENT_PARSER_H #define LLVM_CLANG_AST_COMMENT_PARSER_H +#include "clang/Basic/Diagnostic.h" #include "clang/AST/CommentLexer.h" #include "clang/AST/Comment.h" #include "clang/AST/CommentSema.h" #include "llvm/Support/Allocator.h" namespace clang { +class SourceManager; + namespace comments { /// Doxygen comment parser. @@ -28,8 +31,12 @@ class Parser { Sema &S; + /// Allocator for anything that goes into AST nodes. llvm::BumpPtrAllocator &Allocator; + /// Source manager for the comment being parsed. + const SourceManager &SourceMgr; + template<typename T> ArrayRef<T> copyArray(ArrayRef<T> Source) { size_t Size = Source.size(); @@ -41,6 +48,12 @@ class Parser { return llvm::makeArrayRef(static_cast<T *>(NULL), 0); } + DiagnosticsEngine &Diags; + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + return Diags.Report(Loc, DiagID); + } + /// Current lookahead token. We can safely assume that all tokens are from /// a single source file. Token Tok; @@ -79,7 +92,8 @@ class Parser { } public: - Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator); + Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, + const SourceManager &SourceMgr, DiagnosticsEngine &Diags); /// Parse arguments for \\param command. ParamCommandComment *parseParamCommandArgs( diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 4d853eb086..7b45320f6b 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_COMMENT_SEMA_H #define LLVM_CLANG_AST_COMMENT_SEMA_H +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/AST/Comment.h" #include "llvm/ADT/ArrayRef.h" @@ -21,13 +22,37 @@ #include "llvm/Support/Allocator.h" namespace clang { +class Decl; +class FunctionDecl; +class ParmVarDecl; +class SourceMgr; + namespace comments { class Sema { + /// Allocator for AST nodes. llvm::BumpPtrAllocator &Allocator; + /// Source manager for the comment being parsed. + const SourceManager &SourceMgr; + + DiagnosticsEngine &Diags; + + const Decl *ThisDecl; + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + return Diags.Report(Loc, DiagID); + } + + /// A stack of HTML tags that are currently open (not matched with closing + /// tags). + SmallVector<HTMLOpenTagComment *, 8> HTMLOpenTags; + public: - Sema(llvm::BumpPtrAllocator &Allocator); + Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, + DiagnosticsEngine &Diags); + + void setDecl(const Decl *D); ParagraphComment *actOnParagraphComment( ArrayRef<InlineContentComment *> Content); @@ -47,11 +72,17 @@ public: SourceLocation LocEnd, StringRef Name); - ParamCommandComment *actOnParamCommandArg(ParamCommandComment *Command, + ParamCommandComment *actOnParamCommandDirectionArg( + ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, - StringRef Arg, - bool IsDirection); + StringRef Arg); + + ParamCommandComment *actOnParamCommandParamNameArg( + ParamCommandComment *Command, + SourceLocation ArgLocBegin, + SourceLocation ArgLocEnd, + StringRef Arg); ParamCommandComment *actOnParamCommandFinish(ParamCommandComment *Command, ParagraphComment *Paragraph); @@ -98,7 +129,8 @@ public: HTMLOpenTagComment *actOnHTMLOpenTagFinish( HTMLOpenTagComment *Tag, ArrayRef<HTMLOpenTagComment::Attribute> Attrs, - SourceLocation GreaterLoc); + SourceLocation GreaterLoc, + bool IsSelfClosing); HTMLCloseTagComment *actOnHTMLCloseTag(SourceLocation LocBegin, SourceLocation LocEnd, @@ -106,6 +138,19 @@ public: FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks); + void checkBlockCommandEmptyParagraph(BlockCommandComment *Command); + + /// Returns index of a function parameter with a given name. + unsigned resolveParmVarReference(StringRef Name, + const ParmVarDecl * const *ParamVars, + unsigned NumParams); + + /// Returns index of a function parameter with the name closest to a given + /// typo. + unsigned correctTypoInParmVarReference(StringRef Typo, + const ParmVarDecl * const *ParamVars, + unsigned NumParams); + bool isBlockCommand(StringRef Name); bool isParamCommand(StringRef Name); unsigned getBlockCommandNumArgs(StringRef Name); diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 6ef213bdcb..370f4124c1 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -48,6 +48,14 @@ public: return Kind == RCK_Merged; } + bool isAttached() const LLVM_READONLY { + return IsAttached; + } + + void setAttached() { + IsAttached = true; + } + /// Returns true if it is a comment that should be put after a member: /// \code ///< stuff \endcode /// \code //!< stuff \endcode @@ -110,6 +118,9 @@ private: unsigned Kind : 3; + /// True if comment is attached to a declaration in ASTContext. + bool IsAttached : 1; + bool IsTrailingComment : 1; bool IsAlmostTrailingComment : 1; @@ -122,7 +133,7 @@ private: RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, bool IsAlmostTrailingComment) : Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), - IsTrailingComment(IsTrailingComment), + IsAttached(false), IsTrailingComment(IsTrailingComment), IsAlmostTrailingComment(IsAlmostTrailingComment), BeginLineValid(false), EndLineValid(false) { } diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h index 9f4a25543f..7304c8f673 100644 --- a/include/clang/Basic/AllDiagnostics.h +++ b/include/clang/Basic/AllDiagnostics.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_ALL_DIAGNOSTICS_H #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/CommentDiagnostic.h" #include "clang/Analysis/AnalysisDiagnostic.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/FrontendDiagnostic.h" diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 3df88c7c4a..274b94da8e 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -7,6 +7,7 @@ endmacro(clang_diag_gen) clang_diag_gen(Analysis) clang_diag_gen(AST) +clang_diag_gen(Comment) clang_diag_gen(Common) clang_diag_gen(Driver) clang_diag_gen(Frontend) diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td index 109cd0812c..6dfecdcb79 100644 --- a/include/clang/Basic/Diagnostic.td +++ b/include/clang/Basic/Diagnostic.td @@ -88,6 +88,7 @@ class AccessControl { bit AccessControl = 1; } // Definitions for Diagnostics. include "DiagnosticASTKinds.td" include "DiagnosticAnalysisKinds.td" +include "DiagnosticCommentKinds.td" include "DiagnosticCommonKinds.td" include "DiagnosticDriverKinds.td" include "DiagnosticFrontendKinds.td" diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td new file mode 100644 index 0000000000..7500d402df --- /dev/null +++ b/include/clang/Basic/DiagnosticCommentKinds.td @@ -0,0 +1,70 @@ +//==--- DiagnosticCommentKinds.td - diagnostics related to comments -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "Comment" in { +let CategoryName = "Documentation Issue" in { + +// HTML parsing errors. These are under -Wdocumentation to make sure the user +// knows that we didn't parse something as he might expect. + +def warn_doc_html_open_tag_expected_quoted_string : Warning< + "expected quoted string after equals sign">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_html_open_tag_expected_ident_or_greater : Warning< + "HTML opening tag prematurely ended, expected attribute name or '>'">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_html_tag_started_here : Note< + "HTML tag started here">; + +// HTML semantic errors + +def warn_doc_html_close_unbalanced : Warning< + "HTML closing tag does not match any opening tag">, + InGroup<DocumentationHTML>, DefaultIgnore; + +def warn_doc_html_open_close_mismatch : Warning< + "HTML opening tag '%0' closed by '%1'">, + InGroup<DocumentationHTML>, DefaultIgnore; + +def note_doc_html_closing_tag : Note< + "closing tag">; + +// Commands + +def warn_doc_block_command_empty_paragraph : Warning< + "empty paragraph passed to '\\%0' command">, + InGroup<Documentation>, DefaultIgnore; + +// \param command + +def warn_doc_param_invalid_direction : Warning< + "unrecognized parameter passing direction, " + "valid directions are '[in]', '[out]' and '[in,out]'">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_param_spaces_in_direction : Warning< + "whitespace is not allowed in parameter passing direction">, + InGroup<DocumentationPedantic>, DefaultIgnore; + +def warn_doc_param_not_attached_to_a_function_decl : Warning< + "'\\param' command used in a comment that is not attached to " + "a function declaration">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_param_not_found : Warning< + "parameter '%0' not found in the function declaration">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_param_name_suggestion : Note< + "did you mean '%0'?">; + +} // end of documentation issue category +} // end of AST component diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 3382094aef..1cce51ee31 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -57,7 +57,9 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; def : DiagGroup<"div-by-zero">; -def Doxygen : DiagGroup<"doxygen">; +def DocumentationHTML : DiagGroup<"documentation-html">; +def DocumentationPedantic : DiagGroup<"documentation-pedantic">; +def Documentation : DiagGroup<"documentation", [DocumentationHTML]>; def EmptyBody : DiagGroup<"empty-body">; def ExtraTokens : DiagGroup<"extra-tokens">; diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index 148a14eed0..1cf103acde 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -38,7 +38,8 @@ namespace clang { DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, DIAG_START_PARSE = DIAG_START_LEX + 300, DIAG_START_AST = DIAG_START_PARSE + 400, - DIAG_START_SEMA = DIAG_START_AST + 100, + DIAG_START_COMMENT = DIAG_START_AST + 100, + DIAG_START_SEMA = DIAG_START_COMMENT + 100, DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 }; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 52641b86d6..ebbdb8b263 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5704,7 +5704,7 @@ def err_module_private_definition : Error< let CategoryName = "Documentation Issue" in { def warn_not_a_doxygen_trailing_member_comment : Warning< - "not a Doxygen trailing comment">, InGroup<Doxygen>, DefaultIgnore; + "not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore; } // end of documentation issue category } // end of sema component. diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile index 702afac1e6..6a33133252 100644 --- a/include/clang/Basic/Makefile +++ b/include/clang/Basic/Makefile @@ -1,6 +1,7 @@ CLANG_LEVEL := ../../.. BUILT_SOURCES = \ DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \ + DiagnosticCommentKinds.inc \ DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \ DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \ DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \ diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a48cde03ba..6096466f08 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1313,6 +1313,12 @@ public: unsigned NumDecls); DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, bool TypeMayContainAuto = true); + + /// Should be called on all declarations that might have attached + /// documentation comments. + void ActOnDocumentableDecl(Decl *D); + void ActOnDocumentableDecls(Decl **Group, unsigned NumDecls); + void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); void CheckForFunctionRedefinition(FunctionDecl *FD); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a5b624fbec..27e4de926d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -56,7 +56,7 @@ enum FloatingRank { HalfRank, FloatRank, DoubleRank, LongDoubleRank }; -const RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { +RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (!CommentsLoaded && ExternalSource) { ExternalSource->ReadComments(); CommentsLoaded = true; @@ -160,11 +160,13 @@ const RawComment *ASTContext::getRawCommentForDecl(const Decl *D) const { return C.first; } - const RawComment *RC = getRawCommentForDeclNoCache(D); + RawComment *RC = getRawCommentForDeclNoCache(D); // If we found a comment, it should be a documentation comment. assert(!RC || RC->isDocumentation()); DeclComments[D] = RawAndParsedComment(RC, static_cast<comments::FullComment *>(NULL)); + if (RC) + RC->setAttached(); return RC; } @@ -187,8 +189,10 @@ comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const { comments::Lexer L(RC->getSourceRange().getBegin(), comments::CommentOptions(), RawText.begin(), RawText.end()); - comments::Sema S(this->BumpAlloc); - comments::Parser P(L, S, this->BumpAlloc); + comments::Sema S(getAllocator(), getSourceManager(), getDiagnostics()); + S.setDecl(D); + comments::Parser P(L, S |