//===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines comment AST nodes. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_COMMENT_H #define LLVM_CLANG_AST_COMMENT_H #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" namespace clang { class Decl; class ParmVarDecl; class TemplateParameterList; namespace comments { class FullComment; /// Describes the syntax that was used in a documentation command. /// /// Exact values of this enumeration are important because they used to select /// parts of diagnostic messages. Audit diagnostics before changing or adding /// a new value. enum CommandMarkerKind { /// Command started with a backslash character: /// \code /// \foo /// \endcode CMK_Backslash = 0, /// Command started with an 'at' character: /// \code /// @foo /// \endcode CMK_At = 1 }; /// Any part of the comment. /// Abstract class. class Comment { protected: /// Preferred location to show caret. SourceLocation Loc; /// Source range of this AST node. SourceRange Range; class CommentBitfields { friend class Comment; /// Type of this AST node. unsigned Kind : 8; }; enum { NumCommentBits = 8 }; class InlineContentCommentBitfields { friend class InlineContentComment; unsigned : NumCommentBits; /// True if there is a newline after this inline content node. /// (There is no separate AST node for a newline.) unsigned HasTrailingNewline : 1; }; enum { NumInlineContentCommentBits = NumCommentBits + 1 }; class TextCommentBitfields { friend class TextComment; unsigned : NumInlineContentCommentBits; /// True if \c IsWhitespace field contains a valid value. mutable unsigned IsWhitespaceValid : 1; /// True if this comment AST node contains only whitespace. mutable unsigned IsWhitespace : 1; }; enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; class InlineCommandCommentBitfields { friend class InlineCommandComment; unsigned : NumInlineContentCommentBits; unsigned RenderKind : 2; unsigned CommandID : 8; }; enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 }; class HTMLStartTagCommentBitfields { friend class HTMLStartTagComment; unsigned : NumInlineContentCommentBits; /// True if this tag is self-closing (e. g.,
). This is based on tag /// spelling in comment (plain
would not set this flag). unsigned IsSelfClosing : 1; }; enum { NumHTMLStartTagCommentBits = NumInlineContentCommentBits + 1 }; class ParagraphCommentBitfields { friend class ParagraphComment; unsigned : NumCommentBits; /// True if \c IsWhitespace field contains a valid value. mutable unsigned IsWhitespaceValid : 1; /// True if this comment AST node contains only whitespace. mutable unsigned IsWhitespace : 1; }; enum { NumParagraphCommentBits = NumCommentBits + 2 }; class BlockCommandCommentBitfields { friend class BlockCommandComment; unsigned : NumCommentBits; unsigned CommandID : 8; /// Describes the syntax that was used in a documentation command. /// Contains values from CommandMarkerKind enum. unsigned CommandMarker : 1; }; enum { NumBlockCommandCommentBits = NumCommentBits + 9 }; class ParamCommandCommentBitfields { friend class ParamCommandComment; unsigned : NumBlockCommandCommentBits; /// Parameter passing direction, see ParamCommandComment::PassDirection. unsigned Direction : 2; /// True if direction was specified explicitly in the comment. unsigned IsDirectionExplicit : 1; }; enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; union { CommentBitfields CommentBits; InlineContentCommentBitfields InlineContentCommentBits; TextCommentBitfields TextCommentBits; InlineCommandCommentBitfields InlineCommandCommentBits; HTMLStartTagCommentBitfields HTMLStartTagCommentBits; ParagraphCommentBitfields ParagraphCommentBits; BlockCommandCommentBitfields BlockCommandCommentBits; ParamCommandCommentBitfields ParamCommandCommentBits; }; void setSourceRange(SourceRange SR) { Range = SR; } void setLocation(SourceLocation L) { Loc = L; } public: enum CommentKind { NoCommentKind = 0, #define COMMENT(CLASS, PARENT) CLASS##Kind, #define COMMENT_RANGE(BASE, FIRST, LAST) \ First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, #define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind #define ABSTRACT_COMMENT(COMMENT) #include "clang/AST/CommentNodes.inc" }; Comment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd) : Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { CommentBits.Kind = K; } CommentKind getCommentKind() const { return static_cast(CommentBits.Kind); } const char *getCommentKindName() const; LLVM_ATTRIBUTE_USED void dump() const; LLVM_ATTRIBUTE_USED void dumpColor() const; LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) const; void dump(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) const; SourceRange getSourceRange() const LLVM_READONLY { return Range; } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceLocation getLocation() const LLVM_READONLY { return Loc; } typedef Comment * const *child_iterator; child_iterator child_begin() const; child_iterator child_end() const; // TODO: const child iterator unsigned child_count() const { return child_end() - child_begin(); } }; /// Inline content (contained within a block). /// Abstract class. class InlineContentComment : public Comment { protected: InlineContentComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd) : Comment(K, LocBegin, LocEnd) { InlineContentCommentBits.HasTrailingNewline = 0; } public: static bool classof(const Comment *C) { return C->getCommentKind() >= FirstInlineContentCommentConstant && C->getCommentKind() <= LastInlineContentCommentConstant; } void addTrailingNewline() { InlineContentCommentBits.HasTrailingNewline = 1; } bool hasTrailingNewline() const { return InlineContentCommentBits.HasTrailingNewline; } }; /// Plain text. class TextComment : public InlineContentComment { StringRef Text; public: TextComment(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text) : InlineContentComment(TextCommentKind, LocBegin, LocEnd), Text(Text) { TextCommentBits.IsWhitespaceValid = false; } static bool classof(const Comment *C) { return C->getCommentKind() == TextCommentKind; } child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } StringRef getText() const LLVM_READONLY { return Text; } bool isWhitespace() const { if (TextCommentBits.IsWhitespaceValid) return TextCommentBits.IsWhitespace; TextCommentBits.IsWhitespace = isWhitespaceNoCache(); TextCommentBits.IsWhitespaceValid = true; return TextCommentBits.IsWhitespace; } private: bool isWhitespaceNoCache() const; }; /// A command with word-like arguments that is considered inline content. class InlineCommandComment : public InlineContentComment { public: struct Argument { SourceRange Range; StringRef Text; Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } }; /// The most appropriate rendering mode for this command, chosen on command /// semantics in Doxygen. enum RenderKind { RenderNormal, RenderBold, RenderMonospaced, RenderEmphasized }; protected: /// Command arguments. ArrayRef Args; public: InlineCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, RenderKind RK, ArrayRef Args) : InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), Args(Args) { InlineCommandCommentBits.RenderKind = RK; InlineCommandCommentBits.CommandID = CommandID; } static bool classof(const Comment *C) { return C->getCommentKind() == InlineCommandCommentKind; } child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } unsigned getCommandID() const { return InlineCommandCommentBits.CommandID; } StringRef getCommandName(const CommandTraits &Traits) const { return Traits.getCommandInfo(getCommandID())->Name; } SourceRange getCommandNameRange() const { return SourceRange(getLocStart().getLocWithOffset(-1), getLocEnd()); } RenderKind getRenderKind() const { return static_cast(InlineCommandCommentBits.RenderKind); } unsigned getNumArgs() const { return Args.size(); } StringRef getArgText(unsigned Idx) const { return Args[Idx].Text; } SourceRange getArgRange(unsigned Idx) const { return Args[Idx].Range; } }; /// Abstract class for opening and closing HTML tags. HTML tags are always /// treated as inline content (regardless HTML semantics); opening and closing /// tags are not matched. class HTMLTagComment : public InlineContentComment { protected: StringRef TagName; SourceRange TagNameRange; HTMLTagComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd, StringRef TagName, SourceLocation TagNameBegin, SourceLocation TagNameEnd) : InlineContentComment(K, LocBegin, LocEnd), TagName(TagName), TagNameRange(TagNameBegin, TagNameEnd) { setLocation(TagNameBegin); } public: static bool classof(const Comment *C) { return C->getCommentKind() >= FirstHTMLTagCommentConstant && C->getCommentKind() <= LastHTMLTagCommentConstant; } StringRef getTagName() const LLVM_READONLY { return TagName; } SourceRange getTagNameSourceRange() const LLVM_READONLY { SourceLocation L = getLocation(); return SourceRange(L.getLocWithOffset(1), L.getLocWithOffset(1 + TagName.size())); } }; /// An opening HTML tag with attributes. class HTMLStartTagComment : public HTMLTagComment { public: class Attribute { public: SourceLocation NameLocBegin; StringRef Name; SourceLocation EqualsLoc; SourceRange ValueRange; StringRef Value; Attribute() { } Attribute(SourceLocation NameLocBegin, StringRef Name) : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(SourceLocation()), ValueRange(SourceRange()), Value(StringRef()) { } Attribute(SourceLocation NameLocBegin, StringRef Name, SourceLocation EqualsLoc, SourceRange ValueRange, StringRef Value) : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(EqualsLoc), ValueRange(ValueRange), Value(Value) { } SourceLocation getNameLocEnd() const { return NameLocBegin.getLocWithOffset(Name.size()); } SourceRange getNameRange() const { return SourceRange(NameLocBegin, getNameLocEnd()); } }; private: ArrayRef Attributes; public: HTMLStartTagComment(SourceLocation LocBegin, StringRef TagName) : HTMLTagComment(HTMLStartTagCommentKind, LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), TagName, LocBegin.getLocWithOffset(1), LocBegin.getLocWithOffset(1 + TagName.size())) { HTMLStartTagCommentBits.IsSelfClosing = false; } static bool classof(const Comment *C) { return C->getCommentKind() == HTMLStartTagCommentKind; } child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } unsigned getNumAttrs() const { return Attributes.size(); } const Attribute &getAttr(unsigned Idx) const { return Attributes[Idx]; } void setAttrs(ArrayRef Attrs) { Attributes = Attrs; if (!Attrs.empty()) { const Attribute &Attr = Attrs.back(); SourceLocation L = Attr.ValueRange.getEnd(); if (L.isValid()) Range.setEnd(L); else { Range.setEnd(Attr.getNameLocEnd()); } } } void setGreaterLoc(SourceLocation GreaterLoc) { Range.setEnd(GreaterLoc); } bool isSelfClosing() const { return HTMLStartTagCommentBits.IsSelfClosing; } void setSelfClosing() { HTMLStartTagCommentBits.IsSelfClosing = true; } }; /// A closing HTML tag. class HTMLEndTagComment : public HTMLTagComment { public: HTMLEndTagComment(SourceLocation LocBegin, SourceLocation LocEnd, StringRef TagName) : HTMLTagComment(HTMLEndTagCommentKind, LocBegin, LocEnd, TagName, LocBegin.getLocWithOffset(2), LocBegin.getLocWithOffset(2 + TagName.size())) { } static bool classof(const Comment *C) { return C->getCommentKind() == HTMLEndTagCommentKind; } child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } }; /// Block content (contains inline content). /// Abstract class. class BlockContentComment : public Comment { protected: BlockContentComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd) : Comment(K, LocBegin, LocEnd) { } public: static bool classof(const Comment *C) { return C->getCommentKind() >= FirstBlockContentCommentConstant && C->getCommentKind() <= LastBlockContentCommentConstant; } }; /// A single paragraph that contains inline content. class ParagraphComment : public BlockContentComment { ArrayRef Content; public: ParagraphComment(ArrayRef Content) : BlockContentComment(ParagraphCommentKind, SourceLocation(), SourceLocation()), Content(Content) { if (Content.empty()) { ParagraphCommentBits.IsWhitespace = true; ParagraphCommentBits.IsWhitespaceValid = true; return; } ParagraphCommentBits.IsWhitespaceValid = false; setSourceRange(SourceRange(Content.front()->getLocStart(), Content.back()->getLocEnd())); setLocation(Content.front()->getLocStart()); } static bool classof(const Comment *C) { return C->getCommentKind() == ParagraphCommentKind; } child_iterator child_begin() const { return reinterpret_cast(Content.begin()); } child_iterator child_end() const { return reinterpret_cast(Content.end()); } bool isWhitespace() const { if (ParagraphCommentBits.IsWhitespaceValid) return ParagraphCommentBits.IsWhitespace; ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache(); ParagraphCommentBits.IsWhitespaceValid = true; return ParagraphCommentBits.IsWhitespace; } private: bool isWhitespaceNoCache() const; }; /// A command that has zero or more word-like arguments (number of word-like /// arguments depends on command name) and a paragraph as an argument /// (e. g., \\brief). class BlockCommandComment : public BlockContentComment { public: struct Argument { SourceRange Range; StringRef Text; Argument() { } Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } }; protected: /// Word-like arguments. ArrayRef Args; /// Paragraph argument. ParagraphComment *Paragraph; BlockCommandComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker) : BlockContentComment(K, LocBegin, LocEnd), Paragraph(NULL) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; BlockCommandCommentBits.CommandMarker = CommandMarker; } public: BlockCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker) : BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), Paragraph(NULL) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; BlockCommandCommentBits.CommandMarker = CommandMarker; } static bool classof(const Comment *C) { return C->getCommentKind() >= FirstBlockCommandCommentConstant && C->getCommentKind() <= LastBlockCommandCommentConstant; } child_iterator child_begin() const { return reinterpret_cast(&Paragraph); } child_iterator child_end() const { return reinterpret_cast(&Paragraph + 1); } unsigned getCommandID() const { return BlockCommandCommentBits.CommandID; } 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())); } unsigned getNumArgs() const { return Args.size(); } StringRef getArgText(unsigned Idx) const { return Args[Idx].Text; } SourceRange getArgRange(unsigned Idx) const { return Args[Idx].Range; } void setArgs(ArrayRef A) { Args = A; if (Args.size() > 0) { SourceLocation NewLocEnd = Args.back().Range.getEnd(); if (NewLocEnd.isValid()) setSourceRange(SourceRange(getLocStart(), NewLocEnd)); } } ParagraphComment *getParagraph() const LLVM_READONLY { return Paragraph; } bool hasNonWhitespaceParagraph() const { return Paragraph && !Paragraph->isWhitespace(); } void setParagraph(ParagraphComment *PC) { Paragraph = PC; SourceLocation NewLocEnd = PC->getLocEnd(); if (NewLocEnd.isValid()) setSourceRange(SourceRange(getLocStart(), NewLocEnd)); } CommandMarkerKind getCommandMarker() const LLVM_READONLY { return static_cast( BlockCommandCommentBits.CommandMarker); } }; /// Doxygen \\param command. class ParamCommandComment : public BlockCommandComment { private: /// Parameter index in the function declaration. unsigned ParamIndex; public: enum LLVM_ENUM_INT_TYPE(unsigned) { InvalidParamIndex = ~0U, VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U }; ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker) : BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, CommandID, CommandMarker), ParamIndex(InvalidParamIndex) { ParamCommandCommentBits.Direction = In; ParamCommandCommentBits.IsDirectionExplicit = false; } static bool classof(const Comment *C) { return C->getCommentKind() == ParamCommandCommentKind; } enum PassDirection { In, Out, InOut }; static const char *getDirectionAsString(PassDirection D); PassDirection getDirection() const LLVM_READONLY { return static_cast(ParamCommandCommentBits.Direction); } bool isDirectionExplicit() const LLVM_READONLY { return ParamCommandCommentBits.IsDirectionExplicit; } void setDirection(PassDirection Direction, bool Explicit) { ParamCommandCommentBits.Direction = Direction; ParamCommandCommentBits.IsDirectionExplicit = Explicit; } bool hasParamName() const { return getNumArgs() > 0; } StringRef getParamName(const FullComment *FC) const; StringRef getParamNameAsWritten() const { return Args[0].Text; } SourceRange getParamNameRange() const { return Args[0].Range; } bool isParamIndexValid() const LLVM_READONLY { return ParamIndex != InvalidParamIndex; } bool isVarArgParam() const LLVM_READONLY { return ParamIndex == VarArgParamIndex; } void setIsVarArgParam() { ParamIndex = VarArgParamIndex; assert(isParamIndexValid()); } unsigned getParamIndex() const LLVM_READONLY { assert(isParamIndexValid()); assert(!isVarArgParam()); return ParamIndex; } void setParamIndex(unsigned Index) { ParamIndex = Index; assert(isParamIndexValid()); assert(!isVarArgParam()); } }; /// Doxygen \\tparam command, describes a template parameter. class TParamCommandComment : public BlockCommandComment { private: /// If this template parameter name was resolved (found in template parameter /// list), then this stores a list of position indexes in all template /// parameter lists. /// /// For example: /// \verbatim /// template class TT> /// void test(TT aaa); /// \endverbatim /// For C: Position = { 0 } /// For TT: Position = { 1 } /// For T: Position = { 1, 0 } ArrayRef Position; public: TParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker) : BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID, CommandMarker) { } static bool classof(const Comment *C) { return C->getCommentKind() == TParamCommandCommentKind; } bool hasParamName() const { return getNumArgs() > 0; } StringRef getParamName(const FullComment *FC) const; StringRef getParamNameAsWritten() const { return Args[0].Text; } SourceRange getParamNameRange() const { return Args[0].Range; } bool isPositionValid() const LLVM_READONLY { return !Position.empty(); } unsigned getDepth() const { assert(isPositionValid()); return Position.size(); } unsigned getIndex(unsigned Depth) const { assert(isPositionValid()); return Position[Depth]; } void setPosition(ArrayRef NewPosition) { Position = NewPosition; assert(isPositionValid()); } }; /// A line of text contained in a verbatim block. class VerbatimBlockLineComment : public Comment { StringRef Text; public: VerbatimBlockLineComment(SourceLocation LocBegin, StringRef Text) : Comment(VerbatimBlockLineCommentKind, LocBegin, LocBegin.getLocWithOffset(Text.size())), Text(Text) { } static bool classof(const Comment *C) { return C->getCommentKind() == VerbatimBlockLineCommentKind; } child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } StringRef getText() const LLVM_READONLY { return Text; } }; /// A verbatim block command (e. g., preformatted code). Verbatim block has an /// opening and a closing command and contains multiple lines of text /// (VerbatimBlockLineComment nodes). class VerbatimBlockComment : public BlockCommandComment { protected: StringRef CloseName; SourceLocation CloseNameLocBegin; ArrayRef Lines; public: VerbatimBlockComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID) : BlockCommandComment(VerbatimBlockCommentKind, LocBegin, LocEnd, CommandID, CMK_At) // FIXME: improve source fidelity. { } static bool classof(const Comment *C) { return C->getCommentKind() == VerbatimBlockCommentKind; } child_iterator child_begin() const { return reinterpret_cast(Lines.begin()); } child_iterator child_end() const { return reinterpret_cast(Lines.end()); } void setCloseName(StringRef Name, SourceLocation LocBegin) { CloseName = Name; CloseNameLocBegin = LocBegin; } void setLines(ArrayRef L) { Lines = L; } StringRef getCloseName() const { return CloseName; } unsigned getNumLines() const { return Lines.size(); } StringRef getText(unsigned LineIdx) const { return Lines[LineIdx]->getText(); } }; /// A verbatim line command. Verbatim line has an opening command, a single /// line of text (up to the newline after the opening command) and has no /// closing command. class VerbatimLineComment : public BlockCommandComment { protected: StringRef Text; SourceLocation TextBegin; public: VerbatimLineComment(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, SourceLocation TextBegin, StringRef Text) : BlockCommandComment(VerbatimLineCommentKind, LocBegin, LocEnd, CommandID, CMK_At), // FIXME: improve source fidelity. Text(Text), TextBegin(TextBegin) { } static bool classof(const Comment *C) { return C->getCommentKind() == VerbatimLineCommentKind; } child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } StringRef getText() const { return Text; } SourceRange getTextRange() const { return SourceRange(TextBegin, getLocEnd()); } }; /// Information about the declaration, useful to clients of FullComment. struct DeclInfo { /// Declaration the comment is actually attached to (in the source). /// Should not be NULL. const Decl *CommentDecl; /// CurrentDecl is the declaration with which the FullComment is associated. /// /// It can be different from \c CommentDecl. It happens when we we decide /// that the comment originally attached to \c CommentDecl is fine for /// \c CurrentDecl too (for example, for a redeclaration or an overrider of /// \c CommentDecl). /// /// The information in the DeclInfo corresponds to CurrentDecl. const Decl *CurrentDecl; /// Parameters that can be referenced by \\param if \c CommentDecl is something /// that we consider a "function". ArrayRef ParamVars; /// Function result type if \c CommentDecl is something that we consider /// a "function". QualType ResultType; /// Template parameters that can be referenced by \\tparam if \c CommentDecl is /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is /// true). const TemplateParameterList *TemplateParameters; /// A simplified description of \c CommentDecl kind that should be good enough /// for documentation rendering purposes. enum DeclKind { /// Everything else not explicitly mentioned below. OtherKind, /// Something that we consider a "function": /// \li function, /// \li function template, /// \li function template specialization, /// \li member function, /// \li member function template, /// \li member function template specialization, /// \li ObjC method, /// \li a typedef for a function pointer, member function pointer, /// ObjC block. FunctionKind, /// Something that we consider a "class": /// \li class/struct, /// \li class template, /// \li class template (partial) specialization. ClassKind, /// Something that we consider a "variable": /// \li namespace scope variables; /// \li static and non-static class data members; /// \li enumerators. VariableKind, /// A C++ namespace. NamespaceKind, /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), /// see \c TypedefNameDecl. TypedefKind, /// An enumeration or scoped enumeration. EnumKind }; /// What kind of template specialization \c CommentDecl is. enum TemplateDeclKind { NotTemplate, Template, TemplateSpecialization, TemplatePartialSpecialization }; /// If false, only \c CommentDecl is valid. unsigned IsFilled : 1; /// Simplified kind of \c CommentDecl, see \c DeclKind enum. unsigned Kind : 3; /// Is \c CommentDecl a template declaration. unsigned TemplateKind : 2; /// Is \c CommentDecl an ObjCMethodDecl. unsigned IsObjCMethod : 1; /// Is \c CommentDecl a non-static member function of C++ class or /// instance method of ObjC class. /// Can be true only if \c IsFunctionDecl is true. unsigned IsInstanceMethod : 1; /// Is \c CommentDecl a static member function of C++ class or /// class method of ObjC class. /// Can be true only if \c IsFunctionDecl is true. unsigned IsClassMethod : 1; void fill(); DeclKind getKind() const LLVM_READONLY { return static_cast(Kind); } TemplateDeclKind getTemplateKind() const LLVM_READONLY { return static_cast(TemplateKind); } }; /// A full comment attached to a declaration, contains block content. class FullComment : public Comment { ArrayRef Blocks; DeclInfo *ThisDeclInfo; public: FullComment(ArrayRef Blocks, DeclInfo *D) : Comment(FullCommentKind, SourceLocation(), SourceLocation()), Blocks(Blocks), ThisDeclInfo(D) { if (Blocks.empty()) return; setSourceRange(SourceRange(Blocks.front()->getLocStart(), Blocks.back()->getLocEnd())); setLocation(Blocks.front()->getLocStart()); } static bool classof(const Comment *C) { return C->getCommentKind() == FullCommentKind; } child_iterator child_begin() const { return reinterpret_cast(Blocks.begin()); } child_iterator child_end() const { return reinterpret_cast(Blocks.end()); } const Decl *getDecl() const LLVM_READONLY { return ThisDeclInfo->CommentDecl; } const DeclInfo *getDeclInfo() const LLVM_READONLY { if (!ThisDeclInfo->IsFilled) ThisDeclInfo->fill(); return ThisDeclInfo; } ArrayRef getBlocks() const { return Blocks; } }; } // end namespace comments } // end namespace clang #endif