diff options
30 files changed, 879 insertions, 555 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index cf21d23668..912e657480 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2040,7 +2040,8 @@ typedef struct { * \brief A comment AST node. */ typedef struct { - const void *Data; + const void *ASTNode; + CXTranslationUnit TranslationUnit; } CXComment; /** @@ -3692,14 +3693,11 @@ CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment); * A Relax NG schema for the XML can be found in comment-xml-schema.rng file * inside clang source tree. * - * \param TU the translation unit \c Comment belongs to. - * * \param Comment a \c CXComment_FullComment AST node. * * \returns string containing an XML document. */ -CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXTranslationUnit TU, - CXComment Comment); +CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment); /** * @} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 93ed1c4f5d..0897582205 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -29,6 +29,7 @@ #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/RawCommentList.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -529,6 +530,14 @@ public: /// Returns NULL if no comment is attached. comments::FullComment *getCommentForDecl(const Decl *D) const; +private: + mutable comments::CommandTraits CommentCommandTraits; + +public: + comments::CommandTraits &getCommentCommandTraits() const { + return CommentCommandTraits; + } + /// \brief Retrieve the attributes for the given declaration. AttrVec& getDeclAttrs(const Decl *D); diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 339250b674..4c4c0fb0a0 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -28,3 +28,7 @@ clang_tablegen(CommentHTMLTagsProperties.inc -gen-clang-comment-html-tags-proper SOURCE CommentHTMLTags.td TARGET ClangCommentHTMLTagsProperties) +clang_tablegen(CommentCommandInfo.inc -gen-clang-comment-command-info + SOURCE CommentCommands.td + TARGET ClangCommentCommandInfo) + diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index 09d0a26731..cf43fc3e20 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -16,6 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/AST/Type.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -74,8 +75,9 @@ protected: unsigned : NumInlineContentCommentBits; unsigned RenderKind : 2; + unsigned CommandID : 8; }; - enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 }; + enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 }; class HTMLStartTagCommentBitfields { friend class HTMLStartTagComment; @@ -101,10 +103,19 @@ protected: }; enum { NumParagraphCommentBits = NumCommentBits + 2 }; + class BlockCommandCommentBitfields { + friend class BlockCommandComment; + + unsigned : NumCommentBits; + + unsigned CommandID : 8; + }; + enum { NumBlockCommandCommentBits = NumCommentBits + 8 }; + class ParamCommandCommentBitfields { friend class ParamCommandComment; - unsigned : NumCommentBits; + unsigned : NumBlockCommandCommentBits; /// Parameter passing direction, see ParamCommandComment::PassDirection. unsigned Direction : 2; @@ -112,7 +123,7 @@ protected: /// True if direction was specified explicitly in the comment. unsigned IsDirectionExplicit : 1; }; - enum { NumParamCommandCommentBits = 11 }; + enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; union { CommentBitfields CommentBits; @@ -121,6 +132,7 @@ protected: InlineCommandCommentBitfields InlineCommandCommentBits; HTMLStartTagCommentBitfields HTMLStartTagCommentBits; ParagraphCommentBitfields ParagraphCommentBits; + BlockCommandCommentBitfields BlockCommandCommentBits; ParamCommandCommentBitfields ParamCommandCommentBits; }; @@ -158,8 +170,9 @@ public: const char *getCommentKindName() const; LLVM_ATTRIBUTE_USED void dump() const; - LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; - void dump(llvm::raw_ostream &OS, SourceManager *SM) const; + LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) const; + void dump(llvm::raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) const; static bool classof(const Comment *) { return true; } @@ -273,21 +286,19 @@ public: }; protected: - /// Command name. - StringRef Name; - /// Command arguments. llvm::ArrayRef<Argument> Args; public: InlineCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name, + unsigned CommandID, RenderKind RK, llvm::ArrayRef<Argument> Args) : InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), - Name(Name), Args(Args) { + Args(Args) { InlineCommandCommentBits.RenderKind = RK; + InlineCommandCommentBits.CommandID = CommandID; } static bool classof(const Comment *C) { @@ -300,8 +311,12 @@ public: child_iterator child_end() const { return NULL; } - StringRef getCommandName() const { - return Name; + unsigned getCommandID() const { + return InlineCommandCommentBits.CommandID; + } + + StringRef getCommandName(const CommandTraits &Traits) const { + return Traits.getCommandInfo(getCommandID())->Name; } SourceRange getCommandNameRange() const { @@ -566,9 +581,6 @@ public: }; protected: - /// Command name. - StringRef Name; - /// Word-like arguments. llvm::ArrayRef<Argument> Args; @@ -578,21 +590,21 @@ protected: BlockCommandComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : + unsigned CommandID) : BlockContentComment(K, LocBegin, LocEnd), - Name(Name), Paragraph(NULL) { - setLocation(getCommandNameRange().getBegin()); + setLocation(getCommandNameBeginLoc()); + BlockCommandCommentBits.CommandID = CommandID; } public: BlockCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : + unsigned CommandID) : BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), - Name(Name), Paragraph(NULL) { - setLocation(getCommandNameRange().getBegin()); + setLocation(getCommandNameBeginLoc()); + BlockCommandCommentBits.CommandID = CommandID; } static bool classof(const Comment *C) { @@ -610,12 +622,21 @@ public: return reinterpret_cast<child_iterator>(&Paragraph + 1); } - StringRef getCommandName() const { - return Name; + unsigned getCommandID() const { + return BlockCommandCommentBits.CommandID; } - SourceRange getCommandNameRange() const { - return SourceRange(getLocStart().getLocWithOffset(1), + StringRef getCommandName(const CommandTraits &Traits) const { + return Traits.getCommandInfo(getCommandID())->Name; + } + + SourceLocation getCommandNameBeginLoc() const { + return getLocStart().getLocWithOffset(1); + } + + SourceRange getCommandNameRange(const CommandTraits &Traits) const { + StringRef Name = getCommandName(Traits); + return SourceRange(getCommandNameBeginLoc(), getLocStart().getLocWithOffset(1 + Name.size())); } @@ -667,8 +688,9 @@ public: ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : - BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name), + unsigned CommandID) : + BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, + CommandID), ParamIndex(InvalidParamIndex) { ParamCommandCommentBits.Direction = In; ParamCommandCommentBits.IsDirectionExplicit = false; @@ -748,8 +770,8 @@ private: public: TParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : - BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, Name) + unsigned CommandID) : + BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID) { } static bool classof(const Comment *C) { @@ -830,9 +852,9 @@ protected: public: VerbatimBlockComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : + unsigned CommandID) : BlockCommandComment(VerbatimBlockCommentKind, - LocBegin, LocEnd, Name) + LocBegin, LocEnd, CommandID) { } static bool classof(const Comment *C) { @@ -882,12 +904,12 @@ protected: public: VerbatimLineComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name, + unsigned CommandID, SourceLocation TextBegin, StringRef Text) : BlockCommandComment(VerbatimLineCommentKind, LocBegin, LocEnd, - Name), + CommandID), Text(Text), TextBegin(TextBegin) { } diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index 5f0269a465..07d9a489e3 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -19,136 +19,125 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" namespace clang { namespace comments { -/// This class provides informaiton about commands that can be used -/// in comments. -class CommandTraits { -public: - CommandTraits() { } +/// \brief Information about a single command. +/// +/// When reordering, adding or removing members please update the corresponding +/// TableGen backend. +struct CommandInfo { + unsigned getID() const { + return ID; + } + + const char *Name; + + /// Name of the command that ends the verbatim block. + const char *EndCommandName; + + unsigned ID : 8; + + /// Number of word-like arguments for a given block command, except for + /// \\param and \\tparam commands -- these have special argument parsers. + unsigned NumArgs : 4; + + /// True if this command is a inline command (of any kind). + unsigned IsInlineCommand : 1; + + /// True if this command is a block command (of any kind). + unsigned IsBlockCommand : 1; + + /// True if this command is introducing a brief documentation + /// paragraph (\\brief or an alias). + unsigned IsBriefCommand : 1; + + /// True if this command is \\returns or an alias. + unsigned IsReturnsCommand : 1; + + /// True if this command is introducing documentation for a function + /// parameter (\\param or an alias). + unsigned IsParamCommand : 1; - /// \brief Check if a given command is a verbatim-like block command. + /// True if this command is introducing documentation for + /// a template parameter (\\tparam or an alias). + unsigned IsTParamCommand : 1; + + /// \brief True if this command is a verbatim-like block command. /// /// A verbatim-like block command eats every character (except line starting /// decorations) until matching end command is seen or comment end is hit. - /// - /// \param StartName name of the command that starts the verbatim block. - /// \param [out] EndName name of the command that ends the verbatim block. - /// - /// \returns true if a given command is a verbatim block command. - bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const; + unsigned IsVerbatimBlockCommand : 1; - /// \brief Register a new verbatim block command. - void addVerbatimBlockCommand(StringRef StartName, StringRef EndName); + /// \brief True if this command is an end command for a verbatim-like block. + unsigned IsVerbatimBlockEndCommand : 1; - /// \brief Check if a given command is a verbatim line command. + /// \brief True if this command is a verbatim line command. /// /// A verbatim-like line command eats everything until a newline is seen or /// comment end is hit. - bool isVerbatimLineCommand(StringRef Name) const; + unsigned IsVerbatimLineCommand : 1; - /// \brief Check if a given command is a command that contains a declaration - /// for the entity being documented. + /// \brief True if this command contains a declaration for the entity being + /// documented. /// /// For example: /// \code /// \fn void f(int a); /// \endcode - bool isDeclarationCommand(StringRef Name) const; + unsigned IsDeclarationCommand : 1; - /// \brief Register a new verbatim line command. - void addVerbatimLineCommand(StringRef Name); + /// \brief True if this command is unknown. This \c CommandInfo object was + /// created during parsing. + unsigned IsUnknownCommand : 1; +}; - /// \brief Check if a given command is a block command (of any kind). - bool isBlockCommand(StringRef Name) const; +/// This class provides information about commands that can be used +/// in comments. +class CommandTraits { +public: + CommandTraits(llvm::BumpPtrAllocator &Allocator); - /// \brief Check if a given command is introducing documentation for - /// a function parameter (\\param or an alias). - bool isParamCommand(StringRef Name) const; + /// \returns a CommandInfo object for a given command name or + /// NULL if no CommandInfo object exists for this command. + const CommandInfo *getCommandInfoOrNULL(StringRef Name) const; - /// \brief Check if a given command is introducing documentation for - /// a template parameter (\\tparam or an alias). - bool isTParamCommand(StringRef Name) const; + const CommandInfo *getCommandInfo(StringRef Name) const { + if (const CommandInfo *Info = getCommandInfoOrNULL(Name)) + return Info; + llvm_unreachable("the command should be known"); + } - /// \brief Check if a given command is introducing a brief documentation - /// paragraph (\\brief or an alias). - bool isBriefCommand(StringRef Name) const; + const CommandInfo *getCommandInfo(unsigned CommandID) const; - /// \brief Check if a given command is \\brief or an alias. - bool isReturnsCommand(StringRef Name) const; + const CommandInfo *registerUnknownCommand(StringRef CommandName); - /// \returns the number of word-like arguments for a given block command, - /// except for \\param and \\tparam commands -- these have special argument - /// parsers. - unsigned getBlockCommandNumArgs(StringRef Name) const; + /// \returns a CommandInfo object for a given command name or + /// NULL if \c Name is not a builtin command. + static const CommandInfo *getBuiltinCommandInfo(StringRef Name); - /// \brief Check if a given command is a inline command (of any kind). - bool isInlineCommand(StringRef Name) const; + /// \returns a CommandInfo object for a given command ID or + /// NULL if \c CommandID is not a builtin command. + static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID); private: - struct VerbatimBlockCommand { - StringRef StartName; - StringRef EndName; - }; - - typedef SmallVector<VerbatimBlockCommand, 4> VerbatimBlockCommandVector; + CommandTraits(const CommandTraits &) LLVM_DELETED_FUNCTION; + void operator=(const CommandTraits &) LLVM_DELETED_FUNCTION; - /// Registered additional verbatim-like block commands. - VerbatimBlockCommandVector VerbatimBlockCommands; + const CommandInfo *getRegisteredCommandInfo(StringRef Name) const; + const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const; - struct VerbatimLineCommand { - StringRef Name; - }; + unsigned NextID; - typedef SmallVector<VerbatimLineCommand, 4> VerbatimLineCommandVector; + /// Allocator for CommandInfo objects. + llvm::BumpPtrAllocator &Allocator; - /// Registered verbatim-like line commands. - VerbatimLineCommandVector VerbatimLineCommands; + SmallVector<CommandInfo *, 4> RegisteredCommands; }; -inline bool CommandTraits::isBlockCommand(StringRef Name) const { - return isBriefCommand(Name) || isReturnsCommand(Name) || - isParamCommand(Name) || isTParamCommand(Name) || - llvm::StringSwitch<bool>(Name) - .Case("author", true) - .Case("authors", true) - .Case("pre", true) - .Case("post", true) - .Default(false); -} - -inline bool CommandTraits::isParamCommand(StringRef Name) const { - return Name == "param"; -} - -inline bool CommandTraits::isTParamCommand(StringRef Name) const { - return Name == "tparam" || // Doxygen - Name == "templatefield"; // HeaderDoc -} - -inline bool CommandTraits::isBriefCommand(StringRef Name) const { - return Name == "brief" || Name == "short"; -} - -inline bool CommandTraits::isReturnsCommand(StringRef Name) const { - return Name == "returns" || Name == "return" || Name == "result"; -} - -inline unsigned CommandTraits::getBlockCommandNumArgs(StringRef Name) const { - return 0; -} - -inline bool CommandTraits::isInlineCommand(StringRef Name) const { - return llvm::StringSwitch<bool>(Name) - .Case("b", true) - .Cases("c", "p", true) - .Cases("a", "e", "em", true) - .Default(false); -} - } // end namespace comments } // end namespace clang diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td new file mode 100644 index 0000000000..16ce4fca1b --- /dev/null +++ b/include/clang/AST/CommentCommands.td @@ -0,0 +1,133 @@ +class Command<string name> { + string Name = name; + string EndCommandName = ""; + + int NumArgs = 0; + + bit IsInlineCommand = 0; + + bit IsBlockCommand = 0; + bit IsBriefCommand = 0; + bit IsReturnsCommand = 0; + bit IsParamCommand = 0; + bit IsTParamCommand = 0; + + bit IsVerbatimBlockCommand = 0; + bit IsVerbatimBlockEndCommand = 0; + bit IsVerbatimLineCommand = 0; + bit IsDeclarationCommand = 0; +} + +class InlineCommand<string name> : Command<name> { + let IsInlineCommand = 1; +} + +class BlockCommand<string name> : Command<name> { + let IsBlockCommand = 1; +} + +class VerbatimBlockCommand<string name> : Command<name> { + let EndCommandName = name; + let IsVerbatimBlockCommand = 1; +} + +multiclass VerbatimBlockCommand<string name, string endCommandName> { + def Begin : Command<name> { + let EndCommandName = endCommandName; + let IsVerbatimBlockCommand = 1; + } + + def End : Command<endCommandName> { + let IsVerbatimBlockEndCommand = 1; + } +} + +class VerbatimLineCommand<string name> : Command<name> { + let IsVerbatimLineCommand = 1; +} + +class DeclarationVerbatimLineCommand<string name> : + VerbatimLineCommand<name> { + let IsDeclarationCommand = 1; +} + +def B : InlineCommand<"b">; +def C : InlineCommand<"c">; +def P : InlineCommand<"p">; +def A : InlineCommand<"a">; +def E : InlineCommand<"e">; +def Em : InlineCommand<"em">; + +def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; } +def Short : BlockCommand<"short"> { let IsBriefCommand = 1; } + +def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; } +def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; } +def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; } + +def Param : BlockCommand<"param"> { let IsParamCommand = 1; } + +// Doxygen +def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; } + +// HeaderDoc +def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; } + +def Author : BlockCommand<"author">; +def Authors : BlockCommand<"authors">; +def Pre : BlockCommand<"pre">; +def Post : BlockCommand<"post">; + +defm Code : VerbatimBlockCommand<"code", "endcode">; +defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">; +defm Htmlonly : VerbatimBlockCommand<"htmlonly", "endhtmlonly">; +defm Latexonly : VerbatimBlockCommand<"latexonly", "endlatexonly">; +defm Xmlonly : VerbatimBlockCommand<"xmlonly", "endxmlonly">; +defm Manonly : VerbatimBlockCommand<"manonly", "endmanonly">; +defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">; + +defm Dot : VerbatimBlockCommand<"dot", "enddot">; +defm Msc : VerbatimBlockCommand<"msc", "endmsc">; + +// These commands have special support in lexer. +def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula +defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula +defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment + +def Defgroup : VerbatimLineCommand<"defgroup">; +def Ingroup : VerbatimLineCommand<"ingroup">; +def Addtogroup : VerbatimLineCommand<"addtogroup">; +def Weakgroup : VerbatimLineCommand<"weakgroup">; +def Name : VerbatimLineCommand<"name">; + +def Section : VerbatimLineCommand<"section">; +def Subsection : VerbatimLineCommand<"subsection">; +def Subsubsection : VerbatimLineCommand<"subsubsection">; +def Paragraph : VerbatimLineCommand<"paragraph">; + +def Mainpage : VerbatimLineCommand<"mainpage">; +def Subpage : VerbatimLineCommand<"subpage">; +def Ref : VerbatimLineCommand<"ref">; + +// Doxygen commands. +def Fn : DeclarationVerbatimLineCommand<"fn">; +def Var : DeclarationVerbatimLineCommand<"var">; +def Property : DeclarationVerbatimLineCommand<"property">; +def Typedef : DeclarationVerbatimLineCommand<"typedef">; +def Overload : DeclarationVerbatimLineCommand<"overload">; + +// HeaderDoc commands. +def Class : DeclarationVerbatimLineCommand<"class">; +def Interface : DeclarationVerbatimLineCommand<"interface">; +def Protocol : DeclarationVerbatimLineCommand<"protocol">; +def Category : DeclarationVerbatimLineCommand<"category">; +def Template : DeclarationVerbatimLineCommand<"template">; +def Function : DeclarationVerbatimLineCommand<"function">; +def Method : DeclarationVerbatimLineCommand<"method">; +def Callback : DeclarationVerbatimLineCommand<"callback">; +def Const : DeclarationVerbatimLineCommand<"const">; +def Constant : DeclarationVerbatimLineCommand<"constant">; +def Struct : DeclarationVerbatimLineCommand<"struct">; +def Union : DeclarationVerbatimLineCommand<"union">; +def Enum : DeclarationVerbatimLineCommand<"enum">; + diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index e72052191d..99b95d3404 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -26,6 +26,7 @@ namespace comments { class Lexer; class TextTokenRetokenizer; +struct CommandInfo; class CommandTraits; namespace tok { @@ -33,6 +34,7 @@ enum TokenKind { eof, newline, text, + unknown_command, command, verbatim_block_begin, verbatim_block_line, @@ -65,8 +67,14 @@ class Token { unsigned Length; /// Contains text value associated with a token. - const char *TextPtr1; - unsigned TextLen1; + const char *TextPtr; + + /// Integer value associated with a token. + /// + /// If the token is a konwn command, contains command ID and TextPtr is + /// unused (command spelling can be found with CommandTraits). Otherwise, + /// contains the length of the string that starts at TextPtr. + unsigned IntVal; public: SourceLocation getLocation() const LLVM_READONLY { return Loc; } @@ -89,113 +97,120 @@ public: StringRef getText() const LLVM_READONLY { assert(is(tok::text)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setText(StringRef Text) { assert(is(tok::text)); - TextPtr1 = Text.data(); - TextLen1 = Text.size(); + TextPtr = Text.data(); + IntVal = Text.size(); + } + + StringRef getUnknownCommandName() const LLVM_READONLY { + assert(is(tok::unknown_command)); + return StringRef(TextPtr, IntVal); + } + + void setUnknownCommandName(StringRef Name) { + assert(is(tok::unknown_command)); + TextPtr = Name.data(); + IntVal = Name.size(); } - StringRef getCommandName() const LLVM_READONLY { + unsigned getCommandID() const LLVM_READONLY { assert(is(tok::command)); - return StringRef(TextPtr1, TextLen1); + return IntVal; } - void setCommandName(StringRef Name) { + void setCommandID(unsigned ID) { assert(is(tok::command)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + IntVal = ID; } - StringRef getVerbatimBlockName() const LLVM_READONLY { + unsigned getVerbatimBlockID() const LLVM_READONLY { assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); - return StringRef(TextPtr1, TextLen1); + return IntVal; } - void setVerbatimBlockName(StringRef Name) { + void setVerbatimBlockID(unsigned ID) { assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + IntVal = ID; } StringRef getVerbatimBlockText() const LLVM_READONLY { assert(is(tok::verbatim_block_line)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setVerbatimBlockText(StringRef Text) { assert(is(tok::verbatim_block_line)); - TextPtr1 = Text.data(); - TextLen1 = Text.size(); + TextPtr = Text.data(); + IntVal = Text.size(); } - /// Returns the name of verbatim line command. - StringRef getVerbatimLineName() const LLVM_READONLY { + unsigned getVerbatimLineID() const LLVM_READONLY { assert(is(tok::verbatim_line_name)); - return StringRef(TextPtr1, TextLen1); + return IntVal; } - void setVerbatimLineName(StringRef Name) { + void setVerbatimLineID(unsigned ID) { assert(is(tok::verbatim_line_name)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + IntVal = ID; } StringRef getVerbatimLineText() const LLVM_READONLY { assert(is(tok::verbatim_line_text)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setVerbatimLineText(StringRef Text) { assert(is(tok::verbatim_line_text)); - TextPtr1 = Text.data(); - TextLen1 = Text.size(); + TextPtr = Text.data(); + IntVal = Text.size(); } StringRef getHTMLTagStartName() const LLVM_READONLY { assert(is(tok::html_start_tag)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLTagStartName(StringRef Name) { assert(is(tok::html_start_tag)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + TextPtr = Name.data(); + IntVal = Name.size(); } StringRef getHTMLIdent() const LLVM_READONLY { assert(is(tok::html_ident)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLIdent(StringRef Name) { assert(is(tok::html_ident)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + TextPtr = Name.data(); + IntVal = Name.size(); } StringRef getHTMLQuotedString() const LLVM_READONLY { assert(is(tok::html_quoted_string)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLQuotedString(StringRef Str) { assert(is(tok::html_quoted_string)); - TextPtr1 = Str.data(); - TextLen1 = Str.size(); + TextPtr = Str.data(); + IntVal = Str.size(); } StringRef getHTMLTagEndName() const LLVM_READONLY { assert(is(tok::html_end_tag)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLTagEndName(StringRef Name) { assert(is(tok::html_end_tag)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + TextPtr = Name.data(); + IntVal = Name.size(); } void dump(const Lexer &L, const SourceManager &SM) const; @@ -280,8 +295,8 @@ private: Result.setKind(Kind); Result.setLength(TokLen); #ifndef NDEBUG - Result.TextPtr1 = "<UNSET>"; - Result.TextLen1 = 7; + Result.TextPtr = "<UNSET>"; + Result.IntVal = 7; #endif BufferPtr = TokEnd; } @@ -308,13 +323,14 @@ private: void setupAndLexVerbatimBlock(Token &T, const char *TextBegin, - char Marker, StringRef EndName); + char Marker, const CommandInfo *Info); void lexVerbatimBlockFirstLine(Token &T); void lexVerbatimBlockBody(Token &T); - void setupAndLexVerbatimLine(Token &T, const char *TextBegin); + void setupAndLexVerbatimLine(Token &T, const char *TextBegin, + const CommandInfo *Info); void lexVerbatimLineText(Token &T); diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 3252181255..5ebf5f0afa 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -41,7 +41,7 @@ class Sema { DiagnosticsEngine &Diags; - const CommandTraits &Traits; + CommandTraits &Traits; /// Information about the declaration this comment is attached to. DeclInfo *ThisDeclInfo; @@ -68,7 +68,7 @@ class Sema { public: Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags, const CommandTraits &Traits); + DiagnosticsEngine &Diags, CommandTraits &Traits); void setDecl(const Decl *D); @@ -89,7 +89,7 @@ public: BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + unsigned CommandID); void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef<BlockCommandComment::Argument> Args); @@ -99,7 +99,7 @@ public: ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + unsigned CommandID); void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, @@ -116,7 +116,7 @@ public: TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + unsigned CommandID); void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, @@ -128,11 +128,11 @@ public: InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - StringRef CommandName); + unsigned CommandID); InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - StringRef CommandName, + unsigned CommandID, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg); @@ -146,7 +146,7 @@ public: StringRef Text); VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc, - StringRef Name); + unsigned CommandID); VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc, StringRef Text); @@ -157,7 +157,7 @@ public: ArrayRef<VerbatimBlockLineComment *> Lines); VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin, - StringRef Name, + unsigned CommandID, SourceLocation TextBegin, StringRef Text); diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index dd3a7656ba..7fb33f2774 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -2,7 +2,7 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc \ CommentNodes.inc CommentHTMLTags.inc \ - CommentHTMLTagsProperties.inc + CommentHTMLTagsProperties.inc CommentCommandInfo.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -45,3 +45,8 @@ $(ObjDir)/CommentHTMLTagsProperties.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td $(Echo) "Building Clang comment HTML tag properties with tblgen" $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags-properties -o $(call SYSPATH, $@) $< +$(ObjDir)/CommentCommandInfo.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ + $(CLANG_TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang comment command info with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $< + diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d64ed11d7c..9fd40b206d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -573,6 +573,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, DeclarationNames(*this), ExternalSource(0), Listener(0), Comments(SM), CommentsLoaded(false), + CommentCommandTraits(BumpAlloc), LastSDM(0, 0), UniqueBlockByRefTypeID(0) { diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 14c0aa5eed..d20d77ef7e 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -64,6 +64,7 @@ add_dependencies(clangAST ClangAttrClasses ClangAttrList ClangAttrImpl + ClangCommentCommandInfo ClangCommentNodes ClangCommentHTMLTags ClangCommentHTMLTagsProperties diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 2af3896156..a6a21f3923 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ASTContext.h" #include "clang/AST/Comment.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" @@ -37,11 +38,12 @@ void Comment::dump() const { // in CommentDumper.cpp, that object file would be removed by linker because // none of its functions are referenced by other object files, despite the // LLVM_ATTRIBUTE_USED. - dump(llvm::errs(), NULL); + dump(llvm::errs(), NULL, NULL); } -void Comment::dump(SourceManager &SM) const { - dump(llvm::errs(), &SM); +void Comment::dump(const ASTContext &Context) const { + dump(llvm::errs(), &Context.getCommentCommandTraits(), + &Context.getSourceManager()); } namespace { diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp index 5a9b10d2db..95daa7e3f8 100644 --- a/lib/AST/CommentBriefParser.cpp +++ b/lib/AST/CommentBriefParser.cpp @@ -79,14 +79,14 @@ std::string BriefParser::Parse() { } if (Tok.is(tok::command)) { - StringRef Name = Tok.getCommandName(); - if (Traits.isBriefCommand(Name)) { + const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); + if (Info->IsBriefCommand) { FirstParagraphOrBrief.clear(); InBrief = true; ConsumeToken(); continue; } - if (Traits.isReturnsCommand(Name)) { + if (Info->IsReturnsCommand) { InReturns = true; InBrief = false; InFirstParagraph = false; @@ -95,7 +95,7 @@ std::string BriefParser::Parse() { continue; } // Block commands implicitly start a new paragraph. - if (Traits.isBlockCommand(Name)) { + if (Info->IsBlockCommand) { // We found an implicit paragraph end. InFirstParagraph = false; if (InBrief) diff --git a/lib/AST/CommentCommandTraits.cpp b/lib/AST/CommentCommandTraits.cpp index dc7a0bd175..26e2dee3a2 100644 --- a/lib/AST/CommentCommandTraits.cpp +++ b/lib/AST/CommentCommandTraits.cpp @@ -8,125 +8,63 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CommentCommandTraits.h" -#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/STLExtras.h" namespace clang { namespace comments { -// TODO: tablegen +#include "clang/AST/CommentCommandInfo.inc" -bool CommandTraits::isVerbatimBlockCommand(StringRef StartName, - StringRef &EndName) const { - const char *Result = llvm::StringSwitch<const char *>(StartName) - .Case("code", "endcode") - .Case("verbatim", "endverbatim") - .Case("htmlonly", "endhtmlonly") - .Case("latexonly", "endlatexonly") - .Case("xmlonly", "endxmlonly") - .Case("manonly", "endmanonly") - .Case("rtfonly", "endrtfonly") +CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator) : + NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) +{ } - .Case("dot", "enddot") - .Case("msc", "endmsc") - - .Case("f$", "f$") // Inline LaTeX formula - .Case("f[", "f]") // Displayed LaTeX formula - .Case("f{", "f}") // LaTeX environment - - .Default(NULL); - - if (Result) { - EndName = Result; - return true; - } - - for (VerbatimBlockCommandVector::const_iterator - I = VerbatimBlockCommands.begin(), - E = VerbatimBlockCommands.end(); - I != E; ++I) - if (I->StartName == StartName) { - EndName = I->EndName; - return true; - } - - return false; +const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const { + if (const CommandInfo *Info = getBuiltinCommandInfo(Name)) + return Info; + return getRegisteredCommandInfo(Name); } -bool CommandTraits::isVerbatimLineCommand(StringRef Name) const { - bool Result = isDeclarationCommand(Name) || llvm::StringSwitch<bool>(Name) - .Case("defgroup", true) - .Case("ingroup", true) - .Case("addtogroup", true) - .Case("weakgroup", true) - .Case("name", true) - - .Case("section", true) - .Case("subsection", true) - .Case("subsubsection", true) - .Case("paragraph", true) - - .Case("mainpage", true) - .Case("subpage", true) - .Case("ref", true) +const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { + if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID)) + return Info; + return getRegisteredCommandInfo(CommandID); +} - .Default(false); +const CommandInfo *CommandTraits::registerUnknownCommand(StringRef CommandName) { + char *Name = Allocator.Allocate<char>(CommandName.size()); + memcpy(Name, CommandName.data(), CommandName.size()); + Name[CommandName.size() + 1] = '\0'; - if (Result) - return true; + // Value-initialize (=zero-initialize in this case) a new CommandInfo. + CommandInfo *Info = new (Allocator) CommandInfo(); + Info->Name = Name; + Info->ID = NextID++; - for (VerbatimLineCommandVector::const_iterator - I = VerbatimLineCommands.begin(), - E = VerbatimLineCommands.end(); - I != E; ++I) - if (I->Name == Name) - return true; + RegisteredCommands.push_back(Info); - return false; + return Info; } -bool CommandTraits::isDeclarationCommand(StringRef Name) const { - return llvm::StringSwitch<bool>(Name) - // Doxygen commands. - .Case("fn", true) - .Case("var", true) - .Case("property", true) - .Case("typedef", true) - - .Case("overload", true) - - // HeaderDoc commands. - .Case("class", true) - .Case("interface", true) - .Case("protocol", true) - .Case("category", true) - .Case("template", true) - .Case("function", true) - .Case("method", true) - .Case("callback", true) - .Case("var", true) - .Case("const", true) - .Case("constant", true) - .Case("property", true) - .Case("struct", true) - .Case("union", true) - .Case("typedef", true) - .Case("enum", true) - - .Default(false); +const CommandInfo *CommandTraits::getBuiltinCommandInfo( + unsigned CommandID) { + if (CommandID < llvm::array_lengthof(Commands)) + return &Commands[CommandID]; + return NULL; } -void CommandTraits::addVerbatimBlockCommand(StringRef StartName, - StringRef EndName) { - VerbatimBlockCommand VBC; - VBC.StartName = StartName; - VBC.EndName = EndName; - VerbatimBlockCommands.push_back(VBC); +const CommandInfo *CommandTraits::getRegisteredCommandInfo( + StringRef Name) const { + for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) { + if (RegisteredCommands[i]->Name == Name) + return RegisteredCommands[i]; + } + return NULL; } -void CommandTraits::addVerbatimLineCommand(StringRef Name) { - VerbatimLineCommand VLC; - VLC.Name = Name; - VerbatimLineCommands.push_back(VLC); +const CommandInfo *CommandTraits::getRegisteredCommandInfo( + unsigned CommandID) const { + return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)]; } } // end namespace comments diff --git a/lib/AST/CommentDumper.cpp b/lib/AST/CommentDumper.cpp index dffc8233a0..f6fb3b1baa 100644 --- a/lib/AST/CommentDumper.cpp +++ b/lib/AST/CommentDumper.cpp @@ -16,12 +16,15 @@ namespace comments { namespace { class CommentDumper: public comments::ConstCommentVisitor<CommentDumper> { raw_ostream &OS; - SourceManager *SM; + const CommandTraits *Traits; + const SourceManager *SM; unsigned IndentLevel; public: - CommentDumper(raw_ostream &OS, SourceManager *SM) : - OS(OS), SM(SM), IndentLevel(0) + CommentDumper(raw_ostream &OS, + const CommandTraits *Traits, + const SourceManager *SM) : + OS(OS), Traits(Traits), SM(SM), IndentLevel(0) { } void dumpIndent() const { @@ -56,6 +59,15 @@ public: void visitVerbatimLineComment(const VerbatimLineComment *C); void visitFullComment(const FullComment *C); + + const char *getCommandName(unsigned CommandID) { + if (Traits) + return Traits->getCommandInfo(CommandID)->Name; + const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID); + if (Info) + return Info->Name; + return "<not a builtin command>"; + } }; void CommentDumper::dumpSourceRange(const Comment *C) { @@ -107,7 +119,7 @@ void CommentDumper::visitTextComment(const TextComment *C) { void CommentDumper::visitInlineCommandComment(const InlineCommandComment *C) { dumpComment(C); - OS << " Name=\"" << C->getCommandName() << "\""; + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; switch (C->getRenderKind()) { case InlineCommandComment::RenderNormal: OS << " RenderNormal"; @@ -155,7 +167,7 @@ void CommentDumper::visitParagraphComment(const ParagraphComment *C) { void CommentDumper::visitBlockCommandComment(const BlockCommandComment *C) { dumpComment(C); - OS << " Name=\"" << C->getCommandName() << "\""; + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; } @@ -198,7 +210,7 @@ void CommentDumper::visitTParamCommandComment(const TParamCommandComment *C) { void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) { dumpComment(C); - OS << " Name=\"" << C->getCommandName() << "\"" + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"" " CloseName=\"" << C->getCloseName() << "\""; } @@ -220,8 +232,9 @@ void CommentDumper::visitFullComment(const FullComment *C) { } // unnamed namespace -void Comment::dump(llvm::raw_ostream &OS, SourceManager *SM) const { - CommentDumper D(llvm::errs(), SM); +void Comment::dump(llvm::raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) const { + CommentDumper D(llvm::errs(), Traits, SM); D.dumpSubtree(this); llvm::errs() << '\n'; } diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp index 53440c169f..fde2c40fa5 100644 --- a/lib/AST/CommentLexer.cpp +++ b/lib/AST/CommentLexer.cpp @@ -359,18 +359,23 @@ void Lexer::lexCommentText(Token &T) { } const StringRef CommandName(BufferPtr + 1, Length); - StringRef EndName; - if (Traits.isVerbatimBlockCommand(CommandName, EndName)) { - setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, EndName); + const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName); + if (!Info) { + formTokenWithChars(T, TokenPtr, tok::unknown_command); + T.setUnknownCommandName(CommandName); return; } - if (Traits.isVerbatimLineCommand(CommandName)) { - setupAndLexVerbatimLine(T, TokenPtr); + if (Info->IsVerbatimBlockCommand) { + setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info); + return; + } + if (Info->IsVerbatimLineCommand) { + setupAndLexVerbatimLine(T, TokenPtr, Info); return; } formTokenWithChars(T, TokenPtr, tok::command); - T.setCommandName(CommandName); + T.setCommandID(Info->getID()); return; } @@ -423,14 +428,15 @@ void Lexer::lexCommentText(Token &T) { void Lexer::setupAndLexVerbatimBlock(Token &T, const char *TextBegin, - char Marker, StringRef EndName) { + char Marker, const CommandInfo *Info) { + assert(Info->IsVerbatimBlockCommand); + VerbatimBlockEndCommandName.clear(); VerbatimBlockEndCommandName.append(Marker == '\\' ? "\\" : "@"); - VerbatimBlockEndCommandName.append(EndName); + VerbatimBlockEndCommandName.append(Info->EndCommandName); - StringRef Name(BufferPtr + 1, TextBegin - (BufferPtr + 1)); formTokenWithChars(T, TextBegin, tok::verbatim_block_begin); - T.setVerbatimBlockName(Name); + T.setVerbatimBlockID(Info->getID()); // If there is a newline following the verbatim opening command, skip the // newline so that we don't create an tok::verbatim_block_line with empty @@ -471,7 +477,7 @@ again: const char *End = BufferPtr + VerbatimBlockEndCommandName.size(); StringRef Name(BufferPtr + 1, End - (BufferPtr + 1)); formTokenWithChars(T, End, tok::verbatim_block_end); - T.setVerbatimBlockName(Name); + T.setVerbatimBlockID(Traits.getCommandInfo(Name)->getID()); State = LS_Normal; return; } else { @@ -501,10 +507,11 @@ void Lexer::lexVerbatimBlockBody(Token &T) { lexVerbatimBlockFirstLine(T); } -void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin) { - const StringRef Name(BufferPtr + 1, TextBegin - BufferPtr - 1); +void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin, + const CommandInfo *Info) { + assert(Info->IsVerbatimLineCommand); formTokenWithChars(T, TextBegin, tok::verbatim_line_name); - T.setVerbatimLineName(Name); + T.setVerbatimLineID(Info->getID()); State = LS_VerbatimLineText; } diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index 43abf6a476..f6acd9645f 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -132,8 +132,8 @@ class TextTokenRetokenizer { Result.setKind(tok::text); Result.setLength(TokLength); #ifndef NDEBUG - Result.TextPtr1 = "<UNSET>"; - Result.TextLen1 = 7; + Result.TextPtr = "<UNSET>"; + Result.IntVal = 7; #endif Result.setText(Text); } @@ -312,26 +312,26 @@ BlockCommandComment *Parser::parseBlockCommand() { BlockCommandComment *BC; bool IsParam = false; bool IsTParam = false; - unsigned NumArgs = 0; - if (Traits.isParamCommand(Tok.getCommandName())) { + const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); + if (Info->IsParamCommand) { IsParam = true; PC = S.actOnParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), - Tok.getCommandName()); - } if (Traits.isTParamCommand(Tok.getCommandName())) { + Tok.getCommandID()); + } if (Info->IsTParamCommand) { IsTParam = true; TPC = S.actOnTParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), - Tok.getCommandName()); + Tok.getCommandID()); } else { - NumArgs = Traits.getBlockCommandNumArgs(Tok.getCommandName()); BC = S.actOnBlockCommandStart(Tok.getLocation(), Tok.getEndLocation(), - Tok.getCommandName()); + Tok.getCommandID()); } consumeToken(); - if (Tok.is(tok::command) && Traits.isBlockCommand(Tok.getCommandName())) { + if (Tok.is(tok::command) && + Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand) { // Block command ahead. We can't nest block commands, so pretend that this // command has an empty argument. ParagraphComment *Paragraph = S.actOnParagraphComment( @@ -348,7 +348,7 @@ BlockCommandComment *Parser::parseBlockCommand() { } } - if (IsParam || IsTParam || NumArgs > 0) { + if (IsParam || IsTParam || Info->NumArgs > 0) { // In order to parse command arguments we need to retokenize a few // following text tokens. TextTokenRetokenizer Retokenizer(Allocator, *this); @@ -358,7 +358,7 @@ BlockCommandComment *Parser::parseBlockCommand() { else if (IsTParam) parseTParamCommandArgs(TPC, Retokenizer); else - parseBlockCommandArgs(BC, Retokenizer, NumArgs); + parseBlockCommandArgs(BC, Retokenizer, Info->NumArgs); Retokenizer.putBackLeftoverTokens(); } @@ -394,14 +394,14 @@ InlineCommandComment *Parser::parseInlineCommand() { if (ArgTokValid) { IC = S.actOnInlineCommand(CommandTok.getLocation(), CommandTok.getEndLocation(), - CommandTok.getCommandName(), + CommandTok.getCommandID(), ArgTok.getLocation(), ArgTok.getEndLocation(), ArgTok.getText()); } else { IC = S.actOnInlineCommand(CommandTok.getLocation(), CommandTok.getEndLocation(), - CommandTok.getCommandName()); + CommandTok.getCommandID()); } Retokenizer.putBackLeftoverTokens(); @@ -540,23 +540,24 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { assert(Content.size() != 0); break; // Block content or EOF ahead, finish this parapgaph. - case tok::command: - if (Traits.isBlockCommand(Tok.getCommandName())) { + case tok::unknown_command: + Content.push_back(S.actOnUnknownCommand(Tok.getLocation(), + Tok.getEndLocation(), + Tok.getUnknownCommandName())); + consumeToken(); + continue; + + case tok::command: { + const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); + if (Info->IsBlockCommand) { if (Content.size() == 0) return parseBlockCommand(); break; // Block command ahead, finish this parapgaph. } - if (Traits.isInlineCommand(Tok.getCommandName())) { - Content.push_back(parseInlineCommand()); - continue; - } - - // Not a block command, not an inline command ==> an unknown command. - Content.push_back(S.actOnUnknownCommand(Tok.getLocation(), - Tok.getEndLocation(), - Tok.getCommandName())); - consumeToken(); + assert(Info->IsInlineCommand); + Content.push_back(parseInlineCommand()); continue; + } case tok::newline: { consumeToken(); @@ -606,7 +607,7 @@ VerbatimBlockComment *Parser::parseVerbatimBlock() { VerbatimBlockComment *VB = S.actOnVerbatimBlockStart(Tok.getLocation(), - Tok.getVerbatimBlockName()); + Tok.getVerbatimBlockID()); consumeToken(); // Don't create an empty line if verbatim opening command is followed @@ -634,8 +635,9 @@ VerbatimBlockComment *Parser::parseVerbatimBlock() { } if (Tok.is(tok::verbatim_block_end)) { + const CommandInfo *Info = Traits.getCommandInfo(Tok.getVerbatimBlockID()); S.actOnVerbatimBlockFinish(VB, Tok.getLocation(), - Tok.getVerbatimBlockName(), + Info->Name, S.copyArray(llvm::makeArrayRef(Lines))); consumeToken(); } else { @@ -666,7 +668,7 @@ VerbatimLineComment *Parser::parseVerbatimLine() { } VerbatimLineComment *VL = S.actOnVerbatimLine(NameTok.getLocation(), - NameTok.getVerbatimLineName(), + NameTok.getVerbatimLineID(), TextBegin, Text); consumeToken(); @@ -676,6 +678,7 @@ VerbatimLineComment *Parser::parseVerbatimLine() { BlockContentComment *Parser::parseBlockContent() { switch (Tok.getKind()) { case tok::text: + case tok::unknown_command: case tok::command: case tok::html_start_tag: case tok::html_end_tag: diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index ffb6e86788..953afe147e 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -23,7 +23,7 @@ namespace { } // unnamed namespace Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags, const CommandTraits &Traits) : + DiagnosticsEngine &Diags, CommandTraits &Traits) : Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { } @@ -44,8 +44,8 @@ ParagraphComment *Sema::actOnParagraphComment( BlockCommandComment *Sema::actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) { - return new (Allocator) BlockCommandComment(LocBegin, LocEnd, Name); + unsigned CommandID) { + return new (Allocator) BlockCommandComment(LocBegin, LocEnd, CommandID); } void Sema::actOnBlockCommandArgs(BlockCommandComment *Command, @@ -63,14 +63,14 @@ void Sema::actOnBlockCommandFinish(BlockCommandComment *Command, ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) { + unsigned CommandID) { ParamCommandComment *Command = - new (Allocator) ParamCommandComment(LocBegin, LocEnd, Name); + new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID); if (!isFunctionDecl()) Diag(Command->getLocation(), diag::warn_doc_param_not_attached_to_a_function_decl) - << Command->getCommandNameRange(); + << Command->getCommandNameRange(Traits); return Command; } @@ -156,14 +156,14 @@ void Sema::actOnParamCommandFinish(ParamCommandComment *Command, TParamCommandComment *Sema::actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) { + unsigned CommandID) { TParamCommandComment *Command = - new (Allocator) TParamCommandComment(LocBegin, LocEnd, Name); + new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID); if (!isTemplateOrSpecialization()) Diag(Command->getLocation(), diag::warn_doc_tparam_not_attached_to_a_template_decl) - << Command->getCommandNameRange(); + << Command->getCommandNameRange(Traits); return Command; } @@ -239,19 +239,20 @@ void Sema::actOnTParamCommandFinish(TParamCommandComment *Command, InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - StringRef CommandName) { + unsigned CommandID) { ArrayRef<InlineCommandComment::Argument> Args; + StringRef CommandName = Traits.getCommandInfo(CommandID)->Name; return new (Allocator) InlineCommandComment( CommandLocBegin, CommandLocEnd, - CommandName, + CommandID, getInlineCommandRenderKind(CommandName), Args); } InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - StringRef CommandName, + unsigned CommandID, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg) { @@ -259,11 +260,12 @@ InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin, Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin, ArgLocEnd), Arg); + StringRef CommandName = Traits.getCommandInfo(CommandID)->Name; return new (Allocator) InlineCommandComment( CommandLocBegin, CommandLocEnd, - CommandName, + CommandID, getInlineCommandRenderKind(CommandName), llvm::makeArrayRef(A, 1)); } @@ -272,8 +274,9 @@ InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Name) { ArrayRef<InlineCommandComment::Argument> Args; + unsigned CommandID = Traits.registerUnknownCommand(Name)->getID(); return new (Allocator) InlineCommandComment( - LocBegin, LocEnd, Name, + LocBegin, LocEnd, CommandID, InlineCommandComment::RenderNormal, Args); } @@ -285,11 +288,12 @@ TextComment *Sema::actOnText(SourceLocation LocBegin, } VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc, - StringRef Name) { + unsigned CommandID) { + StringRef CommandName = Traits.getCommandInfo(CommandID)->Name; return new (Allocator) VerbatimBlockComment( Loc, - Loc.getLocWithOffset(1 + Name.size()), - Name); + Loc.getLocWithOffset(1 + CommandName.size()), + CommandID); } VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc, @@ -307,13 +311,13 @@ void Sema::actOnVerbatimBlockFinish( } VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin, - StringRef Name, + unsigned CommandID, SourceLocation TextBegin, StringRef Text) { return new (Allocator) VerbatimLineComment( LocBegin, TextBegin.getLocWithOffset(Text.size()), - Name, + CommandID, TextBegin, Text); } @@ -411,15 +415,15 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { if (Command->getNumArgs() > 0) DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd(); if (!DiagLoc.isValid()) - DiagLoc = Command->getCommandNameRange().getEnd(); + DiagLoc = Command->getCommandNameRange(Traits).getEnd(); Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph) - << Command->getCommandName() + << Command->getCommandName(Traits) << Command->getSourceRange(); } } void Sema::checkReturnsCommand(const BlockCommandComment *Command) { - if (!Traits.isReturnsCommand(Command->getCommandName())) + if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand) return; if (isFunctionDecl()) { if (ThisDeclInfo->ResultType->isVoidType()) { @@ -440,7 +444,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } Diag(Command->getLocation(), diag::warn_doc_returns_attached_to_a_void_function) - << Command->getCommandName() + << Command->getCommandName(Traits) << DiagKind << Command->getSourceRange(); } @@ -448,20 +452,20 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) - << Command->getCommandName() + << Command->getCommandName(Traits) << Command->getSourceRange(); } void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { - StringRef Name = Command->getCommandName(); + const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID()); const BlockCommandComment *PrevCommand = NULL; - if (Traits.isBriefCommand(Name)) { + if (Info->IsBriefCommand) { if (!BriefCommand) { BriefCommand = Command; return; } PrevCommand = BriefCommand; - } else if (Traits.isReturnsCommand(Name)) { + } else if (Info->IsReturnsCommand) { if (!ReturnsCommand) { ReturnsCommand = Command; return; @@ -471,18 +475,20 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { // We don't want to check this command for duplicates. return; } + StringRef CommandName = Command->getCommandName(Traits); + StringRef PrevCommandName = PrevCommand->getCommandName(Traits); Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate) - << Name + << CommandName << Command->getSourceRange(); - if (Name == PrevCommand->getCommandName()) + if (CommandName == PrevCommandName) Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous) - << PrevCommand->getCommandName() - << Command->getSourceRange(); + << PrevCommandName + << PrevCommand->getSourceRange(); else Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous_alias) - << PrevCommand->getCommandName() - << Name; + << PrevCommandName + << CommandName; } void Sema::resolveParamCommandIndexes(const FullComment *FC) { @@ -740,7 +746,7 @@ StringRef Sema::correctTypoInTParamReference( InlineCommandComment::RenderKind Sema::getInlineCommandRenderKind(StringRef Name) const { - assert(Traits.isInlineCommand(Name)); + assert(Traits.getCommandInfo(Name)->IsInlineCommand); return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name) .Case("b", InlineCommandComment::RenderBold) diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp index ae5740e5b9..28ef6112b8 100644 --- a/lib/AST/RawCommentList.cpp +++ b/lib/AST/RawCommentList.cpp @@ -143,10 +143,10 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const { // a separate allocator for all temporary stuff. llvm::BumpPtrAllocator Allocator; - comments::CommandTraits Traits; - comments::Lexer L(Allocator, Traits, Range.getBegin(), + comments::Lexer L(Allocator, Context.getCommentCommandTraits(), + Range.getBegin(), RawText.begin(), RawText.end()); - comments::BriefParser P(L, Traits); + comments::BriefParser P(L, Context.getCommentCommandTraits()); const std::string Result = P.Parse(); const unsigned BriefTextLength = Result.size(); @@ -163,15 +163,16 @@ comments::FullComment *RawComment::parse(const ASTContext &Context, // Make sure that RawText is valid. getRawText(Context.getSourceManager()); - comments::CommandTraits Traits; - comments::Lexer L(Context.getAllocator(), Traits, + comments::Lexer L(Context.getAllocator(), Context.getCommentCommandTraits(), getSourceRange().getBegin(), RawText.begin(), RawText.end()); comments::Sema S(Context.getAllocator(), Context.getSourceManager(), - Context.getDiagnostics(), Traits); + Context.getDiagnostics(), + Context.getCommentCommandTraits()); S.setDecl(D); comments::Parser P(L, S, Context.getAllocator(), Context.getSourceManager(), - Context.getDiagnostics(), Traits); + Context.getDiagnostics(), + Context.getCommentCommandTraits()); return P.parseFullComment(); } diff --git a/test/Index/annotate-comments.cpp b/test/Index/annotate-comments.cpp index 1dc700151a..18754c3e0a 100644 --- a/test/Index/annotate-comments.cpp +++ b/test/Index/annotate-comments.cpp @@ -370,27 +370,30 @@ void comment_to_html_conversion_24(); /// Blah blah. void comment_to_html_conversion_25(); -/// \b Aaa +/// \unknown void comment_to_html_conversion_26(); -/// \c Aaa \p Bbb +/// \b Aaa void comment_to_html_conversion_27(); -/// \a Aaa \e Bbb \em Ccc +/// \c Aaa \p Bbb void comment_to_html_conversion_28(); -/// \a 1<2 \e 3<4 \em 5<6 \param 7<8 aaa \tparam 9<10 bbb +/// \a Aaa \e Bbb \em Ccc void comment_to_html_conversion_29(); -/// \\ \@ \& \$ \# \< \> \% \" \. \:: +/// \a 1<2 \e 3<4 \em 5<6 \param 7<8 aaa \tparam 9<10 bbb void comment_to_html_conversion_30(); -/// & < > " +/// \\ \@ \& \$ \# \< \> \% \" \. \:: void comment_to_html_conversion_31(); -/// <em>0<i</em> +/// & < > " void comment_to_html_conversion_32(); +/// <em>0<i</em> +void comment_to_html_conversion_33(); + /// Aaa. class comment_to_xml_conversion_01 { /// \param aaa Blah blah. @@ -838,13 +841,19 @@ enum class comment_to_xml_conversion_17 { // CHECK: (CXComment_VerbatimLine Text=[ foo]) // CHECK: (CXComment_Paragraph // CHECK: (CXComment_Text Text=[ Blah blah.])))] -// CHECK: annotate-comments.cpp:374:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <b>Aaa</b></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="374" column="6"><Name>comment_to_html_conversion_26</Name><USR>c:@F@comment_to_html_conversion_26#</USR><Abstract><Para> <bold>Aaa</bold></Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:374:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[<p class="para-brief"> </p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="374" column="6"><Name>comment_to_html_conversion_26</Name><USR>c:@F@comment_to_html_conversion_26#</USR><Abstract><Para> </Para></Abstract></Function>] +// CHECK: CommentAST=[ +// CHECK: (CXComment_FullComment +// CHECK: (CXComment_Paragraph +// CHECK: (CXComment_Text Text=[ ] IsWhitespace) +// CHECK: (CXComment_InlineCommand CommandName=[unknown] RenderNormal)))] +// CHECK: annotate-comments.cpp:377:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <b>Aaa</b></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="377" column="6"><Name>comment_to_html_conversion_27</Name><USR>c:@F@comment_to_html_conversion_27#</USR><Abstract><Para> <bold>Aaa</bold></Para></Abstract></Function>] // 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:377:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="377" column="6"><Name>comment_to_html_conversion_27</Name><USR>c:@F@comment_to_html_conversion_27#</USR><Abstract><Para> <monospaced>Aaa</monospaced> <monospaced>Bbb</monospaced></Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:380:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <tt>Aaa</tt> <tt>Bbb</tt></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="380" column="6"><Name>comment_to_html_conversion_28</Name><USR>c:@F@comment_to_html_conversion_28#</USR><Abstract><Para> <monospaced>Aaa</monospaced> <monospaced>Bbb</monospaced></Para></Abstract></Function>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -852,7 +861,7 @@ enum class comment_to_xml_conversion_17 { // 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:380:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="380" column="6"><Name>comment_to_html_conversion_28</Name><USR>c:@F@comment_to_html_conversion_28#</USR><Abstract><Para> <emphasized>Aaa</emphasized> <emphasized>Bbb</emphasized> <emphasized>Ccc</emphasized></Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:383:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>Aaa</em> <em>Bbb</em> <em>Ccc</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="383" column="6"><Name>comment_to_html_conversion_29</Name><USR>c:@F@comment_to_html_conversion_29#</USR><Abstract><Para> <emphasized>Aaa</emphasized> <emphasized>Bbb</emphasized> <emphasized>Ccc</emphasized></Para></Abstract></Function>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -862,7 +871,7 @@ enum class comment_to_xml_conversion_17 { // 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:383:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>1<2</em> <em>3<4</em> <em>5<6</em> </p><dl><dt class="tparam-name-index-invalid">9<10</dt><dd class="tparam-descr-index-invalid"> bbb</dd></dl><dl><dt class="param-name-index-invalid">7<8</dt><dd class="param-descr-index-invalid"> aaa </dd></dl>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="383" column="6"><Name>comment_to_html_conversion_29</Name><USR>c:@F@comment_to_html_conversion_29#</USR><Abstract><Para> <emphasized>1<2</emphasized> <emphasized>3<4</emphasized> <emphasized>5<6</emphasized> </Para></Abstract><TemplateParameters><Parameter><Name>9<10</Name><Discussion><Para> bbb</Para></Discussion></Parameter></TemplateParameters><Parameters><Parameter><Name>7<8</Name><Direction isExplicit="0">in</Direction><Discussion><Para> aaa </Para></Discussion></Parameter></Parameters></Function>] +// CHECK: annotate-comments.cpp:386:6: FunctionDecl=comment_to_html_conversion_30:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>1<2</em> <em>3<4</em> <em>5<6</em> </p><dl><dt class="tparam-name-index-invalid">9<10</dt><dd class="tparam-descr-index-invalid"> bbb</dd></dl><dl><dt class="param-name-index-invalid">7<8</dt><dd class="param-descr-index-invalid"> aaa </dd></dl>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="386" column="6"><Name>comment_to_html_conversion_30</Name><USR>c:@F@comment_to_html_conversion_30#</USR><Abstract><Para> <emphasized>1<2</emphasized> <emphasized>3<4</emphasized> <emphasized>5<6</emphasized> </Para></Abstract><TemplateParameters><Parameter><Name>9<10</Name><Discussion><Para> bbb</Para></Discussion></Parameter></TemplateParameters><Parameters><Parameter><Name>7<8</Name><Direction isExplicit="0">in</Direction><Discussion><Para> aaa </Para></Discussion></Parameter></Parameters></Function>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -879,7 +888,7 @@ enum class comment_to_xml_conversion_17 { // CHECK-NEXT: (CXComment_TParamCommand ParamName=[9<10] ParamPosition=Invalid // CHECK-NEXT: (CXComment_Paragraph // CHECK-NEXT: (CXComment_Text Text=[ bbb]))))] -// CHECK: annotate-comments.cpp:386:6: FunctionDecl=comment_to_html_conversion_30:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ & $ # < > % " . ::</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="386" column="6"><Name>comment_to_html_conversion_30</Name><USR>c:@F@comment_to_html_conversion_30#</USR><Abstract><Para> \ @ & $ # < > % " . ::</Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:389:6: FunctionDecl=comment_to_html_conversion_31:{{.*}} FullCommentAsHTML=[<p class="para-brief"> \ @ & $ # < > % " . ::</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="389" column="6"><Name>comment_to_html_conversion_31</Name><USR>c:@F@comment_to_html_conversion_31#</USR><Abstract><Para> \ @ & $ # < > % " . ::</Para></Abstract></Function>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -905,7 +914,7 @@ enum class comment_to_xml_conversion_17 { // CHECK-NEXT: (CXComment_Text Text=[.]) // CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace) // CHECK-NEXT: (CXComment_Text Text=[::])))] -// CHECK: annotate-comments.cpp:389:6: FunctionDecl=comment_to_html_conversion_31:{{.*}} FullCommentAsHTML=[<p class="para-brief"> & < > "</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="389" column="6"><Name>comment_to_html_conversion_31</Name><USR>c:@F@comment_to_html_conversion_31#</USR><Abstract><Para> & < > "</Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:392:6: FunctionDecl=comment_to_html_conversion_32:{{.*}} FullCommentAsHTML=[<p class="para-brief"> & < > "</p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="392" column="6"><Name>comment_to_html_conversion_32</Name><USR>c:@F@comment_to_html_conversion_32#</USR><Abstract><Para> & < > "</Para></Abstract></Function>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -917,7 +926,7 @@ enum class comment_to_xml_conversion_17 { // CHECK-NEXT: (CXComment_Text Text=[>]) // CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace) // CHECK-NEXT: (CXComment_Text Text=["])))] -// CHECK: annotate-comments.cpp:392:6: FunctionDecl=comment_to_html_conversion_32:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>0<i</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="392" column="6"><Name>comment_to_html_conversion_32</Name><USR>c:@F@comment_to_html_conversion_32#</USR><Abstract><Para> <rawHTML><![CDATA[<em>]]></rawHTML>0<i<rawHTML></em></rawHTML></Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:395:6: FunctionDecl=comment_to_html_conversion_33:{{.*}} FullCommentAsHTML=[<p class="para-brief"> <em>0<i</em></p>] FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments.cpp" line="395" column="6"><Name>comment_to_html_conversion_33</Name><USR>c:@F@comment_to_html_conversion_33#</USR><Abstract><Para> <rawHTML><![CDATA[<em>]]></rawHTML>0<i<rawHTML></em></rawHTML></Para></Abstract></Function>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -928,27 +937,27 @@ enum class comment_to_xml_conversion_17 { // CHECK-NEXT: (CXComment_Text Text=[i]) // CHECK-NEXT: (CXComment_HTMLEndTag Name=[em])))] -// CHECK: annotate-comments.cpp:395:7: ClassDecl=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Class file="{{[^"]+}}annotate-comments.cpp" line="395" column="7"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] -// CHECK: annotate-comments.cpp:397:3: CXXConstructor=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="397" column="3"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_01#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] -// CHECK: annotate-comments.cpp:400:3: CXXDestructor=~comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="400" column="3"><Name>~comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@~comment_to_xml_conversion_01#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] -// CHECK: annotate-comments.cpp:403:7: CXXMethod=comment_to_xml_conversion_02:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="403" column="7"><Name>comment_to_xml_conversion_02</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_02#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] -// CHECK: annotate-comments.cpp:406:14: CXXMethod=comment_to_xml_conversion_03:{{.*}} FullCommentAsXML=[<Function isClassMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="406" column="14"><Name>comment_to_xml_conversion_03</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_03#I#S</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] -// CHECK: annotate-comments.cpp:409:7: FieldDecl=comment_to_xml_conversion_04:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="409" column="7"><Name>comment_to_xml_conversion_04</Name><USR>c:@C@comment_to_xml_conversion_01@FI@comment_to_xml_conversion_04</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] -// CHECK: annotate-comments.cpp:412:14: VarDecl=comment_to_xml_conversion_05:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="412" column="14"><Name>comment_to_xml_conversion_05</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_05</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] -// CHECK: annotate-comments.cpp:415:8: CXXMethod=operator():{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="415" column="8"><Name>operator()</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator()#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] -// CHECK: annotate-comments.cpp:418:3: CXXConversion=operator _Bool:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="418" column="3"><Name>operator _Bool</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator _Bool#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] -// CHECK: annotate-comments.cpp:421:15: TypedefDecl=comment_to_xml_conversion_06:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="421" column="15"><Name>comment_to_xml_conversion_06</Name><USR>c:annotate-comments.cpp@8453@C@comment_to_xml_conversion_01@T@comment_to_xml_conversion_06</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>] -// CHECK: annotate-comments.cpp:424:9: TypeAliasDecl=comment_to_xml_conversion_07:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="424" column="9"><Name>comment_to_xml_conversion_07</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_07</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>] -// CHECK: annotate-comments.cpp:431:3: UnexposedDecl=comment_to_xml_conversion_09:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="431" column="3"><Name>comment_to_xml_conversion_09</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_09</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>] -// CHECK: annotate-comments.cpp:436:6: FunctionTemplate=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="436" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@FT@>2#T#Tcomment_to_xml_conversion_10#t0.0#t0.1#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] -// CHECK: annotate-comments.cpp:440:6: FunctionDecl=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="440" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@F@comment_to_xml_conversion_10<#I#I>#I#I#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] -// CHECK: annotate-comments.cpp:444:7: ClassTemplate=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="444" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CT>2#T#T@comment_to_xml_conversion_11</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] -// CHECK: annotate-comments.cpp:448:7: ClassTemplatePartialSpecialization=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="partialSpecialization" file="{{[^"]+}}annotate-comments.cpp" line="448" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CP>1#T@comment_to_xml_conversion_11>#t0.0#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] -// CHECK: annotate-comments.cpp:452:7: ClassDecl=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="452" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@C@comment_to_xml_conversion_11>#I#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] -// CHECK: annotate-comments.cpp:455:5: VarDecl=comment_to_xml_conversion_12:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="455" column="5"><Name>comment_to_xml_conversion_12</Name><USR>c:@comment_to_xml_conversion_12</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] -// CHECK: annotate-comments.cpp:458:11: Namespace=comment_to_xml_conversion_13:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="458" column="11"><Name>comment_to_xml_conversion_13</Name><USR>c:@N@comment_to_xml_conversion_13</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>] -// CHECK: annotate-comments.cpp:460:13: Namespace=comment_to_xml_conversion_14:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="460" column="13"><Name>comment_to_xml_conversion_14</Name><USR>c:@N@comment_to_xml_conversion_13@N@comment_to_xml_conversion_14</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>] -// CHECK: annotate-comments.cpp:465:6: EnumDecl=comment_to_xml_conversion_15:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="465" column="6"><Name>comment_to_xml_conversion_15</Name><USR>c:@E@comment_to_xml_conversion_15</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>] -// CHECK: annotate-comments.cpp:467:3: EnumConstantDecl=comment_to_xml_conversion_16:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="467" column="3"><Name>comment_to_xml_conversion_16</Name><USR>c:@E@comment_to_xml_conversion_15@comment_to_xml_conversion_16</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] -// CHECK: annotate-comments.cpp:471:12: EnumDecl=comment_to_xml_conversion_17:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="471" column="12"><Name>comment_to_xml_conversion_17</Name><USR>c:@E@comment_to_xml_conversion_17</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>] -// CHECK: annotate-comments.cpp:473:3: EnumConstantDecl=comment_to_xml_conversion_18:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="473" column="3"><Name>comment_to_xml_conversion_18</Name><USR>c:@E@comment_to_xml_conversion_17@comment_to_xml_conversion_18</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] +// CHECK: annotate-comments.cpp:398:7: ClassDecl=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Class file="{{[^"]+}}annotate-comments.cpp" line="398" column="7"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] +// CHECK: annotate-comments.cpp:400:3: CXXConstructor=comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="400" column="3"><Name>comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_01#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] +// CHECK: annotate-comments.cpp:403:3: CXXDestructor=~comment_to_xml_conversion_01:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="403" column="3"><Name>~comment_to_xml_conversion_01</Name><USR>c:@C@comment_to_xml_conversion_01@F@~comment_to_xml_conversion_01#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:406:7: CXXMethod=comment_to_xml_conversion_02:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="406" column="7"><Name>comment_to_xml_conversion_02</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_02#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] +// CHECK: annotate-comments.cpp:409:14: CXXMethod=comment_to_xml_conversion_03:{{.*}} FullCommentAsXML=[<Function isClassMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="409" column="14"><Name>comment_to_xml_conversion_03</Name><USR>c:@C@comment_to_xml_conversion_01@F@comment_to_xml_conversion_03#I#S</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] +// CHECK: annotate-comments.cpp:412:7: FieldDecl=comment_to_xml_conversion_04:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="412" column="7"><Name>comment_to_xml_conversion_04</Name><USR>c:@C@comment_to_xml_conversion_01@FI@comment_to_xml_conversion_04</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] +// CHECK: annotate-comments.cpp:415:14: VarDecl=comment_to_xml_conversion_05:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="415" column="14"><Name>comment_to_xml_conversion_05</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_05</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] +// CHECK: annotate-comments.cpp:418:8: CXXMethod=operator():{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="418" column="8"><Name>operator()</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator()#I#</USR><Parameters><Parameter><Name>aaa</Name><Index>0</Index><Direction isExplicit="0">in</Direction><Discussion><Para> Blah blah.</Para></Discussion></Parameter></Parameters></Function>] +// CHECK: annotate-comments.cpp:421:3: CXXConversion=operator _Bool:{{.*}} FullCommentAsXML=[<Function isInstanceMethod="1" file="{{[^"]+}}annotate-comments.cpp" line="421" column="3"><Name>operator _Bool</Name><USR>c:@C@comment_to_xml_conversion_01@F@operator _Bool#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:424:15: TypedefDecl=comment_to_xml_conversion_06:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="424" column="15"><Name>comment_to_xml_conversion_06</Name><USR>c:annotate-comments.cpp@8505@C@comment_to_xml_conversion_01@T@comment_to_xml_conversion_06</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>] +// CHECK: annotate-comments.cpp:427:9: TypeAliasDecl=comment_to_xml_conversion_07:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="427" column="9"><Name>comment_to_xml_conversion_07</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_07</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>] +// CHECK: annotate-comments.cpp:434:3: UnexposedDecl=comment_to_xml_conversion_09:{{.*}} FullCommentAsXML=[<Typedef file="{{[^"]+}}annotate-comments.cpp" line="434" column="3"><Name>comment_to_xml_conversion_09</Name><USR>c:@C@comment_to_xml_conversion_01@comment_to_xml_conversion_09</USR><Abstract><Para> Aaa.</Para></Abstract></Typedef>] +// CHECK: annotate-comments.cpp:439:6: FunctionTemplate=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="439" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@FT@>2#T#Tcomment_to_xml_conversion_10#t0.0#t0.1#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:443:6: FunctionDecl=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="443" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@F@comment_to_xml_conversion_10<#I#I>#I#I#</USR><Abstract><Para> Aaa.</Para></Abstract></Function>] +// CHECK: annotate-comments.cpp:447:7: ClassTemplate=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="template" file="{{[^"]+}}annotate-comments.cpp" line="447" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CT>2#T#T@comment_to_xml_conversion_11</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] +// CHECK: annotate-comments.cpp:451:7: ClassTemplatePartialSpecialization=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="partialSpecialization" file="{{[^"]+}}annotate-comments.cpp" line="451" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@CP>1#T@comment_to_xml_conversion_11>#t0.0#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] +// CHECK: annotate-comments.cpp:455:7: ClassDecl=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="specialization" file="{{[^"]+}}annotate-comments.cpp" line="455" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@C@comment_to_xml_conversion_11>#I#I</USR><Abstract><Para> Aaa.</Para></Abstract></Class>] +// CHECK: annotate-comments.cpp:458:5: VarDecl=comment_to_xml_conversion_12:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="458" column="5"><Name>comment_to_xml_conversion_12</Name><USR>c:@comment_to_xml_conversion_12</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] +// CHECK: annotate-comments.cpp:461:11: Namespace=comment_to_xml_conversion_13:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="461" column="11"><Name>comment_to_xml_conversion_13</Name><USR>c:@N@comment_to_xml_conversion_13</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>] +// CHECK: annotate-comments.cpp:463:13: Namespace=comment_to_xml_conversion_14:{{.*}} FullCommentAsXML=[<Namespace file="{{[^"]+}}annotate-comments.cpp" line="463" column="13"><Name>comment_to_xml_conversion_14</Name><USR>c:@N@comment_to_xml_conversion_13@N@comment_to_xml_conversion_14</USR><Abstract><Para> Aaa.</Para></Abstract></Namespace>] +// CHECK: annotate-comments.cpp:468:6: EnumDecl=comment_to_xml_conversion_15:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="468" column="6"><Name>comment_to_xml_conversion_15</Name><USR>c:@E@comment_to_xml_conversion_15</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>] +// CHECK: annotate-comments.cpp:470:3: EnumConstantDecl=comment_to_xml_conversion_16:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="470" column="3"><Name>comment_to_xml_conversion_16</Name><USR>c:@E@comment_to_xml_conversion_15@comment_to_xml_conversion_16</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] +// CHECK: annotate-comments.cpp:474:12: EnumDecl=comment_to_xml_conversion_17:{{.*}} FullCommentAsXML=[<Enum file="{{[^"]+}}annotate-comments.cpp" line="474" column="12"><Name>comment_to_xml_conversion_17</Name><USR>c:@E@comment_to_xml_conversion_17</USR><Abstract><Para> Aaa.</Para></Abstract></Enum>] +// CHECK: annotate-comments.cpp:476:3: EnumConstantDecl=comment_to_xml_conversion_18:{{.*}} FullCommentAsXML=[<Variable file="{{[^"]+}}annotate-comments.cpp" line="476" column="3"><Name>comment_to_xml_conversion_18</Name><USR>c:@E@comment_to_xml_conversion_17@comment_to_xml_conversion_18</USR><Abstract><Para> Aaa.</Para></Abstract></Variable>] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 511f1a90bb..85dcddd91c 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -512,8 +512,7 @@ static void ValidateCommentXML(const char *Str, #endif } -static void PrintCursorComments(CXTranslationUnit TU, - CXCursor Cursor, +static void PrintCursorComments(CXCursor Cursor, CommentXMLValidationData *ValidationData) { { CXString RawComment; @@ -543,7 +542,7 @@ static void PrintCursorComments(CXTranslationUnit TU, clang_FullComment_getAsHTML(Comment)); { CXString XML; - XML = clang_FullComment_getAsXML(TU, Comment); + XML = clang_FullComment_getAsXML(Comment); PrintCXStringWithPrefix("FullCommentAsXML", XML); ValidateCommentXML(clang_getCString(XML), ValidationData); clang_disposeString(XML); @@ -781,7 +780,7 @@ static void PrintCursor(CXCursor Cursor, PrintRange(RefNameRange, "RefName"); } - PrintCursorComments(TU, Cursor, ValidationData); + PrintCursorComments(Cursor, ValidationData); } } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index ae488abf39..6cf40fd7f7 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -5800,13 +5800,13 @@ CXString clang_Cursor_getBriefCommentText(CXCursor C) { CXComment clang_Cursor_getParsedComment(CXCursor C) { if (!clang_isDeclaration(C.kind)) - return cxcomment::createCXComment(NULL); + return cxcomment::createCXComment(NULL, NULL); const Decl *D = getCursorDecl(C); const ASTContext &Context = getCursorContext(C); const comments::FullComment *FC = Context.getCommentForDecl(D); - return cxcomment::createCXComment(FC); + return cxcomment::createCXComment(FC, getCursorTU(C)); } } // end: extern "C" diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp index c5c9ca8cf3..4e26a9e984 100644 --- a/tools/libclang/CXComment.cpp +++ b/tools/libclang/CXComment.cpp @@ -15,12 +15,10 @@ #include "CXString.h" #include "CXComment.h" #include "CXCursor.h" -#include "CXTranslationUnit.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/Decl.h" -#include "clang/Frontend/ASTUnit.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" @@ -94,9 +92,9 @@ unsigned clang_Comment_getNumChildren(CXComment CXC) { CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) { const Comment *C = getASTNode(CXC); if (!C || ChildIdx >= C->child_count()) - return createCXComment(NULL); + return createCXComment(NULL, NULL); - return createCXComment(*(C->child_begin() + ChildIdx)); + return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit); } unsigned clang_Comment_isWhitespace(CXComment CXC) { @@ -134,7 +132,8 @@ CXString clang_InlineCommandComment_getCommandName(CXComment CXC) { if (!ICC) return createCXString((const char *) 0); - return createCXString(ICC->getCommandName(), /*DupString=*/ false); + const CommandTraits &Traits = getCommandTraits(CXC); + return createCXString(ICC->getCommandName(Traits), /*DupString=*/ false); } enum CXCommentInlineCommandRenderKind @@ -221,7 +220,8 @@ CXString clang_BlockCommandComment_getCommandName(CXComment CXC) { if (!BCC) return createCXString((const char *) 0); - return createCXString(BCC->getCommandName(), /*DupString=*/ false); + const CommandTraits &Traits = getCommandTraits(CXC); + return createCXString(BCC->getCommandName(Traits), /*DupString=*/ false); } unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) { @@ -244,9 +244,9 @@ CXString clang_BlockCommandComment_getArgText(CXComment CXC, CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) { const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC); if (!BCC) - return createCXComment(NULL); + return createCXComment(NULL, NULL); - return createCXComment(BCC->getParagraph()); + return createCXComment(BCC->getParagraph(), CXC.TranslationUnit); } CXString clang_ParamCommandComment_getParamName(CXComment CXC) { @@ -405,7 +405,8 @@ public: /// Separate parts of a FullComment. struct FullCommentParts { /// Take a full comment apart and initialize members accordingly. - FullCommentParts(const FullComment *C); + FullCommentParts(const FullComment *C, + const CommandTraits &Traits); const BlockContentComment *Brief; const ParagraphComment *FirstParagraph; @@ -415,9 +416,9 @@ struct FullCommentParts { SmallVector<const BlockContentComment *, 8> MiscBlocks; }; -FullCommentParts::FullCommentParts(const FullComment *C) : +FullCommentParts::FullCommentParts(const FullComment *C, + const CommandTraits &Traits) : Brief(NULL), FirstParagraph(NULL), Returns(NULL) { - const CommandTraits Traits; for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E; ++I) { const Comment *Child = *I; @@ -440,12 +441,12 @@ FullCommentParts::FullCommentParts(const FullComment *C) : case Comment::BlockCommandCommentKind: { const BlockCommandComment *BCC = cast<BlockCommandComment>(Child); - StringRef CommandName = BCC->getCommandName(); - if (!Brief && Traits.isBriefCommand(CommandName)) { + const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID()); + if (!Brief && Info->IsBriefCommand) { Brief = BCC; break; } - if (!Returns && Traits.isReturnsCommand(CommandName)) { + if (!Returns && Info->IsReturnsCommand) { Returns = BCC; break; } @@ -483,7 +484,8 @@ FullCommentParts::FullCommentParts(const FullComment *C) : case Comment::VerbatimLineCommentKind: { const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child); - if (!Traits.isDeclarationCommand(VLC->getCommandName())) + const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID()); + if (!Info->IsDeclarationCommand) MiscBlocks.push_back(VLC); break; } @@ -533,7 +535,10 @@ class CommentASTToHTMLConverter : public ConstCommentVisitor<CommentASTToHTMLConverter> { public: /// \param Str accumulator for HTML. - CommentASTToHTMLConverter(SmallVectorImpl<char> &Str) : Result(Str) { } + CommentASTToHTMLConverter(SmallVectorImpl<char> &Str, + const CommandTraits &Traits) : + Result(Str), Traits(Traits) + { } // Inline content. void visitTextComment(const TextComment *C); @@ -561,10 +566,10 @@ public: void appendToResultWithHTMLEscaping(StringRef S); private: - const CommandTraits Traits; - /// Output stream for HTML. llvm::raw_svector_ostream Result; + + const CommandTraits &Traits; }; } // end unnamed namespace @@ -637,14 +642,14 @@ void CommentASTToHTMLConverter::visitParagraphComment( void CommentASTToHTMLConverter::visitBlockCommandComment( const BlockCommandComment *C) { - StringRef CommandName = C->getCommandName(); - if (Traits.isBriefCommand(CommandName)) { + const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID()); + if (Info->IsBriefCommand) { Result << "<p class=\"para-brief\">"; visitNonStandaloneParagraphComment(C->getParagraph()); Result << "</p>"; return; } - if (Traits.isReturnsCommand(CommandName)) { + if (Info->IsReturnsCommand) { Result << "<p class=\"para-returns\">" "<span class=\"word-returns\">Returns</span> "; visitNonStandaloneParagraphComment(C->getParagraph()); @@ -735,7 +740,7 @@ void CommentASTToHTMLConverter::visitVerbatimLineComment( } void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) { - FullCommentParts Parts(C); + FullCommentParts Parts(C, Traits); bool FirstParagraphIsBrief = false; if (Parts.Brief) @@ -822,7 +827,7 @@ CXString clang_HTMLTagComment_getAsString(CXComment CXC) { return createCXString((const char *) 0); SmallString<128> HTML; - CommentASTToHTMLConverter Converter(HTML); + CommentASTToHTMLConverter Converter(HTML, getCommandTraits(CXC)); Converter.visit(HTC); return createCXString(HTML.str(), /* DupString = */ true); } @@ -833,7 +838,7 @@ CXString clang_FullComment_getAsHTML(CXComment CXC) { return createCXString((const char *) 0); SmallString<1024> HTML; - CommentASTToHTMLConverter Converter(HTML); + CommentASTToHTMLConverter Converter(HTML, getCommandTraits(CXC)); Converter.visit(FC); return createCXString(HTML.str(), /* DupString = */ true); } @@ -845,9 +850,10 @@ class CommentASTToXMLConverter : public ConstCommentVisitor<CommentASTToXMLConverter> { public: /// \param Str accumulator for XML. - CommentASTToXMLConverter(const SourceManager &SM, - SmallVectorImpl<char> &Str) : - SM(SM), Result(Str) { } + CommentASTToXMLConverter(SmallVectorImpl<char> &Str, + const CommandTraits &Traits, + const SourceManager &SM) : + Result(Str), Traits(Traits), SM(SM) { } // Inline content. void visitTextComment(const TextComment *C); @@ -870,10 +876,11 @@ public: void appendToResultWithXMLEscaping(StringRef S); private: - const SourceManager &SM; - /// Output stream for XML. llvm::raw_svector_ostream Result; + + const CommandTraits &Traits; + const SourceManager &SM; }; } // end unnamed namespace @@ -991,7 +998,7 @@ void CommentASTToXMLConverter::visitVerbatimBlockComment( if (NumLines == 0) return; - Result << llvm::StringSwitch<const char *>(C->getCommandName()) + Result << llvm::StringSwitch<const char *>(C->getCommandName(Traits)) .Case("code", "<Verbatim xml:space=\"preserve\" kind=\"code\">") .Default("<Verbatim xml:space=\"preserve\" kind=\"verbatim\">"); for (unsigned i = 0; i != NumLines; ++i) { @@ -1015,7 +1022,7 @@ void CommentASTToXMLConverter::visitVerbatimLineComment( } void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { - FullCommentParts Parts(C); + FullCommentParts Parts(C, Traits); const DeclInfo *DI = C->getDeclInfo(); StringRef RootEndTag; @@ -1213,15 +1220,16 @@ void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) { extern "C" { -CXString clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) { +CXString clang_FullComment_getAsXML(CXComment CXC) { const FullComment *FC = getASTNodeAs<FullComment>(CXC); if (!FC) return createCXString((const char *) 0); + CXTranslationUnit TU = CXC.TranslationUnit; SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager(); SmallString<1024> XML; - CommentASTToXMLConverter Converter(SM, XML); + CommentASTToXMLConverter Converter(XML, getCommandTraits(CXC), SM); Converter.visit(FC); return createCXString(XML.str(), /* DupString = */ true); } diff --git a/tools/libclang/CXComment.h b/tools/libclang/CXComment.h index 753877e6c7..513431709f 100644 --- a/tools/libclang/CXComment.h +++ b/tools/libclang/CXComment.h @@ -15,20 +15,29 @@ #define LLVM_CLANG_CXCOMMENT_H #include "clang-c/Index.h" +#include "CXTranslationUnit.h" #include "clang/AST/Comment.h" +#include "clang/AST/ASTContext.h" +#include "clang/Frontend/ASTUnit.h" namespace clang { +namespace comments { + class CommandTraits; +} + namespace cxcomment { -inline CXComment createCXComment(const comments::Comment *C) { +inline CXComment createCXComment(const comments::Comment *C, + CXTranslationUnit TU) { CXComment Result; - Result.Data = C; + Result.ASTNode = C; + Result.TranslationUnit = TU; return Result; } inline const comments::Comment *getASTNode(CXComment CXC) { - return static_cast<const comments::Comment *>(CXC.Data); + return static_cast<const comments::Comment *>(CXC.ASTNode); } template<typename T> @@ -40,6 +49,14 @@ inline const T *getASTNodeAs(CXComment CXC) { return dyn_cast<T>(C); } +inline ASTContext &getASTContext(CXComment CXC) { + return static_cast<ASTUnit *>(CXC.TranslationUnit->TUData)->getASTContext(); +} + +inline comments::CommandTraits &getCommandTraits(CXComment CXC) { + return getASTContext(CXC).getCommentCommandTraits(); +} + } // end namespace cxcomment } // end namespace clang diff --git a/unittests/AST/CommentLexer.cpp b/unittests/AST/CommentLexer.cpp index b7bc078392..2ec741ba3d 100644 --- a/unittests/AST/CommentLexer.cpp +++ b/unittests/AST/CommentLexer.cpp @@ -30,7 +30,8 @@ protected: : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), Diags(DiagID, new IgnoringDiagConsumer()), - SourceMgr(Diags, FileMgr) { + SourceMgr(Diags, FileMgr), + Traits(Allocator) { } FileSystemOptions FileMgrOpts; @@ -39,8 +40,21 @@ protected: DiagnosticsEngine Diags; SourceManager SourceMgr; llvm::BumpPtrAllocator Allocator; + CommandTraits Traits; void lexString(const char *Source, std::vector<Token> &Toks); + + StringRef getCommandName(const Token &Tok) { + return Traits.getCommandInfo(Tok.getCommandID())->Name; + } + + StringRef getVerbatimBlockName(const Token &Tok) { + return Traits.getCommandInfo(Tok.getVerbatimBlockID())->Name; + } + + StringRef getVerbatimLineName(const Token &Tok) { + return Traits.getCommandInfo(Tok.getVerbatimLineID())->Name; + } }; void CommentLexerTest::lexString(const char *Source, @@ -49,9 +63,7 @@ void CommentLexerTest::lexString(const char *Source, FileID File = SourceMgr.createFileIDForMemBuffer(Buf); SourceLocation Begin = SourceMgr.getLocForStartOfFile(File); - comments::CommandTraits Traits; - comments::Lexer L(Allocator, Traits, Begin, - Source, Source + strlen(Source)); + Lexer L(Allocator, Traits, Begin, Source, Source + strlen(Source)); while (1) { Token Tok; @@ -322,7 +334,7 @@ TEST_F(CommentLexerTest, DoxygenCommand5) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::command, Toks[1].getKind()); - ASSERT_EQ(StringRef("brief"), Toks[1].getCommandName()); + ASSERT_EQ(StringRef("brief"), getCommandName(Toks[1])); ASSERT_EQ(tok::text, Toks[2].getKind()); ASSERT_EQ(StringRef(" Aaa."), Toks[2].getText()); @@ -331,6 +343,38 @@ TEST_F(CommentLexerTest, DoxygenCommand5) { } TEST_F(CommentLexerTest, DoxygenCommand6) { + const char *Source = "/// \\em\\em \\em\t\\em\n"; + std::vector<Token> Toks; + + lexString(Source, Toks); + + ASSERT_EQ(8U, Toks.size()); + + ASSERT_EQ(tok::text, Toks[0].getKind()); + ASSERT_EQ(StringRef(" "), Toks[0].getText()); + + ASSERT_EQ(tok::command, Toks[1].getKind()); + ASSERT_EQ(StringRef("em"), getCommandName(Toks[1])); + + ASSERT_EQ(tok::command, Toks[2].getKind()); + ASSERT_EQ(StringRef("em"), getCommandName(Toks[2])); + + ASSERT_EQ(tok::text, Toks[3].getKind()); + ASSERT_EQ(StringRef(" "), Toks[3].getText()); + + ASSERT_EQ(tok::command, Toks[4].getKind()); + ASSERT_EQ(StringRef("em"), getCommandName(Toks[4])); + + ASSERT_EQ(tok::text, Toks[5].getKind()); + ASSERT_EQ(StringRef("\t"), Toks[5].getText()); + + ASSERT_EQ(tok::command, Toks[6].getKind()); + ASSERT_EQ(StringRef("em"), getCommandName(Toks[6])); + + ASSERT_EQ(tok::newline, Toks[7].getKind()); +} + +TEST_F(CommentLexerTest, DoxygenCommand7) { const char *Source = "/// \\aaa\\bbb \\ccc\t\\ddd\n"; std::vector<Token> Toks; @@ -341,28 +385,28 @@ TEST_F(CommentLexerTest, DoxygenCommand6) { ASSERT_EQ(tok::text, Toks[0].getKind()); ASSERT_EQ(StringRef(" "), Toks[0].getText()); - ASSERT_EQ(tok::command, Toks[1].getKind()); - ASSERT_EQ(StringRef("aaa"), Toks[1].getCommandName()); + ASSERT_EQ(tok::unknown_command, Toks[1].getKind()); + ASSERT_EQ(StringRef("aaa"), Toks[1].getUnknownCommandName()); - ASSERT_EQ(tok::command, Toks[2].getKind()); - ASSERT_EQ(StringRef("bbb"), Toks[2].getCommandName()); + ASSERT_EQ(tok::unknown_command, Toks[2].getKind()); + ASSERT_EQ(StringRef("bbb"), Toks[2].getUnknownCommandName()); ASSERT_EQ(tok::text, Toks[3].getKind()); ASSERT_EQ(StringRef(" "), Toks[3].getText()); - ASSERT_EQ(tok::command, Toks[4].getKind()); - ASSERT_EQ(StringRef("ccc"), Toks[4].getCommandName()); + ASSERT_EQ(tok::unknown_command, Toks[4].getKind()); + ASSERT_EQ(StringRef("ccc"), Toks[4].getUnknownCommandName()); ASSERT_EQ(tok::text, Toks[5].getKind()); ASSERT_EQ(StringRef("\t"), Toks[5].getText()); - ASSERT_EQ(tok::command, Toks[6].getKind()); - ASSERT_EQ(StringRef("ddd"), Toks[6].getCommandName()); + ASSERT_EQ(tok::unknown_command, Toks[6].getKind()); + ASSERT_EQ(StringRef("ddd"), Toks[6].getUnknownCommandName()); ASSERT_EQ(tok::newline, Toks[7].getKind()); } -TEST_F(CommentLexerTest, DoxygenCommand7) { +TEST_F(CommentLexerTest, DoxygenCommand8) { const char *Source = "// \\c\n"; std::vector<Token> Toks; @@ -374,7 +418,7 @@ TEST_F(CommentLexerTest, DoxygenCommand7) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::command, Toks[1].getKind()); - ASSERT_EQ(StringRef("c"), Toks[1].getCommandName()); + ASSERT_EQ(StringRef("c"), getCommandName(Toks[1])); ASSERT_EQ(tok::newline, Toks[2].getKind()); } @@ -397,10 +441,10 @@ TEST_F(CommentLexerTest, VerbatimBlock1) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::verbatim_block_end, Toks[2].getKind()); - ASSERT_EQ(StringRef("endverbatim"), Toks[2].getVerbatimBlockName()); + ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[2])); ASSERT_EQ(tok::newline, Toks[3].getKind()); ASSERT_EQ(tok::newline, Toks[4].getKind()); @@ -421,7 +465,7 @@ TEST_F(CommentLexerTest, VerbatimBlock2) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::newline, Toks[2].getKind()); } @@ -440,7 +484,7 @@ TEST_F(CommentLexerTest, VerbatimBlock3) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::newline, Toks[2].getKind()); ASSERT_EQ(tok::newline, Toks[3].getKind()); @@ -464,13 +508,13 @@ TEST_F(CommentLexerTest, VerbatimBlock4) { ASSERT_EQ(StringRef(" Meow "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind()); ASSERT_EQ(StringRef(" aaa "), Toks[2].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[3].getKind()); - ASSERT_EQ(StringRef("endverbatim"), Toks[3].getVerbatimBlockName()); + ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[3])); ASSERT_EQ(tok::newline, Toks[4].getKind()); ASSERT_EQ(tok::newline, Toks[5].getKind()); @@ -495,7 +539,7 @@ TEST_F(CommentLexerTest, VerbatimBlock5) { ASSERT_EQ(StringRef(" Meow "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind()); ASSERT_EQ(StringRef(" aaa "), Toks[2].getVerbatimBlockText()); @@ -523,7 +567,7 @@ TEST_F(CommentLexerTest, VerbatimBlock6) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::newline, Toks[2].getKind()); @@ -540,7 +584,7 @@ TEST_F(CommentLexerTest, VerbatimBlock6) { ASSERT_EQ(tok::newline, Toks[7].getKind()); ASSERT_EQ(tok::verbatim_block_end, Toks[8].getKind()); - ASSERT_EQ(StringRef("endverbatim"), Toks[8].getVerbatimBlockName()); + ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[8])); ASSERT_EQ(tok::newline, Toks[9].getKind()); } @@ -564,7 +608,7 @@ TEST_F(CommentLexerTest, VerbatimBlock7) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind()); ASSERT_EQ(StringRef(" Aaa"), Toks[2].getVerbatimBlockText()); @@ -576,7 +620,7 @@ TEST_F(CommentLexerTest, VerbatimBlock7) { ASSERT_EQ(StringRef(" Bbb"), Toks[4].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[5].getKind()); - ASSERT_EQ(StringRef("endverbatim"), Toks[5].getVerbatimBlockName()); + ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[5])); ASSERT_EQ(tok::newline, Toks[6].getKind()); @@ -605,7 +649,7 @@ TEST_F(CommentLexerTest, VerbatimBlock8) { ASSERT_EQ(StringRef(" Meow "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind()); ASSERT_EQ(StringRef(" aaa\\$\\@"), Toks[2].getVerbatimBlockText()); @@ -620,19 +664,19 @@ TEST_F(CommentLexerTest, VerbatimBlock8) { ASSERT_EQ(StringRef("ddd "), Toks[5].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[6].getKind()); - ASSERT_EQ(StringRef("endverbatim"), Toks[6].getVerbatimBlockName()); + ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[6])); ASSERT_EQ(tok::text, Toks[7].getKind()); ASSERT_EQ(StringRef(" Blah "), Toks[7].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[8].getKind()); - ASSERT_EQ(StringRef("verbatim"), Toks[8].getVerbatimBlockName()); + ASSERT_EQ(StringRef("verbatim"), getVerbatimBlockName(Toks[8])); ASSERT_EQ(tok::verbatim_block_line, Toks[9].getKind()); ASSERT_EQ(StringRef(" eee"), Toks[9].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[10].getKind()); - ASSERT_EQ(StringRef("endverbatim"), Toks[10].getVerbatimBlockName()); + ASSERT_EQ(StringRef("endverbatim"), getVerbatimBlockName(Toks[10])); ASSERT_EQ(tok::text, Toks[11].getKind()); ASSERT_EQ(StringRef(" BlahBlah"), Toks[11].getText()); @@ -655,37 +699,37 @@ TEST_F(CommentLexerTest, VerbatimBlock9) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind()); - ASSERT_EQ(StringRef("f$"), Toks[1].getVerbatimBlockName()); + ASSERT_EQ(StringRef("f$"), getVerbatimBlockName(Toks[1])); ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind()); ASSERT_EQ(StringRef(" Aaa "), Toks[2].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[3].getKind()); - ASSERT_EQ(StringRef("f$"), Toks[3].getVerbatimBlockName()); + ASSERT_EQ(StringRef("f$"), getVerbatimBlockName(Toks[3])); ASSERT_EQ(tok::text, Toks[4].getKind()); ASSERT_EQ(StringRef(" "), Toks[4].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[5].getKind()); - ASSERT_EQ(StringRef("f["), Toks[5].getVerbatimBlockName()); + ASSERT_EQ(StringRef("f["), getVerbatimBlockName(Toks[5])); ASSERT_EQ(tok::verbatim_block_line, Toks[6].getKind()); ASSERT_EQ(StringRef(" Bbb "), Toks[6].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[7].getKind()); - ASSERT_EQ(StringRef("f]"), Toks[7].getVerbatimBlockName()); + ASSERT_EQ(StringRef("f]"), getVerbatimBlockName(Toks[7])); ASSERT_EQ(tok::text, Toks[8].getKind()); ASSERT_EQ(StringRef(" "), Toks[8].getText()); ASSERT_EQ(tok::verbatim_block_begin, Toks[9].getKind()); - ASSERT_EQ(StringRef("f{"), Toks[9].getVerbatimBlockName()); + ASSERT_EQ(StringRef("f{"), getVerbatimBlockName(Toks[9])); ASSERT_EQ(tok::verbatim_block_line, Toks[10].getKind()); ASSERT_EQ(StringRef(" Ccc "), Toks[10].getVerbatimBlockText()); ASSERT_EQ(tok::verbatim_block_end, Toks[11].getKind()); - ASSERT_EQ(StringRef("f}"), Toks[11].getVerbatimBlockName()); + ASSERT_EQ(StringRef("f}"), getVerbatimBlockName(Toks[11])); ASSERT_EQ(tok::newline, Toks[12].getKind()); } @@ -708,7 +752,7 @@ TEST_F(CommentLexerTest, VerbatimLine1) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind()); - ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName()); + ASSERT_EQ(StringRef("fn"), getVerbatimLineName(Toks[1])); ASSERT_EQ(tok::newline, Toks[2].getKind()); ASSERT_EQ(tok::newline, Toks[3].getKind()); @@ -733,7 +777,7 @@ TEST_F(CommentLexerTest, VerbatimLine2) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind()); - ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName()); + ASSERT_EQ(StringRef("fn"), getVerbatimLineName(Toks[1])); ASSERT_EQ(tok::verbatim_line_text, Toks[2].getKind()); ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"), @@ -761,7 +805,7 @@ TEST_F(CommentLexerTest, VerbatimLine3) { ASSERT_EQ(StringRef(" "), Toks[0].getText()); ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind()); - ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName()); + ASSERT_EQ(StringRef("fn"), getVerbatimLineName(Toks[1])); ASSERT_EQ(tok::verbatim_line_text, Toks[2].getKind()); ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"), diff --git a/unittests/AST/CommentParser.cpp b/unittests/AST/CommentParser.cpp index f04cf197b6..0ed8771e98 100644 --- a/unittests/AST/CommentParser.cpp +++ b/unittests/AST/CommentParser.cpp @@ -37,7 +37,8 @@ protected: : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), Diags(DiagID, new IgnoringDiagConsumer()), - SourceMgr(Diags, FileMgr) { + SourceMgr(Diags, FileMgr), + Traits(Allocator) { } FileSystemOptions FileMgrOpts; @@ -46,6 +47,7 @@ protected: DiagnosticsEngine Diags; SourceManager SourceMgr; llvm::BumpPtrAllocator Allocator; + CommandTraits Traits; FullComment *parseString(const char *Source); }; @@ -55,17 +57,15 @@ FullComment *CommentParserTest::parseString(const char *Source) { FileID File = SourceMgr.createFileIDForMemBuffer(Buf); SourceLocation Begin = SourceMgr.getLocForStartOfFile(File); - comments::CommandTraits Traits; - comments::Lexer L(Allocator, Traits, Begin, - Source, Source + strlen(Source)); + Lexer L(Allocator, Traits, Begin, Source, Source + strlen(Source)); - comments::Sema S(Allocator, SourceMgr, Diags, Traits); - comments::Parser P(L, S, Allocator, SourceMgr, Diags, Traits); - comments::FullComment *FC = P.parseFullComment(); + Sema S(Allocator, SourceMgr, Diags, Traits); + Parser P(L, S, Allocator, SourceMgr, Diags, Traits); + FullComment *FC = P.parseFullComment(); if (DEBUG) { llvm::errs() << "=== Source:\n" << Source << "\n=== AST:\n"; - FC->dump(SourceMgr); + FC->dump(llvm::errs(), &Traits, &SourceMgr); } Token Tok; @@ -157,6 +157,7 @@ template <typename T> } ::testing::AssertionResult HasBlockCommandAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, BlockCommandComment *&BCC, StringRef Name, @@ -165,7 +166,7 @@ template <typename T> if (!AR) return AR; - StringRef ActualName = BCC->getCommandName(); + StringRef ActualName = BCC->getCommandName(Traits); if (ActualName != Name) return ::testing::AssertionFailure() << "BlockCommandComment has name \"" << ActualName.str() << "\", " @@ -178,6 +179,7 @@ template <typename T> ::testing::AssertionResult HasParamCommandAt( const Comment *C, + const CommandTraits &Traits, size_t Idx, ParamCommandComment *&PCC, StringRef CommandName, @@ -189,7 +191,7 @@ template <typename T> if (!AR) return AR; - StringRef ActualCommandName = PCC->getCommandName(); + StringRef ActualCommandName = PCC->getCommandName(Traits); if (ActualCommandName != CommandName) return ::testing::AssertionFailure() << "ParamCommandComment has name \"" << ActualCommandName.str() << "\", " @@ -225,6 +227,7 @@ template <typename T> ::testing::AssertionResult HasTParamCommandAt( const Comment *C, + const CommandTraits &Traits, size_t Idx, TParamCommandComment *&TPCC, StringRef CommandName, @@ -234,7 +237,7 @@ template <typename T> if (!AR) return AR; - StringRef ActualCommandName = TPCC->getCommandName(); + StringRef ActualCommandName = TPCC->getCommandName(Traits); if (ActualCommandName != CommandName) return ::testing::AssertionFailure() << "TParamCommandComment has name \"" << ActualCommandName.str() << "\", " @@ -257,6 +260,7 @@ template <typename T> } ::testing::AssertionResult HasInlineCommandAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, InlineCommandComment *&ICC, StringRef Name) { @@ -264,7 +268,7 @@ template <typename T> if (!AR) return AR; - StringRef ActualName = ICC->getCommandName(); + StringRef ActualName = ICC->getCommandName(Traits); if (ActualName != Name) return ::testing::AssertionFailure() << "InlineCommandComment has name \"" << ActualName.str() << "\", " @@ -276,11 +280,12 @@ template <typename T> struct NoArgs {}; ::testing::AssertionResult HasInlineCommandAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, InlineCommandComment *&ICC, StringRef Name, NoArgs) { - ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name); + ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name); if (!AR) return AR; @@ -293,11 +298,12 @@ struct NoArgs {}; } ::testing::AssertionResult HasInlineCommandAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, InlineCommandComment *&ICC, StringRef Name, StringRef Arg) { - ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name); + ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name); if (!AR) return AR; @@ -452,6 +458,7 @@ struct NoAttrs {}; } ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, VerbatimBlockComment *&VBC, StringRef Name, @@ -460,7 +467,7 @@ struct NoAttrs {}; if (!AR) return AR; - StringRef ActualName = VBC->getCommandName(); + StringRef ActualName = VBC->getCommandName(Traits); if (ActualName != Name) return ::testing::AssertionFailure() << "VerbatimBlockComment has name \"" << ActualName.str() << "\", " @@ -480,12 +487,13 @@ struct NoLines {}; struct Lines {}; ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, VerbatimBlockComment *&VBC, StringRef Name, StringRef CloseName, NoLines) { - ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name, + ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name, CloseName); if (!AR) return AR; @@ -499,13 +507,14 @@ struct Lines {}; } ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, VerbatimBlockComment *&VBC, StringRef Name, StringRef CloseName, Lines, StringRef Line0) { - ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name, + ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name, CloseName); if (!AR) return AR; @@ -525,6 +534,7 @@ struct Lines {}; } ::testing::AssertionResult HasVerbatimBlockAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, VerbatimBlockComment *&VBC, StringRef Name, @@ -532,7 +542,7 @@ struct Lines {}; Lines, StringRef Line0, StringRef Line1) { - ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name, + ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name, CloseName); if (!AR) return AR; @@ -558,6 +568,7 @@ struct Lines {}; } ::testing::AssertionResult HasVerbatimLineAt(const Comment *C, + const CommandTraits &Traits, size_t Idx, VerbatimLineComment *&VLC, StringRef Name, @@ -566,7 +577,7 @@ struct Lines {}; if (!AR) return AR; - StringRef ActualName = VLC->getCommandName(); + StringRef ActualName = VLC->getCommandName(Traits); if (ActualName != Name) return ::testing::AssertionFailure() << "VerbatimLineComment has name \"" << ActualName.str() << "\", " @@ -651,7 +662,7 @@ TEST_F(CommentParserTest, Paragraph2) { { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC)); ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Aaa")); } @@ -668,14 +679,14 @@ TEST_F(CommentParserTest, Paragraph3) { { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC)); ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " ")); } { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC)); ASSERT_TRUE(GetChildAt(BCC, 0, PC)); ASSERT_TRUE(HasChildCount(PC, 0)); @@ -695,7 +706,7 @@ TEST_F(CommentParserTest, Paragraph4) { { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC)); ASSERT_TRUE(GetChildAt(BCC, 0, PC)); ASSERT_TRUE(HasChildCount(PC, 2)); @@ -705,7 +716,7 @@ TEST_F(CommentParserTest, Paragraph4) { { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC)); ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Ccc")); } @@ -721,7 +732,7 @@ TEST_F(CommentParserTest, ParamCommand1) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::In, /* IsDirectionExplicit = */ false, "aaa", PC)); @@ -740,7 +751,7 @@ TEST_F(CommentParserTest, ParamCommand2) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::In, /* IsDirectionExplicit = */ false, "", PC)); @@ -750,7 +761,7 @@ TEST_F(CommentParserTest, ParamCommand2) { { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "brief", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC)); ASSERT_TRUE(HasChildCount(PC, 0)); } } @@ -774,7 +785,7 @@ TEST_F(CommentParserTest, ParamCommand3) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::In, /* IsDirectionExplicit = */ false, "aaa", PC)); @@ -804,7 +815,7 @@ TEST_F(CommentParserTest, ParamCommand4) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::In, /* IsDirectionExplicit = */ true, "aaa", PC)); @@ -834,7 +845,7 @@ TEST_F(CommentParserTest, ParamCommand5) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::Out, /* IsDirectionExplicit = */ true, "aaa", PC)); @@ -865,7 +876,7 @@ TEST_F(CommentParserTest, ParamCommand6) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::InOut, /* IsDirectionExplicit = */ true, "aaa", PC)); @@ -886,7 +897,7 @@ TEST_F(CommentParserTest, ParamCommand7) { { ParamCommandComment *PCC; ParagraphComment *PC; - ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param", + ASSERT_TRUE(HasParamCommandAt(FC, Traits, 1, PCC, "param", ParamCommandComment::In, /* IsDirectionExplicit = */ false, "aaa", PC)); @@ -920,7 +931,7 @@ TEST_F(CommentParserTest, TParamCommand1) { { TParamCommandComment *TPCC; ParagraphComment *PC; - ASSERT_TRUE(HasTParamCommandAt(FC, 1, TPCC, "tparam", + ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam", "aaa", PC)); ASSERT_TRUE(HasChildCount(TPCC, 1)); ASSERT_TRUE(HasParagraphCommentAt(TPCC, 0, " Bbb")); @@ -938,14 +949,14 @@ TEST_F(CommentParserTest, TParamCommand2) { { TParamCommandComment *TPCC; ParagraphComment *PC; - ASSERT_TRUE(HasTParamCommandAt(FC, 1, TPCC, "tparam", "", PC)); + ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam", "", PC)); ASSERT_TRUE(HasChildCount(TPCC, 1)); ASSERT_TRUE(HasChildCount(PC, 0)); } { BlockCommandComment *BCC; ParagraphComment *PC; - ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "brief", PC)); + ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC)); ASSERT_TRUE(HasChildCount(PC, 0)); } } @@ -964,7 +975,7 @@ TEST_F(CommentParserTest, InlineCommand1) { ASSERT_TRUE(HasChildCount(PC, 2)); ASSERT_TRUE(HasTextAt(PC, 0, " ")); - ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs())); + ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs())); } } @@ -981,7 +992,7 @@ TEST_F(CommentParserTest, InlineCommand2) { ASSERT_TRUE(HasChildCount(PC, 3)); ASSERT_TRUE(HasTextAt(PC, 0, " ")); - ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs())); + ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs())); ASSERT_TRUE(HasTextAt(PC, 2, " ")); } } @@ -999,7 +1010,7 @@ TEST_F(CommentParserTest, InlineCommand3) { ASSERT_TRUE(HasChildCount(PC, 2)); ASSERT_TRUE(HasTextAt(PC, 0, " ")); - ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa")); + ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa")); } } @@ -1016,7 +1027,7 @@ TEST_F(CommentParserTest, InlineCommand4) { ASSERT_TRUE(HasChildCount(PC, 3)); ASSERT_TRUE(HasTextAt(PC, 0, " ")); - ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa")); + ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa")); ASSERT_TRUE(HasTextAt(PC, 2, " bbb")); } } @@ -1034,7 +1045,7 @@ TEST_F(CommentParserTest, InlineCommand5) { ASSERT_TRUE(HasChildCount(PC, 3)); ASSERT_TRUE(HasTextAt(PC, 0, " ")); - ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "unknown", NoArgs())); + ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "unknown", NoArgs())); ASSERT_TRUE(HasTextAt(PC, 2, " aaa")); } } @@ -1188,7 +1199,8 @@ TEST_F(CommentParserTest, VerbatimBlock1) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimBlockComment *VCC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VCC, "verbatim", "endverbatim", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VCC, + "verbatim", "endverbatim", NoLines())); } } @@ -1202,7 +1214,8 @@ TEST_F(CommentParserTest, VerbatimBlock2) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, + "verbatim", "endverbatim", Lines(), " Aaa ")); } } @@ -1216,7 +1229,7 @@ TEST_F(CommentParserTest, VerbatimBlock3) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, "verbatim", "", Lines(), " Aaa")); } } @@ -1231,7 +1244,8 @@ TEST_F(CommentParserTest, VerbatimBlock4) { { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", "endverbatim", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC, + "verbatim", "endverbatim", NoLines())); } } @@ -1253,7 +1267,8 @@ TEST_F(CommentParserTest, VerbatimBlock5) { { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", "endverbatim", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC, + "verbatim", "endverbatim", Lines(), " Aaa")); } } @@ -1277,7 +1292,8 @@ TEST_F(CommentParserTest, VerbatimBlock6) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, + "verbatim", "endverbatim", Lines(), " Aaa")); } } @@ -1303,7 +1319,8 @@ TEST_F(CommentParserTest, VerbatimBlock7) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim", + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, + "verbatim", "endverbatim", Lines(), " Aaa", " Bbb")); } } @@ -1330,7 +1347,8 @@ TEST_F(CommentParserTest, VerbatimBlock8) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimBlockComment *VBC; - ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", "endverbatim")); + ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, + "verbatim", "endverbatim")); ASSERT_EQ(3U, VBC->getNumLines()); ASSERT_EQ(" Aaa", VBC->getText(0)); ASSERT_EQ("", VBC->getText(1)); @@ -1352,7 +1370,7 @@ TEST_F(CommentParserTest, VerbatimLine1) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimLineComment *VLC; - ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", "")); + ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn", "")); } } } @@ -1370,7 +1388,7 @@ TEST_F(CommentParserTest, VerbatimLine2) { ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " ")); { VerbatimLineComment *VLC; - ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", + ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn", " void *foo(const char *zzz = \"\\$\");")); } } diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index ca2e4696a5..d5748bc2ce 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS Support) add_tablegen(clang-tblgen CLANG ClangASTNodesEmitter.cpp ClangAttrEmitter.cpp + ClangCommentCommandInfoEmitter.cpp ClangCommentHTMLTagsEmitter.cpp ClangDiagnosticsEmitter.cpp ClangSACheckersEmitter.cpp diff --git a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp new file mode 100644 index 0000000000..11b2f51f71 --- /dev/null +++ b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp @@ -0,0 +1,70 @@ +//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits command lists and efficient matchers command +// names that are used in documentation comments. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringMatcher.h" +#include <vector> + +using namespace llvm; + +namespace clang { +void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + OS << "namespace {\n" + "const CommandInfo Commands[] = {\n"; + std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); + for (size_t i = 0, e = Tags.size(); i != e; ++i) { + Record &Tag = *Tags[i]; + OS << " { " + << "\"" << Tag.getValueAsString("Name") << "\", " + << "\"" << Tag.getValueAsString("EndCommandName") << "\", " + << i << ", " + << Tag.getValueAsInt("NumArgs") << ", " + << Tag.getValueAsBit("IsInlineCommand") << ", " + << Tag.getValueAsBit("IsBlockCommand") << ", " + << Tag.getValueAsBit("IsBriefCommand") << ", " + << Tag.getValueAsBit("IsReturnsCommand") << ", " + << Tag.getValueAsBit("IsParamCommand") << ", " + << Tag.getValueAsBit("IsTParamCommand") << ", " + << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " + << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " + << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " + << Tag.getValueAsBit("IsDeclarationCommand") << ", " + << /* IsUnknownCommand = */ "0" + << " }"; + if (i + 1 != e) + OS << ","; + OS << "\n"; + } + OS << "};\n" + "} // unnamed namespace\n\n"; + + std::vector<StringMatcher::StringPair> Matches; + for (size_t i = 0, e = Tags.size(); i != e; ++i) { + Record &Tag = *Tags[i]; + std::string Name = Tag.getValueAsString("Name"); + std::string Return; + raw_string_ostream(Return) << "return &Commands[" << i << "];"; + Matches.push_back(StringMatcher::StringPair(Name, Return)); + } + + OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" + << " StringRef Name) {\n"; + StringMatcher("Name", Matches, OS).Emit(); + OS << " return NULL;\n" + << "}\n\n"; +} +} // end namespace clang + diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index bb9b918505..4f7789dbef 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -44,6 +44,7 @@ enum ActionType { GenClangSACheckers, GenClangCommentHTMLTags, GenClangCommentHTMLTagsProperties, + GenClangCommentCommandInfo, GenOptParserDefs, GenOptParserImpl, GenArmNeon, GenArmNeonSema, @@ -105,6 +106,10 @@ namespace { "gen-clang-comment-html-tags-properties", "Generate efficient matchers for HTML tag " "properties"), + clEnumValN(GenClangCommentCommandInfo, + "gen-clang-comment-command-info", + "Generate list of commands that are used in " + "documentation comments"), clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"), clEnumValN(GenArmNeonSema, "gen-arm-neon-sema", @@ -180,6 +185,9 @@ public: case GenClangCommentHTMLTagsProperties: EmitClangCommentHTMLTagsProperties(Records, OS); break; + case GenClangCommentCommandInfo: + EmitClangCommentCommandInfo(Records, OS); + break; case GenOptParserDefs: EmitOptParser(Records, OS, true); break; diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 74fc60ec11..838fc84dca 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -50,6 +50,8 @@ void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS); void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS); void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS); +void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS); + void EmitNeon(RecordKeeper &Records, raw_ostream &OS); void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS); void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS); |