[cfe-commits] r161087 - in /cfe/trunk: include/clang-c/ include/clang/AST/ include/clang/Basic/ lib/AST/ lib/Sema/ test/Index/ test/Sema/ tools/c-index-test/ tools/libclang/ unittests/AST/
Dmitri Gribenko
gribozavr at gmail.com
Tue Jul 31 15:37:06 PDT 2012
Author: gribozavr
Date: Tue Jul 31 17:37:06 2012
New Revision: 161087
URL: http://llvm.org/viewvc/llvm-project?rev=161087&view=rev
Log:
Comment parsing: add support for \tparam command on all levels.
The only caveat is renumbering CXCommentKind enum for aesthetic reasons -- this
breaks libclang binary compatibility, but should not be a problem since API is
so new.
This also fixes PR13372 as a side-effect.
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/include/clang/AST/Comment.h
cfe/trunk/include/clang/AST/CommentParser.h
cfe/trunk/include/clang/AST/CommentSema.h
cfe/trunk/include/clang/Basic/CommentNodes.td
cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/CommentBriefParser.cpp
cfe/trunk/lib/AST/CommentDumper.cpp
cfe/trunk/lib/AST/CommentParser.cpp
cfe/trunk/lib/AST/CommentSema.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/Index/annotate-comments.cpp
cfe/trunk/test/Sema/warn-documentation.cpp
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CXComment.cpp
cfe/trunk/tools/libclang/libclang.exports
cfe/trunk/unittests/AST/CommentParser.cpp
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue Jul 31 17:37:06 2012
@@ -3277,6 +3277,14 @@
CXComment_ParamCommand = 7,
/**
+ * \brief A \\tparam command that describes a template parameter (name and
+ * description).
+ *
+ * \brief For example: \\tparam T description.
+ */
+ CXComment_TParamCommand = 8,
+
+ /**
* \brief A verbatim block command (e. g., preformatted code). Verbatim
* block has an opening and a closing command and contains multiple lines of
* text (\c CXComment_VerbatimBlockLine child nodes).
@@ -3286,25 +3294,25 @@
* aaa
* \\endverbatim
*/
- CXComment_VerbatimBlockCommand = 8,
+ CXComment_VerbatimBlockCommand = 9,
/**
* \brief A line of text that is contained within a
* CXComment_VerbatimBlockCommand node.
*/
- CXComment_VerbatimBlockLine = 9,
+ CXComment_VerbatimBlockLine = 10,
/**
* \brief A verbatim line command. Verbatim line has an opening command,
* a single line of text (up to the newline after the opening command) and
* has no closing command.
*/
- CXComment_VerbatimLine = 10,
+ CXComment_VerbatimLine = 11,
/**
* \brief A full comment attached to a declaration, contains block content.
*/
- CXComment_FullComment = 11
+ CXComment_FullComment = 12
};
/**
@@ -3564,6 +3572,63 @@
CXComment Comment);
/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns template parameter name.
+ */
+CINDEX_LINKAGE
+CXString clang_TParamCommandComment_getParamName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the template parameter list and
+ * \c clang_TParamCommandComment_getDepth and
+ * \c clang_TParamCommandComment_getIndex functions will return a meaningful
+ * value.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_isParamPositionValid(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based nesting depth of this parameter in the template parameter list.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0,
+ * for T nesting depth is 1.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_getDepth(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based parameter index in the template parameter list at a
+ * given nesting depth.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0, so we can ask for index at depth 0:
+ * at depth 0 C's index is 0, TT's index is 1.
+ *
+ * For T nesting depth is 1, so we can ask for index at depth 0 and 1:
+ * at depth 0 T's index is 1 (same as TT's),
+ * at depth 1 T's index is 0.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_getIndex(CXComment Comment, unsigned Depth);
+
+/**
* \param Comment a \c CXComment_VerbatimBlockLine AST node.
*
* \returns text contained in the AST node.
@@ -3606,6 +3671,15 @@
* \li "param-name-index-invalid" and "param-descr-index-invalid" are used if
* parameter index is invalid.
*
+ * Template parameter documentation is rendered as a \<dl\> list with
+ * parameters sorted in template parameter list order. CSS classes used:
+ * \li "tparam-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "tparam-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "taram-name-index-other" and "tparam-descr-index-other" are used for
+ * names inside template template parameters;
+ * \li "tparam-name-index-invalid" and "tparam-descr-index-invalid" are used if
+ * parameter position is invalid.
+ *
* \param Comment a \c CXComment_FullComment AST node.
*
* \returns string containing an HTML fragment.
Modified: cfe/trunk/include/clang/AST/Comment.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Comment.h?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Comment.h (original)
+++ cfe/trunk/include/clang/AST/Comment.h Tue Jul 31 17:37:06 2012
@@ -723,6 +723,68 @@
}
};
+/// Doxygen \\tparam command, describes a template parameter.
+class TParamCommandComment : public BlockCommandComment {
+private:
+ /// If this template parameter name was resolved (found in template parameter
+ /// list), then this stores a list of position indexes in all template
+ /// parameter lists.
+ ///
+ /// For example:
+ /// \verbatim
+ /// template<typename C, template<typename T> class TT>
+ /// void test(TT<int> aaa);
+ /// \endverbatim
+ /// For C: Position = { 0 }
+ /// For TT: Position = { 1 }
+ /// For T: Position = { 1, 0 }
+ llvm::ArrayRef<unsigned> Position;
+
+public:
+ TParamCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) :
+ BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, Name)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == TParamCommandCommentKind;
+ }
+
+ static bool classof(const TParamCommandComment *) { return true; }
+
+ bool hasParamName() const {
+ return getNumArgs() > 0;
+ }
+
+ StringRef getParamName() const {
+ return Args[0].Text;
+ }
+
+ SourceRange getParamNameRange() const {
+ return Args[0].Range;
+ }
+
+ bool isPositionValid() const LLVM_READONLY {
+ return !Position.empty();
+ }
+
+ unsigned getDepth() const {
+ assert(isPositionValid());
+ return Position.size();
+ }
+
+ unsigned getIndex(unsigned Depth) const {
+ assert(isPositionValid());
+ return Position[Depth];
+ }
+
+ void setPosition(ArrayRef<unsigned> NewPosition) {
+ Position = NewPosition;
+ assert(isPositionValid());
+ }
+};
+
/// A line of text contained in a verbatim block.
class VerbatimBlockLineComment : public Comment {
StringRef Text;
Modified: cfe/trunk/include/clang/AST/CommentParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CommentParser.h?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/CommentParser.h (original)
+++ cfe/trunk/include/clang/AST/CommentParser.h Tue Jul 31 17:37:06 2012
@@ -42,17 +42,6 @@
/// Source manager for the comment being parsed.
const SourceManager &SourceMgr;
- template<typename T>
- ArrayRef<T> copyArray(ArrayRef<T> Source) {
- size_t Size = Source.size();
- if (Size != 0) {
- T *Mem = Allocator.Allocate<T>(Size);
- std::uninitialized_copy(Source.begin(), Source.end(), Mem);
- return llvm::makeArrayRef(Mem, Size);
- } else
- return llvm::makeArrayRef(static_cast<T *>(NULL), 0);
- }
-
DiagnosticsEngine &Diags;
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
@@ -105,6 +94,11 @@
ParamCommandComment *PC,
TextTokenRetokenizer &Retokenizer);
+ /// Parse arguments for \\tparam command.
+ TParamCommandComment *parseTParamCommandArgs(
+ TParamCommandComment *TPC,
+ TextTokenRetokenizer &Retokenizer);
+
BlockCommandComment *parseBlockCommandArgs(
BlockCommandComment *BC,
TextTokenRetokenizer &Retokenizer,
Modified: cfe/trunk/include/clang/AST/CommentSema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CommentSema.h?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/CommentSema.h (original)
+++ cfe/trunk/include/clang/AST/CommentSema.h Tue Jul 31 17:37:06 2012
@@ -19,12 +19,14 @@
#include "clang/AST/Comment.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class Decl;
class FunctionDecl;
class ParmVarDecl;
+class TemplateParameterList;
class SourceMgr;
namespace comments {
@@ -56,6 +58,18 @@
/// true.
llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
+ /// Template parameters that can be referenced by \\tparam if \c ThisDecl is
+ /// a template.
+ ///
+ /// Contains a valid value if \c IsThisDeclInspected is true.
+ const TemplateParameterList *TemplateParameters;
+
+ /// Comment AST nodes that correspond to parameter names in
+ /// \c TemplateParameters.
+ ///
+ /// Contains a valid value if \c IsThisDeclInspected is true.
+ llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
+
/// True if we extracted all important information from \c ThisDecl into
/// \c Sema members.
unsigned IsThisDeclInspected : 1;
@@ -64,6 +78,10 @@
/// Contains a valid value if \c IsThisDeclInspected is true.
unsigned IsFunctionDecl : 1;
+ /// Is \c ThisDecl a template declaration.
+ /// Contains a valid value if \c IsThisDeclInspected is true.
+ unsigned IsTemplateDecl : 1;
+
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
@@ -78,6 +96,18 @@
void setDecl(const Decl *D);
+ /// Returns a copy of array, owned by Sema's allocator.
+ template<typename T>
+ ArrayRef<T> copyArray(ArrayRef<T> Source) {
+ size_t Size = Source.size();
+ if (Size != 0) {
+ T *Mem = Allocator.Allocate<T>(Size);
+ std::uninitialized_copy(Source.begin(), Source.end(), Mem);
+ return llvm::makeArrayRef(Mem, Size);
+ } else
+ return llvm::makeArrayRef(static_cast<T *>(NULL), 0);
+ }
+
ParagraphComment *actOnParagraphComment(
ArrayRef<InlineContentComment *> Content);
@@ -111,6 +141,19 @@
ParamCommandComment *actOnParamCommandFinish(ParamCommandComment *Command,
ParagraphComment *Paragraph);
+ TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name);
+
+ TParamCommandComment *actOnTParamCommandParamNameArg(
+ TParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ TParamCommandComment *actOnTParamCommandFinish(TParamCommandComment *Command,
+ ParagraphComment *Paragraph);
+
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
StringRef CommandName);
@@ -165,6 +208,8 @@
void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
bool isFunctionDecl();
+ bool isTemplateDecl();
+
ArrayRef<const ParmVarDecl *> getParamVars();
/// Extract all important semantic information from \c ThisDecl into
@@ -180,8 +225,17 @@
unsigned correctTypoInParmVarReference(StringRef Typo,
ArrayRef<const ParmVarDecl *> ParamVars);
+ bool resolveTParamReference(StringRef Name,
+ const TemplateParameterList *TemplateParameters,
+ SmallVectorImpl<unsigned> *Position);
+
+ StringRef correctTypoInTParamReference(
+ StringRef Typo,
+ const TemplateParameterList *TemplateParameters);
+
bool isBlockCommand(StringRef Name);
bool isParamCommand(StringRef Name);
+ bool isTParamCommand(StringRef Name);
unsigned getBlockCommandNumArgs(StringRef Name);
bool isInlineCommand(StringRef Name) const;
Modified: cfe/trunk/include/clang/Basic/CommentNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/CommentNodes.td?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/CommentNodes.td (original)
+++ cfe/trunk/include/clang/Basic/CommentNodes.td Tue Jul 31 17:37:06 2012
@@ -17,6 +17,7 @@
def ParagraphComment : DComment<BlockContentComment>;
def BlockCommandComment : DComment<BlockContentComment>;
def ParamCommandComment : DComment<BlockCommandComment>;
+ def TParamCommandComment : DComment<BlockCommandComment>;
def VerbatimBlockComment : DComment<BlockCommandComment>;
def VerbatimLineComment : DComment<BlockCommandComment>;
Modified: cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td Tue Jul 31 17:37:06 2012
@@ -77,5 +77,26 @@
def note_doc_param_name_suggestion : Note<
"did you mean '%0'?">;
+// \tparam command
+
+def warn_doc_tparam_not_attached_to_a_template_decl : Warning<
+ "'\\tparam' command used in a comment that is not attached to "
+ "a template declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_tparam_duplicate : Warning<
+ "template parameter '%0' is already documented">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_tparam_previous : Note<
+ "previous documentation">;
+
+def warn_doc_tparam_not_found : Warning<
+ "template parameter '%0' not found in the template declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_tparam_name_suggestion : Note<
+ "did you mean '%0'?">;
+
} // end of documentation issue category
} // end of AST component
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jul 31 17:37:06 2012
@@ -72,6 +72,13 @@
if (isa<ParmVarDecl>(D))
return NULL;
+ // TODO: we could look up template parameter documentation in the template
+ // documentation.
+ if (isa<TemplateTypeParmDecl>(D) ||
+ isa<NonTypeTemplateParmDecl>(D) ||
+ isa<TemplateTemplateParmDecl>(D))
+ return NULL;
+
ArrayRef<RawComment *> RawComments = Comments.getComments();
// If there are no comments anywhere, we won't find anything.
@@ -86,7 +93,9 @@
// so we use the location of the identifier as the "declaration location".
SourceLocation DeclLoc;
if (isa<ObjCMethodDecl>(D) || isa<ObjCContainerDecl>(D) ||
- isa<ObjCPropertyDecl>(D))
+ isa<ObjCPropertyDecl>(D) ||
+ isa<FunctionTemplateDecl>(D) ||
+ isa<ClassTemplateDecl>(D) || isa<ClassTemplateSpecializationDecl>(D))
DeclLoc = D->getLocStart();
else
DeclLoc = D->getLocation();
Modified: cfe/trunk/lib/AST/CommentBriefParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CommentBriefParser.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CommentBriefParser.cpp (original)
+++ cfe/trunk/lib/AST/CommentBriefParser.cpp Tue Jul 31 17:37:06 2012
@@ -48,6 +48,7 @@
.Case("pre", true)
.Case("post", true)
.Cases("param", "arg", true)
+ .Case("tparam", true)
.Default(false);
}
} // unnamed namespace
Modified: cfe/trunk/lib/AST/CommentDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CommentDumper.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CommentDumper.cpp (original)
+++ cfe/trunk/lib/AST/CommentDumper.cpp Tue Jul 31 17:37:06 2012
@@ -50,6 +50,7 @@
void visitParagraphComment(const ParagraphComment *C);
void visitBlockCommandComment(const BlockCommandComment *C);
void visitParamCommandComment(const ParamCommandComment *C);
+ void visitTParamCommandComment(const TParamCommandComment *C);
void visitVerbatimBlockComment(const VerbatimBlockComment *C);
void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
void visitVerbatimLineComment(const VerbatimLineComment *C);
@@ -176,6 +177,24 @@
OS << " ParamIndex=" << C->getParamIndex();
}
+void CommentDumper::visitTParamCommandComment(const TParamCommandComment *C) {
+ dumpComment(C);
+
+ if (C->hasParamName()) {
+ OS << " Param=\"" << C->getParamName() << "\"";
+ }
+
+ if (C->isPositionValid()) {
+ OS << " Position=<";
+ for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
+ OS << C->getIndex(i);
+ if (i != e - 1)
+ OS << ", ";
+ }
+ OS << ">";
+ }
+}
+
void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
dumpComment(C);
Modified: cfe/trunk/lib/AST/CommentParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CommentParser.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CommentParser.cpp (original)
+++ cfe/trunk/lib/AST/CommentParser.cpp Tue Jul 31 17:37:06 2012
@@ -276,6 +276,19 @@
return PC;
}
+TParamCommandComment *Parser::parseTParamCommandArgs(
+ TParamCommandComment *TPC,
+ TextTokenRetokenizer &Retokenizer) {
+ Token Arg;
+ if (Retokenizer.lexWord(Arg))
+ TPC = S.actOnTParamCommandParamNameArg(TPC,
+ Arg.getLocation(),
+ Arg.getEndLocation(),
+ Arg.getText());
+
+ return TPC;
+}
+
BlockCommandComment *Parser::parseBlockCommandArgs(
BlockCommandComment *BC,
TextTokenRetokenizer &Retokenizer,
@@ -299,14 +312,21 @@
assert(Tok.is(tok::command));
ParamCommandComment *PC;
+ TParamCommandComment *TPC;
BlockCommandComment *BC;
bool IsParam = false;
+ bool IsTParam = false;
unsigned NumArgs = 0;
if (S.isParamCommand(Tok.getCommandName())) {
IsParam = true;
PC = S.actOnParamCommandStart(Tok.getLocation(),
Tok.getEndLocation(),
Tok.getCommandName());
+ } if (S.isTParamCommand(Tok.getCommandName())) {
+ IsTParam = true;
+ TPC = S.actOnTParamCommandStart(Tok.getLocation(),
+ Tok.getEndLocation(),
+ Tok.getCommandName());
} else {
NumArgs = S.getBlockCommandNumArgs(Tok.getCommandName());
BC = S.actOnBlockCommandStart(Tok.getLocation(),
@@ -323,13 +343,15 @@
return S.actOnBlockCommandFinish(IsParam ? PC : BC, Paragraph);
}
- if (IsParam || NumArgs > 0) {
+ if (IsParam || IsTParam || NumArgs > 0) {
// In order to parse command arguments we need to retokenize a few
// following text tokens.
TextTokenRetokenizer Retokenizer(Allocator, *this);
if (IsParam)
PC = parseParamCommandArgs(PC, Retokenizer);
+ else if (IsTParam)
+ TPC = parseTParamCommandArgs(TPC, Retokenizer);
else
BC = parseBlockCommandArgs(BC, Retokenizer, NumArgs);
@@ -341,6 +363,8 @@
// paragraph.
if (IsParam)
return S.actOnParamCommandFinish(PC, cast<ParagraphComment>(Block));
+ else if (IsTParam)
+ return S.actOnTParamCommandFinish(TPC, cast<ParagraphComment>(Block));
else
return S.actOnBlockCommandFinish(BC, cast<ParagraphComment>(Block));
}
@@ -419,7 +443,7 @@
case tok::html_greater:
HST = S.actOnHTMLStartTagFinish(HST,
- copyArray(llvm::makeArrayRef(Attrs)),
+ S.copyArray(llvm::makeArrayRef(Attrs)),
Tok.getLocation(),
/* IsSelfClosing = */ false);
consumeToken();
@@ -427,7 +451,7 @@
case tok::html_slash_greater:
HST = S.actOnHTMLStartTagFinish(HST,
- copyArray(llvm::makeArrayRef(Attrs)),
+ S.copyArray(llvm::makeArrayRef(Attrs)),
Tok.getLocation(),
/* IsSelfClosing = */ true);
consumeToken();
@@ -446,14 +470,14 @@
continue;
return S.actOnHTMLStartTagFinish(HST,
- copyArray(llvm::makeArrayRef(Attrs)),
+ S.copyArray(llvm::makeArrayRef(Attrs)),
SourceLocation(),
/* IsSelfClosing = */ false);
default:
// Not a token from an HTML start tag. Thus HTML tag prematurely ended.
HST = S.actOnHTMLStartTagFinish(HST,
- copyArray(llvm::makeArrayRef(Attrs)),
+ S.copyArray(llvm::makeArrayRef(Attrs)),
SourceLocation(),
/* IsSelfClosing = */ false);
bool StartLineInvalid;
@@ -563,7 +587,7 @@
break;
}
- return S.actOnParagraphComment(copyArray(llvm::makeArrayRef(Content)));
+ return S.actOnParagraphComment(S.copyArray(llvm::makeArrayRef(Content)));
}
VerbatimBlockComment *Parser::parseVerbatimBlock() {
@@ -601,12 +625,12 @@
if (Tok.is(tok::verbatim_block_end)) {
VB = S.actOnVerbatimBlockFinish(VB, Tok.getLocation(),
Tok.getVerbatimBlockName(),
- copyArray(llvm::makeArrayRef(Lines)));
+ S.copyArray(llvm::makeArrayRef(Lines)));
consumeToken();
} else {
// Unterminated \\verbatim block
VB = S.actOnVerbatimBlockFinish(VB, SourceLocation(), "",
- copyArray(llvm::makeArrayRef(Lines)));
+ S.copyArray(llvm::makeArrayRef(Lines)));
}
return VB;
@@ -680,7 +704,7 @@
while (Tok.is(tok::newline))
consumeToken();
}
- return S.actOnFullComment(copyArray(llvm::makeArrayRef(Blocks)));
+ return S.actOnFullComment(S.copyArray(llvm::makeArrayRef(Blocks)));
}
} // end namespace comments
Modified: cfe/trunk/lib/AST/CommentSema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CommentSema.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CommentSema.cpp (original)
+++ cfe/trunk/lib/AST/CommentSema.cpp Tue Jul 31 17:37:06 2012
@@ -11,6 +11,7 @@
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringSwitch.h"
@@ -200,6 +201,90 @@
return Command;
}
+TParamCommandComment *Sema::actOnTParamCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Name) {
+ TParamCommandComment *Command =
+ new (Allocator) TParamCommandComment(LocBegin, LocEnd, Name);
+
+ if (!isTemplateDecl())
+ Diag(Command->getLocation(),
+ diag::warn_doc_tparam_not_attached_to_a_template_decl)
+ << Command->getCommandNameRange();
+
+ return Command;
+}
+
+TParamCommandComment *Sema::actOnTParamCommandParamNameArg(
+ TParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg) {
+ // Parser will not feed us more arguments than needed.
+ assert(Command->getNumArgs() == 0);
+
+ typedef BlockCommandComment::Argument Argument;
+ Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
+ ArgLocEnd),
+ Arg);
+ Command->setArgs(llvm::makeArrayRef(A, 1));
+
+ if (!isTemplateDecl()) {
+ // We already warned that this \\tparam is not attached to a template decl.
+ return Command;
+ }
+
+ SmallVector<unsigned, 2> Position;
+ if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
+ Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
+ llvm::StringMap<TParamCommandComment *>::iterator PrevCommandIt =
+ TemplateParameterDocs.find(Arg);
+ if (PrevCommandIt != TemplateParameterDocs.end()) {
+ SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
+ Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
+ << Arg << ArgRange;
+ TParamCommandComment *PrevCommand = PrevCommandIt->second;
+ Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
+ << PrevCommand->getParamNameRange();
+ }
+ TemplateParameterDocs[Arg] = Command;
+ return Command;
+ }
+
+ SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
+ Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
+ << Arg << ArgRange;
+
+ if (!TemplateParameters || TemplateParameters->size() == 0)
+ return Command;
+
+ StringRef CorrectedName;
+ if (TemplateParameters->size() == 1) {
+ const NamedDecl *Param = TemplateParameters->getParam(0);
+ const IdentifierInfo *II = Param->getIdentifier();
+ if (II)
+ CorrectedName = II->getName();
+ } else {
+ CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
+ }
+
+ if (!CorrectedName.empty()) {
+ Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
+ << CorrectedName
+ << FixItHint::CreateReplacement(ArgRange, CorrectedName);
+ }
+
+ return Command;
+}
+
+TParamCommandComment *Sema::actOnTParamCommandFinish(
+ TParamCommandComment *Command,
+ ParagraphComment *Paragraph) {
+ Command->setParagraph(Paragraph);
+ checkBlockCommandEmptyParagraph(Command);
+ return Command;
+}
+
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
StringRef CommandName) {
@@ -387,6 +472,12 @@
return IsFunctionDecl;
}
+bool Sema::isTemplateDecl() {
+ if (!IsThisDeclInspected)
+ inspectThisDecl();
+ return IsTemplateDecl;
+}
+
ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
if (!IsThisDeclInspected)
inspectThisDecl();
@@ -397,18 +488,56 @@
assert(!IsThisDeclInspected);
if (!ThisDecl) {
IsFunctionDecl = false;
+ IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>();
+ TemplateParameters = NULL;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
IsFunctionDecl = true;
+ IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
FD->getNumParams());
+ TemplateParameters = NULL;
+ unsigned NumLists = FD->getNumTemplateParameterLists();
+ if (NumLists != 0) {
+ IsTemplateDecl = true;
+ TemplateParameters = FD->getTemplateParameterList(NumLists - 1);
+ }
} else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
IsFunctionDecl = true;
+ IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
MD->param_size());
+ TemplateParameters = NULL;
+ } else if (const FunctionTemplateDecl *FTD =
+ dyn_cast<FunctionTemplateDecl>(ThisDecl)) {
+ IsFunctionDecl = true;
+ IsTemplateDecl = true;
+ const FunctionDecl *FD = FTD->getTemplatedDecl();
+ ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
+ FD->getNumParams());
+ TemplateParameters = FTD->getTemplateParameters();
+ } else if (const ClassTemplateDecl *CTD =
+ dyn_cast<ClassTemplateDecl>(ThisDecl)) {
+ IsFunctionDecl = false;
+ IsTemplateDecl = true;
+ ParamVars = ArrayRef<const ParmVarDecl *>();
+ TemplateParameters = CTD->getTemplateParameters();
+ } else if (const ClassTemplatePartialSpecializationDecl *CTPSD =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) {
+ IsFunctionDecl = false;
+ IsTemplateDecl = true;
+ ParamVars = ArrayRef<const ParmVarDecl *>();
+ TemplateParameters = CTPSD->getTemplateParameters();
+ } else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) {
+ IsFunctionDecl = false;
+ IsTemplateDecl = true;
+ ParamVars = ArrayRef<const ParmVarDecl *>();
+ TemplateParameters = NULL;
} else {
IsFunctionDecl = false;
+ IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>();
+ TemplateParameters = NULL;
}
ParamVarDocs.resize(ParamVars.size(), NULL);
IsThisDeclInspected = true;
@@ -424,34 +553,136 @@
return ParamCommandComment::InvalidParamIndex;
}
+namespace {
+class SimpleTypoCorrector {
+ StringRef Typo;
+ const unsigned MaxEditDistance;
+
+ const NamedDecl *BestDecl;
+ unsigned BestEditDistance;
+ unsigned BestIndex;
+ unsigned NextIndex;
+
+public:
+ SimpleTypoCorrector(StringRef Typo) :
+ Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
+ BestDecl(NULL), BestEditDistance(MaxEditDistance + 1),
+ BestIndex(0), NextIndex(0)
+ { }
+
+ void addDecl(const NamedDecl *ND);
+
+ const NamedDecl *getBestDecl() const {
+ if (BestEditDistance > MaxEditDistance)
+ return NULL;
+
+ return BestDecl;
+ }
+
+ unsigned getBestDeclIndex() const {
+ assert(getBestDecl());
+ return BestIndex;
+ }
+};
+
+void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
+ unsigned CurrIndex = NextIndex++;
+
+ const IdentifierInfo *II = ND->getIdentifier();
+ if (!II)
+ return;
+
+ StringRef Name = II->getName();
+ unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
+ if (MinPossibleEditDistance > 0 &&
+ Typo.size() / MinPossibleEditDistance < 3)
+ return;
+
+ unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
+ if (EditDistance < BestEditDistance) {
+ BestEditDistance = EditDistance;
+ BestDecl = ND;
+ BestIndex = CurrIndex;
+ }
+}
+} // unnamed namespace
+
unsigned Sema::correctTypoInParmVarReference(
StringRef Typo,
ArrayRef<const ParmVarDecl *> ParamVars) {
- const unsigned MaxEditDistance = (Typo.size() + 2) / 3;
- unsigned BestPVDIndex = 0;
- unsigned BestEditDistance = MaxEditDistance + 1;
- for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
- const IdentifierInfo *II = ParamVars[i]->getIdentifier();
- if (II) {
- StringRef Name = II->getName();
- unsigned MinPossibleEditDistance =
- abs((int)Name.size() - (int)Typo.size());
- if (MinPossibleEditDistance > 0 &&
- Typo.size() / MinPossibleEditDistance < 3)
- continue;
-
- unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
- if (EditDistance < BestEditDistance) {
- BestEditDistance = EditDistance;
- BestPVDIndex = i;
- }
+ SimpleTypoCorrector Corrector(Typo);
+ for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
+ Corrector.addDecl(ParamVars[i]);
+ if (Corrector.getBestDecl())
+ return Corrector.getBestDeclIndex();
+ else
+ return ParamCommandComment::InvalidParamIndex;;
+}
+
+namespace {
+bool ResolveTParamReferenceHelper(
+ StringRef Name,
+ const TemplateParameterList *TemplateParameters,
+ SmallVectorImpl<unsigned> *Position) {
+ for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
+ const NamedDecl *Param = TemplateParameters->getParam(i);
+ const IdentifierInfo *II = Param->getIdentifier();
+ if (II && II->getName() == Name) {
+ Position->push_back(i);
+ return true;
+ }
+
+ if (const TemplateTemplateParmDecl *TTP =
+ dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ Position->push_back(i);
+ if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
+ Position))
+ return true;
+ Position->pop_back();
}
}
+ return false;
+}
+} // unnamed namespace
- if (BestEditDistance <= MaxEditDistance)
- return BestPVDIndex;
- else
- return ParamCommandComment::InvalidParamIndex;
+bool Sema::resolveTParamReference(
+ StringRef Name,
+ const TemplateParameterList *TemplateParameters,
+ SmallVectorImpl<unsigned> *Position) {
+ Position->clear();
+ if (!TemplateParameters)
+ return false;
+
+ return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
+}
+
+namespace {
+void CorrectTypoInTParamReferenceHelper(
+ const TemplateParameterList *TemplateParameters,
+ SimpleTypoCorrector &Corrector) {
+ for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
+ const NamedDecl *Param = TemplateParameters->getParam(i);
+ Corrector.addDecl(Param);
+
+ if (const TemplateTemplateParmDecl *TTP =
+ dyn_cast<TemplateTemplateParmDecl>(Param))
+ CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
+ Corrector);
+ }
+}
+} // unnamed namespace
+
+StringRef Sema::correctTypoInTParamReference(
+ StringRef Typo,
+ const TemplateParameterList *TemplateParameters) {
+ SimpleTypoCorrector Corrector(Typo);
+ CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
+ if (const NamedDecl *ND = Corrector.getBestDecl()) {
+ const IdentifierInfo *II = ND->getIdentifier();
+ assert(II && "SimpleTypoCorrector should not return this decl");
+ return II->getName();
+ }
+ return StringRef();
}
// TODO: tablegen
@@ -465,7 +696,7 @@
.Case("authors", true)
.Case("pre", true)
.Case("post", true)
- .Default(false) || isParamCommand(Name);
+ .Default(false) || isParamCommand(Name) || isTParamCommand(Name);
}
bool Sema::isParamCommand(StringRef Name) {
@@ -475,6 +706,10 @@
.Default(false);
}
+bool Sema::isTParamCommand(StringRef Name) {
+ return Name == "tparam";
+}
+
unsigned Sema::getBlockCommandNumArgs(StringRef Name) {
return llvm::StringSwitch<unsigned>(Name)
.Cases("brief", "short", 0)
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jul 31 17:37:06 2012
@@ -7618,6 +7618,7 @@
<< FD->getName() << "dllimport";
}
}
+ ActOnDocumentableDecl(FD);
return FD;
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jul 31 17:37:06 2012
@@ -1139,6 +1139,8 @@
if (PrevClassTemplate)
mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());
+ ActOnDocumentableDecl(NewTemplate);
+
return NewTemplate;
}
@@ -5568,7 +5570,9 @@
Decl *Sema::ActOnTemplateDeclarator(Scope *S,
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D) {
- return HandleDeclarator(S, D, move(TemplateParameterLists));
+ Decl *NewDecl = HandleDeclarator(S, D, move(TemplateParameterLists));
+ ActOnDocumentableDecl(NewDecl);
+ return NewDecl;
}
Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
Modified: cfe/trunk/test/Index/annotate-comments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-comments.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/test/Index/annotate-comments.cpp (original)
+++ cfe/trunk/test/Index/annotate-comments.cpp Tue Jul 31 17:37:06 2012
@@ -290,6 +290,30 @@
/// \param x1 Aaa.
void comment_to_html_conversion_16(int x1, int x2);
+/// \tparam
+/// \param aaa Blah blah
+template<typename T>
+void comment_to_html_conversion_17(T aaa);
+
+/// \tparam T2 Bbb
+/// \tparam T1 Aaa
+template<typename T1, typename T2>
+void comment_to_html_conversion_18(T1 aaa, T2 bbb);
+
+/// \tparam T2 Bbb
+/// \tparam U Zzz
+/// \tparam V Ccc
+/// \tparam T1 Aaa
+template<typename T1, typename T2, int V>
+void comment_to_html_conversion_19(T1 aaa, T2 bbb);
+
+/// \tparam TTT Ddd
+/// \tparam C Ccc
+/// \tparam T Aaa
+/// \tparam TT Bbb
+template<template<template<typename T> class TT, class C> class TTT>
+void comment_to_html_conversion_20();
+
/// \brief Aaa.
///
/// Bbb.
@@ -297,34 +321,34 @@
/// \param x2 Ddd.
/// \param x1 Ccc.
/// \returns Eee.
-void comment_to_html_conversion_17(int x1, int x2);
+void comment_to_html_conversion_21(int x1, int x2);
/// <br><a href="http://example.com/">Aaa</a>
-void comment_to_html_conversion_18();
+void comment_to_html_conversion_22();
/// \verbatim
/// <a href="http://example.com/">Aaa</a>
/// <a href='http://example.com/'>Aaa</a>
/// \endverbatim
-void comment_to_html_conversion_19();
+void comment_to_html_conversion_23();
/// \b Aaa
-void comment_to_html_conversion_20();
+void comment_to_html_conversion_24();
/// \c Aaa \p Bbb
-void comment_to_html_conversion_21();
+void comment_to_html_conversion_25();
/// \a Aaa \e Bbb \em Ccc
-void comment_to_html_conversion_22();
+void comment_to_html_conversion_26();
/// \\ \@ \& \$ \# \< \> \% \" \. \::
-void comment_to_html_conversion_23();
+void comment_to_html_conversion_27();
/// & < > "
-void comment_to_html_conversion_24();
+void comment_to_html_conversion_28();
/// <em>0<i</em>
-void comment_to_html_conversion_25();
+void comment_to_html_conversion_29();
#endif
@@ -555,7 +579,70 @@
// CHECK-NEXT: (CXComment_ParamCommand in implicitly ParamName=[x1] ParamIndex=0
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Aaa.]))))]
-// CHECK: annotate-comments.cpp:300:6: FunctionDecl=comment_to_html_conversion_17:{{.*}} FullCommentAsHTML=[<p class="para-brief"> Aaa.</p><p> Bbb.</p><dl><dt class="param-name-index-0">x1</dt><dd class="param-descr-index-0"> Ccc. </dd><dt class="param-name-index-1">x2</dt><dd class="param-descr-index-1"> Ddd. </dd></dl><p class="para-returns"><span class="word-returns">Returns</span> Eee.</p>]
+// CHECK: annotate-comments.cpp:296:6: FunctionTemplate=comment_to_html_conversion_17:{{.*}} FullCommentAsHTML=[<dl><dt class="param-name-index-0">aaa</dt><dd class="param-descr-index-0"> Blah blah</dd></dl>]
+// CHECK-NEXT: CommentAST=[
+// CHECK-NEXT: (CXComment_FullComment
+// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[] ParamPosition=Invalid
+// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_ParamCommand in implicitly ParamName=[aaa] ParamIndex=0
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Blah blah]))))]
+// CHECK: annotate-comments.cpp:301:6: FunctionTemplate=comment_to_html_conversion_18:{{.*}} FullCommentAsHTML=[<dl><dt class="taram-name-index-0">T1</dt><dd class="tparam-descr-index-0"> Aaa</dd><dt class="taram-name-index-1">T2</dt><dd class="tparam-descr-index-1"> Bbb </dd></dl>]
+// CHECK-NEXT: CommentAST=[
+// CHECK-NEXT: (CXComment_FullComment
+// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[T2] ParamPosition={1}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Bbb] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[T1] ParamPosition={0}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa]))))]
+// CHECK: annotate-comments.cpp:308:6: FunctionTemplate=comment_to_html_conversion_19:{{.*}} FullCommentAsHTML=[<dl><dt class="taram-name-index-0">T1</dt><dd class="tparam-descr-index-0"> Aaa</dd><dt class="taram-name-index-1">T2</dt><dd class="tparam-descr-index-1"> Bbb </dd><dt class="taram-name-index-2">V</dt><dd class="tparam-descr-index-2"> Ccc </dd><dt class="tparam-name-index-invalid">U</dt><dd class="tparam-descr-index-invalid"> Zzz </dd></dl>]
+// CHECK-NEXT: CommentAST=[
+// CHECK-NEXT: (CXComment_FullComment
+// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[T2] ParamPosition={1}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Bbb] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[U] ParamPosition=Invalid
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Zzz] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[V] ParamPosition={2}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Ccc] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[T1] ParamPosition={0}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa]))))]
+// CHECK: annotate-comments.cpp:315:6: FunctionTemplate=comment_to_html_conversion_20:{{.*}} FullCommentAsHTML=[<dl><dt class="taram-name-index-0">TTT</dt><dd class="tparam-descr-index-0"> Ddd </dd><dt class="taram-name-index-other">C</dt><dd class="tparam-descr-index-other"> Ccc </dd><dt class="taram-name-index-other">T</dt><dd class="tparam-descr-index-other"> Aaa </dd><dt class="taram-name-index-other">TT</dt><dd class="tparam-descr-index-other"> Bbb</dd></dl>]
+// CHECK-NEXT: CommentAST=[
+// CHECK-NEXT: (CXComment_FullComment
+// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[TTT] ParamPosition={0}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Ddd] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[C] ParamPosition={0, 1}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Ccc] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[T] ParamPosition={0, 0, 0}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Aaa] HasTrailingNewline)
+// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
+// CHECK-NEXT: (CXComment_TParamCommand ParamName=[TT] ParamPosition={0, 0}
+// CHECK-NEXT: (CXComment_Paragraph
+// CHECK-NEXT: (CXComment_Text Text=[ Bbb]))))]
+// CHECK: annotate-comments.cpp:324:6: FunctionDecl=comment_to_html_conversion_21:{{.*}} FullCommentAsHTML=[<p class="para-brief"> Aaa.</p><p> Bbb.</p><dl><dt class="param-name-index-0">x1</dt><dd class="param-descr-index-0"> Ccc. </dd><dt class="param-name-index-1">x2</dt><dd class="param-descr-index-1"> Ddd. </dd></dl><p class="para-returns"><span class="word-returns">Returns</span> Eee.</p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
@@ -578,7 +665,7 @@
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[returns]
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ Eee.]))))]
-// CHECK: annotate-comments.cpp:303:6: FunctionDecl=comment_to_html_conversion_18:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <br><a href="http://example.com/">Aaa</a></p>]
+// CHECK: annotate-comments.cpp:327:6: FunctionDecl=comment_to_html_conversion_22:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <br><a href="http://example.com/">Aaa</a></p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
@@ -587,7 +674,7 @@
// CHECK-NEXT: (CXComment_HTMLStartTag Name=[a] Attrs: href=http://example.com/)
// CHECK-NEXT: (CXComment_Text Text=[Aaa])
// CHECK-NEXT: (CXComment_HTMLEndTag Name=[a])))]
-// CHECK: annotate-comments.cpp:309:6: FunctionDecl=comment_to_html_conversion_19:{{.*}} FullCommentAsHTML=[<pre> <a href="http://example.com/">Aaa</a>\n <a href='http://example.com/'>Aaa</a></pre>]
+// CHECK: annotate-comments.cpp:333:6: FunctionDecl=comment_to_html_conversion_23:{{.*}} FullCommentAsHTML=[<pre> <a href="http://example.com/">Aaa</a>\n <a href='http://example.com/'>Aaa</a></pre>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
@@ -595,13 +682,13 @@
// CHECK-NEXT: (CXComment_VerbatimBlockCommand CommandName=[verbatim]
// CHECK-NEXT: (CXComment_VerbatimBlockLine Text=[ <a href="http://example.com/">Aaa</a>])
// CHECK-NEXT: (CXComment_VerbatimBlockLine Text=[ <a href='http://example.com/'>Aaa</a>])))]
-// CHECK: annotate-comments.cpp:312:6: FunctionDecl=comment_to_html_conversion_20:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <b>Aaa</b></p>]
+// CHECK: annotate-comments.cpp:336:6: FunctionDecl=comment_to_html_conversion_24:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <b>Aaa</b></p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[b] RenderBold Arg[0]=Aaa)))]
-// CHECK: annotate-comments.cpp:315:6: FunctionDecl=comment_to_html_conversion_21:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>]
+// CHECK: annotate-comments.cpp:339:6: FunctionDecl=comment_to_html_conversion_25:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
@@ -609,7 +696,7 @@
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[c] RenderMonospaced Arg[0]=Aaa)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[p] RenderMonospaced Arg[0]=Bbb)))]
-// CHECK: annotate-comments.cpp:318:6: FunctionDecl=comment_to_html_conversion_22:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>]
+// CHECK: annotate-comments.cpp:342:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
@@ -619,7 +706,7 @@
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[e] RenderEmphasized Arg[0]=Bbb)
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_InlineCommand CommandName=[em] RenderEmphasized Arg[0]=Ccc)))]
-// CHECK: annotate-comments.cpp:321:6: FunctionDecl=comment_to_html_conversion_23:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ & $ # < > % " . ::</p>]
+// CHECK: annotate-comments.cpp:345:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ & $ # < > % " . ::</p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
@@ -645,7 +732,7 @@
// CHECK-NEXT: (CXComment_Text Text=[.])
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_Text Text=[::])))]
-// CHECK: annotate-comments.cpp:324:6: FunctionDecl=comment_to_html_conversion_24:{{.*}} FullCommentAsHTML=[<p class="para-brief"> & < > "</p>]
+// CHECK: annotate-comments.cpp:348:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[<p class="para-brief"> & < > "</p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
@@ -657,7 +744,7 @@
// CHECK-NEXT: (CXComment_Text Text=[>])
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
// CHECK-NEXT: (CXComment_Text Text=["])))]
-// CHECK: annotate-comments.cpp:327:6: FunctionDecl=comment_to_html_conversion_25:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>0<i</em></p>]
+// CHECK: annotate-comments.cpp:351:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>0<i</em></p>]
// CHECK-NEXT: CommentAST=[
// CHECK-NEXT: (CXComment_FullComment
// CHECK-NEXT: (CXComment_Paragraph
Modified: cfe/trunk/test/Sema/warn-documentation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-documentation.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-documentation.cpp (original)
+++ cfe/trunk/test/Sema/warn-documentation.cpp Tue Jul 31 17:37:06 2012
@@ -170,18 +170,86 @@
int test_param15(int bbb, int ccc);
};
+// expected-warning at +1 {{parameter 'aab' not found in the function declaration}}
+/// \param aab Blah blah.
+template<typename T>
+void test_param16(int bbb, int ccc);
+
// expected-warning at +3 {{parameter 'a' is already documented}}
// expected-note at +1 {{previous documentation}}
/// \param a Aaa.
/// \param a Aaa.
-int test_param16(int a);
+int test_param17(int a);
// expected-warning at +4 {{parameter 'x2' is already documented}}
// expected-note at +2 {{previous documentation}}
/// \param x1 Aaa.
/// \param x2 Bbb.
/// \param x2 Ccc.
-int test_param17(int x1, int x2, int x3);
+int test_param18(int x1, int x2, int x3);
+
+
+// expected-warning at +1 {{'\tparam' command used in a comment that is not attached to a template declaration}}
+/// \tparam T Aaa
+int test_tparam1;
+
+// expected-warning at +1 {{'\tparam' command used in a comment that is not attached to a template declaration}}
+/// \tparam T Aaa
+void test_tparam2(int aaa);
+
+// expected-warning at +1 {{empty paragraph passed to '\tparam' command}}
+/// \tparam
+/// \param aaa Blah blah
+template<typename T>
+void test_tparam3(T aaa);
+
+// expected-warning at +1 {{template parameter 'T' not found in the template declaration}} expected-note at +1 {{did you mean 'TT'?}}
+/// \tparam T Aaa
+template<typename TT>
+void test_tparam4(TT aaa);
+
+// expected-warning at +1 {{template parameter 'T' not found in the template declaration}} expected-note at +1 {{did you mean 'TT'?}}
+/// \tparam T Aaa
+template<typename TT>
+class test_tparam5 {
+ // expected-warning at +1 {{template parameter 'T' not found in the template declaration}} expected-note at +1 {{did you mean 'TTT'?}}
+ /// \tparam T Aaa
+ template<typename TTT>
+ void test_tparam6(TTT aaa);
+};
+
+/// \tparam T1 Aaa
+/// \tparam T2 Bbb
+template<typename T1, typename T2>
+void test_tparam7(T1 aaa, T2 bbb);
+
+// expected-warning at +1 {{template parameter 'SomTy' not found in the template declaration}} expected-note at +1 {{did you mean 'SomeTy'?}}
+/// \tparam SomTy Aaa
+/// \tparam OtherTy Bbb
+template<typename SomeTy, typename OtherTy>
+void test_tparam8(SomeTy aaa, OtherTy bbb);
+
+// expected-warning at +2 {{template parameter 'T1' is already documented}} expected-note at +1 {{previous documentation}}
+/// \tparam T1 Aaa
+/// \tparam T1 Bbb
+template<typename T1, typename T2>
+void test_tparam9(T1 aaa, T2 bbb);
+
+/// \tparam T Aaa
+/// \tparam TT Bbb
+template<template<typename T> class TT>
+void test_tparam10(TT<int> aaa);
+
+/// \tparam T Aaa
+/// \tparam TT Bbb
+/// \tparam TTT Ccc
+template<template<template<typename T> class TT, class C> class TTT>
+void test_tparam11();
+
+/// \tparam I Aaa
+template<int I>
+void test_tparam12();
+
// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
int test1; ///< \brief\brief Aaa
@@ -292,6 +360,125 @@
}
}
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T>
+void test_attach26(T aaa);
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T, typename U>
+void test_attach27(T aaa, U bbb);
+
+// expected-warning at +2 {{empty paragraph passed to '\brief' command}}
+// expected-warning at +2 {{template parameter 'T' not found in the template declaration}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<>
+void test_attach27(int aaa, int bbb);
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T>
+class test_attach28 {
+ T aaa;
+};
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T, typename U>
+class test_attach29 { };
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T>
+class test_attach29<T, int> { };
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+template<>
+class test_attach29<int, int> { };
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T, typename U, typename V>
+class test_attach30 { };
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T, typename U>
+class test_attach30<T, U, int> { };
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T>
+class test_attach30<T, int, int> { };
+
+// expected-warning at +2 {{empty paragraph passed to '\brief' command}}
+// expected-warning at +2 {{template parameter 'T' not found in the template declaration}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<>
+class test_attach30<int, int, int> { };
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+class test_attach31 {
+ // expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+ /// \brief\brief Aaa
+ /// \tparam T Aaa
+ template<typename T, typename U>
+ void test_attach32(T aaa, U bbb);
+};
+
+template<typename T>
+class test_attach33 {
+ // expected-warning at +2 {{empty paragraph passed to '\brief' command}}
+ // expected-warning at +2 {{template parameter 'T' not found in the template declaration}}
+ /// \brief\brief Aaa
+ /// \tparam T Aaa
+ template<typename TT, typename UU>
+ void test_attach34(TT aaa, UU bbb);
+};
+
+// expected-warning at +2 {{empty paragraph passed to '\brief' command}}
+// expected-warning at +2 {{template parameter 'T' not found in the template declaration}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<> template<>
+void test_attach33<int>::test_attach34(int aaa, int bbb) {}
+
+template<typename T>
+class test_attach35 {
+ // expected-warning at +2 {{empty paragraph passed to '\brief' command}}
+ // expected-warning at +2 {{'\tparam' command used in a comment that is not attached to a template declaration}}
+ /// \brief\brief Aaa
+ /// \tparam T Aaa
+ void test_attach36(int aaa, int bbb);
+};
+
+// expected-warning at +1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<typename T>
+void test_attach35<T>::test_attach36(int aaa, int bbb) {}
+
+// expected-warning at +2 {{empty paragraph passed to '\brief' command}}
+// expected-warning at +2 {{template parameter 'T' not found in the template declaration}}
+/// \brief\brief Aaa
+/// \tparam T Aaa
+template<>
+void test_attach35<int>::test_attach36(int aaa, int bbb) {}
+
+
// PR13411, reduced. We used to crash on this.
/**
* @code Aaa.
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Tue Jul 31 17:37:06 2012
@@ -378,6 +378,23 @@
else
printf(" ParamIndex=Invalid");
break;
+ case CXComment_TParamCommand:
+ printf("CXComment_TParamCommand");
+ PrintCXStringWithPrefixAndDispose(
+ "ParamName",
+ clang_TParamCommandComment_getParamName(Comment));
+ if (clang_TParamCommandComment_isParamPositionValid(Comment)) {
+ printf(" ParamPosition={");
+ for (i = 0, e = clang_TParamCommandComment_getDepth(Comment);
+ i != e; ++i) {
+ printf("%u", clang_TParamCommandComment_getIndex(Comment, i));
+ if (i != e - 1)
+ printf(", ");
+ }
+ printf("}");
+ } else
+ printf(" ParamPosition=Invalid");
+ break;
case CXComment_VerbatimBlockCommand:
printf("CXComment_VerbatimBlockCommand");
PrintCXStringWithPrefixAndDispose(
Modified: cfe/trunk/tools/libclang/CXComment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXComment.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXComment.cpp (original)
+++ cfe/trunk/tools/libclang/CXComment.cpp Tue Jul 31 17:37:06 2012
@@ -59,6 +59,9 @@
case Comment::ParamCommandCommentKind:
return CXComment_ParamCommand;
+ case Comment::TParamCommandCommentKind:
+ return CXComment_TParamCommand;
+
case Comment::VerbatimBlockCommentKind:
return CXComment_VerbatimBlockCommand;
@@ -291,6 +294,38 @@
llvm_unreachable("unknown ParamCommandComment::PassDirection");
}
+CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->hasParamName())
+ return createCXString((const char *) 0);
+
+ return createCXString(TPCC->getParamName(), /*DupString=*/ false);
+}
+
+unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC)
+ return false;
+
+ return TPCC->isPositionValid();
+}
+
+unsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->isPositionValid())
+ return 0;
+
+ return TPCC->getDepth();
+}
+
+unsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
+ return 0;
+
+ return TPCC->getIndex(Depth);
+}
+
CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
const VerbatimBlockLineComment *VBL =
getASTNodeAs<VerbatimBlockLineComment>(CXC);
@@ -333,6 +368,34 @@
}
};
+/// This comparison will sort template parameters in the following order:
+/// \li real template parameters (depth = 1) in index order;
+/// \li all other names (depth > 1);
+/// \li unresolved names.
+class TParamCommandCommentComparePosition {
+public:
+ bool operator()(const TParamCommandComment *LHS,
+ const TParamCommandComment *RHS) const {
+ // Sort unresolved names last.
+ if (!LHS->isPositionValid())
+ return false;
+ if (!RHS->isPositionValid())
+ return true;
+
+ if (LHS->getDepth() > 1)
+ return false;
+ if (RHS->getDepth() > 1)
+ return true;
+
+ // Sort template parameters in index order.
+ if (LHS->getDepth() == 1 && RHS->getDepth() == 1)
+ return LHS->getIndex(0) < RHS->getIndex(0);
+
+ // Leave all other names in source order.
+ return true;
+ }
+};
+
class CommentASTToHTMLConverter :
public ConstCommentVisitor<CommentASTToHTMLConverter> {
public:
@@ -349,6 +412,7 @@
void visitParagraphComment(const ParagraphComment *C);
void visitBlockCommandComment(const BlockCommandComment *C);
void visitParamCommandComment(const ParamCommandComment *C);
+ void visitTParamCommandComment(const TParamCommandComment *C);
void visitVerbatimBlockComment(const VerbatimBlockComment *C);
void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
void visitVerbatimLineComment(const VerbatimLineComment *C);
@@ -486,6 +550,34 @@
Result << "</dd>";
}
+void CommentASTToHTMLConverter::visitTParamCommandComment(
+ const TParamCommandComment *C) {
+ if (C->isPositionValid()) {
+ if (C->getDepth() == 1)
+ Result << "<dt class=\"taram-name-index-"
+ << C->getIndex(0)
+ << "\">";
+ else
+ Result << "<dt class=\"taram-name-index-other\">";
+ } else
+ Result << "<dt class=\"tparam-name-index-invalid\">";
+
+ Result << C->getParamName() << "</dt>";
+
+ if (C->isPositionValid()) {
+ if (C->getDepth() == 1)
+ Result << "<dd class=\"tparam-descr-index-"
+ << C->getIndex(0)
+ << "\">";
+ else
+ Result << "<dd class=\"tparam-descr-index-other\">";
+ } else
+ Result << "<dd class=\"tparam-descr-index-invalid\">";
+
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</dd>";
+}
+
void CommentASTToHTMLConverter::visitVerbatimBlockComment(
const VerbatimBlockComment *C) {
unsigned NumLines = C->getNumLines();
@@ -518,6 +610,7 @@
const ParagraphComment *FirstParagraph = NULL;
const BlockCommandComment *Returns = NULL;
SmallVector<const ParamCommandComment *, 8> Params;
+ SmallVector<const TParamCommandComment *, 4> TParams;
SmallVector<const BlockContentComment *, 8> MiscBlocks;
// Extract various blocks into separate variables and vectors above.
@@ -568,6 +661,15 @@
break;
}
+ case Comment::TParamCommandCommentKind: {
+ const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
+ if (!TPCC->hasParamName())
+ break;
+
+ TParams.push_back(TPCC);
+ break;
+ }
+
case Comment::VerbatimBlockCommentKind:
case Comment::VerbatimLineCommentKind:
MiscBlocks.push_back(cast<BlockCommandComment>(Child));
@@ -590,6 +692,9 @@
std::stable_sort(Params.begin(), Params.end(),
ParamCommandCommentCompareIndex());
+ std::stable_sort(TParams.begin(), TParams.end(),
+ TParamCommandCommentComparePosition());
+
bool FirstParagraphIsBrief = false;
if (Brief)
visit(Brief);
@@ -607,6 +712,13 @@
visit(C);
}
+ if (TParams.size() != 0) {
+ Result << "<dl>";
+ for (unsigned i = 0, e = TParams.size(); i != e; ++i)
+ visit(TParams[i]);
+ Result << "</dl>";
+ }
+
if (Params.size() != 0) {
Result << "<dl>";
for (unsigned i = 0, e = Params.size(); i != e; ++i)
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Tue Jul 31 17:37:06 2012
@@ -42,6 +42,10 @@
clang_ParamCommandComment_getParamIndex
clang_ParamCommandComment_isDirectionExplicit
clang_ParamCommandComment_getDirection
+clang_TParamCommandComment_getParamName
+clang_TParamCommandComment_isParamPositionValid
+clang_TParamCommandComment_getDepth
+clang_TParamCommandComment_getIndex
clang_VerbatimBlockLineComment_getText
clang_VerbatimLineComment_getText
clang_HTMLTagComment_getAsString
Modified: cfe/trunk/unittests/AST/CommentParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CommentParser.cpp?rev=161087&r1=161086&r2=161087&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CommentParser.cpp (original)
+++ cfe/trunk/unittests/AST/CommentParser.cpp Tue Jul 31 17:37:06 2012
@@ -221,6 +221,39 @@
return ::testing::AssertionSuccess();
}
+::testing::AssertionResult HasTParamCommandAt(
+ const Comment *C,
+ size_t Idx,
+ TParamCommandComment *&TPCC,
+ StringRef CommandName,
+ StringRef ParamName,
+ ParagraphComment *&Paragraph) {
+ ::testing::AssertionResult AR = GetChildAt(C, Idx, TPCC);
+ if (!AR)
+ return AR;
+
+ StringRef ActualCommandName = TPCC->getCommandName();
+ if (ActualCommandName != CommandName)
+ return ::testing::AssertionFailure()
+ << "TParamCommandComment has name \"" << ActualCommandName.str() << "\", "
+ "expected \"" << CommandName.str() << "\"";
+
+ if (!TPCC->hasParamName())
+ return ::testing::AssertionFailure()
+ << "TParamCommandComment has no parameter name";
+
+ StringRef ActualParamName = TPCC->getParamName();
+ if (ActualParamName != ParamName)
+ return ::testing::AssertionFailure()
+ << "TParamCommandComment has parameter name \"" << ActualParamName.str()
+ << "\", "
+ "expected \"" << ParamName.str() << "\"";
+
+ Paragraph = TPCC->getParagraph();
+
+ return ::testing::AssertionSuccess();
+}
+
::testing::AssertionResult HasInlineCommandAt(const Comment *C,
size_t Idx,
InlineCommandComment *&ICC,
@@ -838,6 +871,33 @@
}
}
+TEST_F(CommentParserTest, TParamCommand1) {
+ const char *Sources[] = {
+ "// \\tparam aaa Bbb\n",
+ "// \\tparam\n"
+ "// aaa Bbb\n",
+ "// \\tparam \n"
+ "// aaa Bbb\n",
+ "// \\tparam aaa\n"
+ "// Bbb\n"
+ };
+
+ for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
+ FullComment *FC = parseString(Sources[i]);
+ ASSERT_TRUE(HasChildCount(FC, 2));
+
+ ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
+ {
+ TParamCommandComment *TPCC;
+ ParagraphComment *PC;
+ ASSERT_TRUE(HasTParamCommandAt(FC, 1, TPCC, "tparam",
+ "aaa", PC));
+ ASSERT_TRUE(HasChildCount(TPCC, 1));
+ ASSERT_TRUE(HasParagraphCommentAt(TPCC, 0, " Bbb"));
+ }
+ }
+}
+
TEST_F(CommentParserTest, InlineCommand1) {
const char *Source = "// \\c";
More information about the cfe-commits
mailing list