aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitri Gribenko <gribozavr@gmail.com>2012-07-11 21:38:39 +0000
committerDmitri Gribenko <gribozavr@gmail.com>2012-07-11 21:38:39 +0000
commita5ef44ff5d93a3be6ca67782828157a71894cf0c (patch)
treef19f1a744483b5cfef3a471957125fa76b7ed36a
parentff398965a5abfaf5bc47bc022876f56a28e5b9a7 (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
-rw-r--r--include/clang/AST/ASTContext.h11
-rw-r--r--include/clang/AST/Comment.h74
-rw-r--r--include/clang/AST/CommentDiagnostic.h29
-rw-r--r--include/clang/AST/CommentLexer.h1
-rw-r--r--include/clang/AST/CommentParser.h16
-rw-r--r--include/clang/AST/CommentSema.h55
-rw-r--r--include/clang/AST/RawCommentList.h13
-rw-r--r--include/clang/Basic/AllDiagnostics.h1
-rw-r--r--include/clang/Basic/CMakeLists.txt1
-rw-r--r--include/clang/Basic/Diagnostic.td1
-rw-r--r--include/clang/Basic/DiagnosticCommentKinds.td70
-rw-r--r--include/clang/Basic/DiagnosticGroups.td4
-rw-r--r--include/clang/Basic/DiagnosticIDs.h3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Basic/Makefile1
-rw-r--r--include/clang/Sema/Sema.h6
-rw-r--r--lib/AST/ASTContext.cpp12
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/Comment.cpp32
-rw-r--r--lib/AST/CommentDumper.cpp14
-rw-r--r--lib/AST/CommentLexer.cpp14
-rw-r--r--lib/AST/CommentParser.cpp98
-rw-r--r--lib/AST/CommentSema.cpp314
-rw-r--r--lib/AST/RawCommentList.cpp2
-rw-r--r--lib/Basic/DiagnosticIDs.cpp1
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/SemaDecl.cpp54
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaDeclObjC.cpp4
-rw-r--r--test/Sema/doxygen-comments.c14
-rw-r--r--test/Sema/warn-documentation-almost-trailing.c14
-rw-r--r--test/Sema/warn-documentation-fixits.c12
-rw-r--r--test/Sema/warn-documentation.cpp272
-rw-r--r--test/Sema/warn-documentation.m24
-rw-r--r--tools/diagtool/DiagnosticNames.cpp1
-rw-r--r--unittests/AST/CommentLexer.cpp61
-rw-r--r--unittests/AST/CommentParser.cpp59
-rw-r--r--unittests/AST/Makefile2
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