clang API Documentation

Comment.h
Go to the documentation of this file.
00001 //===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines comment AST nodes.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_AST_COMMENT_H
00015 #define LLVM_CLANG_AST_COMMENT_H
00016 
00017 #include "clang/AST/CommentCommandTraits.h"
00018 #include "clang/AST/DeclObjC.h"
00019 #include "clang/AST/Type.h"
00020 #include "clang/Basic/SourceLocation.h"
00021 #include "llvm/ADT/ArrayRef.h"
00022 #include "llvm/ADT/StringRef.h"
00023 
00024 namespace clang {
00025 class Decl;
00026 class ParmVarDecl;
00027 class TemplateParameterList;
00028 
00029 namespace comments {
00030 class FullComment;
00031 
00032 /// Describes the syntax that was used in a documentation command.
00033 ///
00034 /// Exact values of this enumeration are important because they used to select
00035 /// parts of diagnostic messages.  Audit diagnostics before changing or adding
00036 /// a new value.
00037 enum CommandMarkerKind {
00038   /// Command started with a backslash character:
00039   /// \code
00040   ///   \foo
00041   /// \endcode
00042   CMK_Backslash = 0,
00043 
00044   /// Command started with an 'at' character:
00045   /// \code
00046   ///   @foo
00047   /// \endcode
00048   CMK_At = 1
00049 };
00050 
00051 /// Any part of the comment.
00052 /// Abstract class.
00053 class Comment {
00054 protected:
00055   /// Preferred location to show caret.
00056   SourceLocation Loc;
00057 
00058   /// Source range of this AST node.
00059   SourceRange Range;
00060 
00061   class CommentBitfields {
00062     friend class Comment;
00063 
00064     /// Type of this AST node.
00065     unsigned Kind : 8;
00066   };
00067   enum { NumCommentBits = 8 };
00068 
00069   class InlineContentCommentBitfields {
00070     friend class InlineContentComment;
00071 
00072     unsigned : NumCommentBits;
00073 
00074     /// True if there is a newline after this inline content node.
00075     /// (There is no separate AST node for a newline.)
00076     unsigned HasTrailingNewline : 1;
00077   };
00078   enum { NumInlineContentCommentBits = NumCommentBits + 1 };
00079 
00080   class TextCommentBitfields {
00081     friend class TextComment;
00082 
00083     unsigned : NumInlineContentCommentBits;
00084 
00085     /// True if \c IsWhitespace field contains a valid value.
00086     mutable unsigned IsWhitespaceValid : 1;
00087 
00088     /// True if this comment AST node contains only whitespace.
00089     mutable unsigned IsWhitespace : 1;
00090   };
00091   enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
00092 
00093   class InlineCommandCommentBitfields {
00094     friend class InlineCommandComment;
00095 
00096     unsigned : NumInlineContentCommentBits;
00097 
00098     unsigned RenderKind : 2;
00099     unsigned CommandID : CommandInfo::NumCommandIDBits;
00100   };
00101   enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + 
00102                                        CommandInfo::NumCommandIDBits };
00103 
00104   class HTMLTagCommentBitfields {
00105     friend class HTMLTagComment;
00106 
00107     unsigned : NumInlineContentCommentBits;
00108 
00109     /// True if we found that this tag is malformed in some way.
00110     unsigned IsMalformed : 1;
00111   };
00112   enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };
00113 
00114   class HTMLStartTagCommentBitfields {
00115     friend class HTMLStartTagComment;
00116 
00117     unsigned : NumHTMLTagCommentBits;
00118 
00119     /// True if this tag is self-closing (e. g., <br />).  This is based on tag
00120     /// spelling in comment (plain <br> would not set this flag).
00121     unsigned IsSelfClosing : 1;
00122   };
00123   enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
00124 
00125   class ParagraphCommentBitfields {
00126     friend class ParagraphComment;
00127 
00128     unsigned : NumCommentBits;
00129 
00130     /// True if \c IsWhitespace field contains a valid value.
00131     mutable unsigned IsWhitespaceValid : 1;
00132 
00133     /// True if this comment AST node contains only whitespace.
00134     mutable unsigned IsWhitespace : 1;
00135   };
00136   enum { NumParagraphCommentBits = NumCommentBits + 2 };
00137 
00138   class BlockCommandCommentBitfields {
00139     friend class BlockCommandComment;
00140 
00141     unsigned : NumCommentBits;
00142 
00143     unsigned CommandID : CommandInfo::NumCommandIDBits;
00144 
00145     /// Describes the syntax that was used in a documentation command.
00146     /// Contains values from CommandMarkerKind enum.
00147     unsigned CommandMarker : 1;
00148   };
00149   enum { NumBlockCommandCommentBits = NumCommentBits + 
00150                                       CommandInfo::NumCommandIDBits + 1 };
00151 
00152   class ParamCommandCommentBitfields {
00153     friend class ParamCommandComment;
00154 
00155     unsigned : NumBlockCommandCommentBits;
00156 
00157     /// Parameter passing direction, see ParamCommandComment::PassDirection.
00158     unsigned Direction : 2;
00159 
00160     /// True if direction was specified explicitly in the comment.
00161     unsigned IsDirectionExplicit : 1;
00162   };
00163   enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
00164 
00165   union {
00166     CommentBitfields CommentBits;
00167     InlineContentCommentBitfields InlineContentCommentBits;
00168     TextCommentBitfields TextCommentBits;
00169     InlineCommandCommentBitfields InlineCommandCommentBits;
00170     HTMLTagCommentBitfields HTMLTagCommentBits;
00171     HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
00172     ParagraphCommentBitfields ParagraphCommentBits;
00173     BlockCommandCommentBitfields BlockCommandCommentBits;
00174     ParamCommandCommentBitfields ParamCommandCommentBits;
00175   };
00176 
00177   void setSourceRange(SourceRange SR) {
00178     Range = SR;
00179   }
00180 
00181   void setLocation(SourceLocation L) {
00182     Loc = L;
00183   }
00184 
00185 public:
00186   enum CommentKind {
00187     NoCommentKind = 0,
00188 #define COMMENT(CLASS, PARENT) CLASS##Kind,
00189 #define COMMENT_RANGE(BASE, FIRST, LAST) \
00190     First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
00191 #define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
00192     First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
00193 #define ABSTRACT_COMMENT(COMMENT)
00194 #include "clang/AST/CommentNodes.inc"
00195   };
00196 
00197   Comment(CommentKind K,
00198           SourceLocation LocBegin,
00199           SourceLocation LocEnd) :
00200       Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
00201     CommentBits.Kind = K;
00202   }
00203 
00204   CommentKind getCommentKind() const {
00205     return static_cast<CommentKind>(CommentBits.Kind);
00206   }
00207 
00208   const char *getCommentKindName() const;
00209 
00210   void dump() const;
00211   void dumpColor() const;
00212   void dump(const ASTContext &Context) const;
00213   void dump(raw_ostream &OS, const CommandTraits *Traits,
00214             const SourceManager *SM) const;
00215 
00216   SourceRange getSourceRange() const LLVM_READONLY { return Range; }
00217 
00218   SourceLocation getLocStart() const LLVM_READONLY {
00219     return Range.getBegin();
00220   }
00221 
00222   SourceLocation getLocEnd() const LLVM_READONLY {
00223     return Range.getEnd();
00224   }
00225 
00226   SourceLocation getLocation() const LLVM_READONLY { return Loc; }
00227 
00228   typedef Comment * const *child_iterator;
00229 
00230   child_iterator child_begin() const;
00231   child_iterator child_end() const;
00232 
00233   // TODO: const child iterator
00234 
00235   unsigned child_count() const {
00236     return child_end() - child_begin();
00237   }
00238 };
00239 
00240 /// Inline content (contained within a block).
00241 /// Abstract class.
00242 class InlineContentComment : public Comment {
00243 protected:
00244   InlineContentComment(CommentKind K,
00245                        SourceLocation LocBegin,
00246                        SourceLocation LocEnd) :
00247       Comment(K, LocBegin, LocEnd) {
00248     InlineContentCommentBits.HasTrailingNewline = 0;
00249   }
00250 
00251 public:
00252   static bool classof(const Comment *C) {
00253     return C->getCommentKind() >= FirstInlineContentCommentConstant &&
00254            C->getCommentKind() <= LastInlineContentCommentConstant;
00255   }
00256 
00257   void addTrailingNewline() {
00258     InlineContentCommentBits.HasTrailingNewline = 1;
00259   }
00260 
00261   bool hasTrailingNewline() const {
00262     return InlineContentCommentBits.HasTrailingNewline;
00263   }
00264 };
00265 
00266 /// Plain text.
00267 class TextComment : public InlineContentComment {
00268   StringRef Text;
00269 
00270 public:
00271   TextComment(SourceLocation LocBegin,
00272               SourceLocation LocEnd,
00273               StringRef Text) :
00274       InlineContentComment(TextCommentKind, LocBegin, LocEnd),
00275       Text(Text) {
00276     TextCommentBits.IsWhitespaceValid = false;
00277   }
00278 
00279   static bool classof(const Comment *C) {
00280     return C->getCommentKind() == TextCommentKind;
00281   }
00282 
00283   child_iterator child_begin() const { return nullptr; }
00284 
00285   child_iterator child_end() const { return nullptr; }
00286 
00287   StringRef getText() const LLVM_READONLY { return Text; }
00288 
00289   bool isWhitespace() const {
00290     if (TextCommentBits.IsWhitespaceValid)
00291       return TextCommentBits.IsWhitespace;
00292 
00293     TextCommentBits.IsWhitespace = isWhitespaceNoCache();
00294     TextCommentBits.IsWhitespaceValid = true;
00295     return TextCommentBits.IsWhitespace;
00296   }
00297 
00298 private:
00299   bool isWhitespaceNoCache() const;
00300 };
00301 
00302 /// A command with word-like arguments that is considered inline content.
00303 class InlineCommandComment : public InlineContentComment {
00304 public:
00305   struct Argument {
00306     SourceRange Range;
00307     StringRef Text;
00308 
00309     Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
00310   };
00311 
00312   /// The most appropriate rendering mode for this command, chosen on command
00313   /// semantics in Doxygen.
00314   enum RenderKind {
00315     RenderNormal,
00316     RenderBold,
00317     RenderMonospaced,
00318     RenderEmphasized
00319   };
00320 
00321 protected:
00322   /// Command arguments.
00323   ArrayRef<Argument> Args;
00324 
00325 public:
00326   InlineCommandComment(SourceLocation LocBegin,
00327                        SourceLocation LocEnd,
00328                        unsigned CommandID,
00329                        RenderKind RK,
00330                        ArrayRef<Argument> Args) :
00331       InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
00332       Args(Args) {
00333     InlineCommandCommentBits.RenderKind = RK;
00334     InlineCommandCommentBits.CommandID = CommandID;
00335   }
00336 
00337   static bool classof(const Comment *C) {
00338     return C->getCommentKind() == InlineCommandCommentKind;
00339   }
00340 
00341   child_iterator child_begin() const { return nullptr; }
00342 
00343   child_iterator child_end() const { return nullptr; }
00344 
00345   unsigned getCommandID() const {
00346     return InlineCommandCommentBits.CommandID;
00347   }
00348 
00349   StringRef getCommandName(const CommandTraits &Traits) const {
00350     return Traits.getCommandInfo(getCommandID())->Name;
00351   }
00352 
00353   SourceRange getCommandNameRange() const {
00354     return SourceRange(getLocStart().getLocWithOffset(-1),
00355                        getLocEnd());
00356   }
00357 
00358   RenderKind getRenderKind() const {
00359     return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
00360   }
00361 
00362   unsigned getNumArgs() const {
00363     return Args.size();
00364   }
00365 
00366   StringRef getArgText(unsigned Idx) const {
00367     return Args[Idx].Text;
00368   }
00369 
00370   SourceRange getArgRange(unsigned Idx) const {
00371     return Args[Idx].Range;
00372   }
00373 };
00374 
00375 /// Abstract class for opening and closing HTML tags.  HTML tags are always
00376 /// treated as inline content (regardless HTML semantics).
00377 class HTMLTagComment : public InlineContentComment {
00378 protected:
00379   StringRef TagName;
00380   SourceRange TagNameRange;
00381 
00382   HTMLTagComment(CommentKind K,
00383                  SourceLocation LocBegin,
00384                  SourceLocation LocEnd,
00385                  StringRef TagName,
00386                  SourceLocation TagNameBegin,
00387                  SourceLocation TagNameEnd) :
00388       InlineContentComment(K, LocBegin, LocEnd),
00389       TagName(TagName),
00390       TagNameRange(TagNameBegin, TagNameEnd) {
00391     setLocation(TagNameBegin);
00392     HTMLTagCommentBits.IsMalformed = 0;
00393   }
00394 
00395 public:
00396   static bool classof(const Comment *C) {
00397     return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
00398            C->getCommentKind() <= LastHTMLTagCommentConstant;
00399   }
00400 
00401   StringRef getTagName() const LLVM_READONLY { return TagName; }
00402 
00403   SourceRange getTagNameSourceRange() const LLVM_READONLY {
00404     SourceLocation L = getLocation();
00405     return SourceRange(L.getLocWithOffset(1),
00406                        L.getLocWithOffset(1 + TagName.size()));
00407   }
00408 
00409   bool isMalformed() const {
00410     return HTMLTagCommentBits.IsMalformed;
00411   }
00412 
00413   void setIsMalformed() {
00414     HTMLTagCommentBits.IsMalformed = 1;
00415   }
00416 };
00417 
00418 /// An opening HTML tag with attributes.
00419 class HTMLStartTagComment : public HTMLTagComment {
00420 public:
00421   class Attribute {
00422   public:
00423     SourceLocation NameLocBegin;
00424     StringRef Name;
00425 
00426     SourceLocation EqualsLoc;
00427 
00428     SourceRange ValueRange;
00429     StringRef Value;
00430 
00431     Attribute() { }
00432 
00433     Attribute(SourceLocation NameLocBegin, StringRef Name) :
00434         NameLocBegin(NameLocBegin), Name(Name),
00435         EqualsLoc(SourceLocation()),
00436         ValueRange(SourceRange()), Value(StringRef())
00437     { }
00438 
00439     Attribute(SourceLocation NameLocBegin, StringRef Name,
00440               SourceLocation EqualsLoc,
00441               SourceRange ValueRange, StringRef Value) :
00442         NameLocBegin(NameLocBegin), Name(Name),
00443         EqualsLoc(EqualsLoc),
00444         ValueRange(ValueRange), Value(Value)
00445     { }
00446 
00447     SourceLocation getNameLocEnd() const {
00448       return NameLocBegin.getLocWithOffset(Name.size());
00449     }
00450 
00451     SourceRange getNameRange() const {
00452       return SourceRange(NameLocBegin, getNameLocEnd());
00453     }
00454   };
00455 
00456 private:
00457   ArrayRef<Attribute> Attributes;
00458 
00459 public:
00460   HTMLStartTagComment(SourceLocation LocBegin,
00461                       StringRef TagName) :
00462       HTMLTagComment(HTMLStartTagCommentKind,
00463                      LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
00464                      TagName,
00465                      LocBegin.getLocWithOffset(1),
00466                      LocBegin.getLocWithOffset(1 + TagName.size())) {
00467     HTMLStartTagCommentBits.IsSelfClosing = false;
00468   }
00469 
00470   static bool classof(const Comment *C) {
00471     return C->getCommentKind() == HTMLStartTagCommentKind;
00472   }
00473 
00474   child_iterator child_begin() const { return nullptr; }
00475 
00476   child_iterator child_end() const { return nullptr; }
00477 
00478   unsigned getNumAttrs() const {
00479     return Attributes.size();
00480   }
00481 
00482   const Attribute &getAttr(unsigned Idx) const {
00483     return Attributes[Idx];
00484   }
00485 
00486   void setAttrs(ArrayRef<Attribute> Attrs) {
00487     Attributes = Attrs;
00488     if (!Attrs.empty()) {
00489       const Attribute &Attr = Attrs.back();
00490       SourceLocation L = Attr.ValueRange.getEnd();
00491       if (L.isValid())
00492         Range.setEnd(L);
00493       else {
00494         Range.setEnd(Attr.getNameLocEnd());
00495       }
00496     }
00497   }
00498 
00499   void setGreaterLoc(SourceLocation GreaterLoc) {
00500     Range.setEnd(GreaterLoc);
00501   }
00502 
00503   bool isSelfClosing() const {
00504     return HTMLStartTagCommentBits.IsSelfClosing;
00505   }
00506 
00507   void setSelfClosing() {
00508     HTMLStartTagCommentBits.IsSelfClosing = true;
00509   }
00510 };
00511 
00512 /// A closing HTML tag.
00513 class HTMLEndTagComment : public HTMLTagComment {
00514 public:
00515   HTMLEndTagComment(SourceLocation LocBegin,
00516                     SourceLocation LocEnd,
00517                     StringRef TagName) :
00518       HTMLTagComment(HTMLEndTagCommentKind,
00519                      LocBegin, LocEnd,
00520                      TagName,
00521                      LocBegin.getLocWithOffset(2),
00522                      LocBegin.getLocWithOffset(2 + TagName.size()))
00523   { }
00524 
00525   static bool classof(const Comment *C) {
00526     return C->getCommentKind() == HTMLEndTagCommentKind;
00527   }
00528 
00529   child_iterator child_begin() const { return nullptr; }
00530 
00531   child_iterator child_end() const { return nullptr; }
00532 };
00533 
00534 /// Block content (contains inline content).
00535 /// Abstract class.
00536 class BlockContentComment : public Comment {
00537 protected:
00538   BlockContentComment(CommentKind K,
00539                       SourceLocation LocBegin,
00540                       SourceLocation LocEnd) :
00541       Comment(K, LocBegin, LocEnd)
00542   { }
00543 
00544 public:
00545   static bool classof(const Comment *C) {
00546     return C->getCommentKind() >= FirstBlockContentCommentConstant &&
00547            C->getCommentKind() <= LastBlockContentCommentConstant;
00548   }
00549 };
00550 
00551 /// A single paragraph that contains inline content.
00552 class ParagraphComment : public BlockContentComment {
00553   ArrayRef<InlineContentComment *> Content;
00554 
00555 public:
00556   ParagraphComment(ArrayRef<InlineContentComment *> Content) :
00557       BlockContentComment(ParagraphCommentKind,
00558                           SourceLocation(),
00559                           SourceLocation()),
00560       Content(Content) {
00561     if (Content.empty()) {
00562       ParagraphCommentBits.IsWhitespace = true;
00563       ParagraphCommentBits.IsWhitespaceValid = true;
00564       return;
00565     }
00566 
00567     ParagraphCommentBits.IsWhitespaceValid = false;
00568 
00569     setSourceRange(SourceRange(Content.front()->getLocStart(),
00570                                Content.back()->getLocEnd()));
00571     setLocation(Content.front()->getLocStart());
00572   }
00573 
00574   static bool classof(const Comment *C) {
00575     return C->getCommentKind() == ParagraphCommentKind;
00576   }
00577 
00578   child_iterator child_begin() const {
00579     return reinterpret_cast<child_iterator>(Content.begin());
00580   }
00581 
00582   child_iterator child_end() const {
00583     return reinterpret_cast<child_iterator>(Content.end());
00584   }
00585 
00586   bool isWhitespace() const {
00587     if (ParagraphCommentBits.IsWhitespaceValid)
00588       return ParagraphCommentBits.IsWhitespace;
00589 
00590     ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
00591     ParagraphCommentBits.IsWhitespaceValid = true;
00592     return ParagraphCommentBits.IsWhitespace;
00593   }
00594 
00595 private:
00596   bool isWhitespaceNoCache() const;
00597 };
00598 
00599 /// A command that has zero or more word-like arguments (number of word-like
00600 /// arguments depends on command name) and a paragraph as an argument
00601 /// (e. g., \\brief).
00602 class BlockCommandComment : public BlockContentComment {
00603 public:
00604   struct Argument {
00605     SourceRange Range;
00606     StringRef Text;
00607 
00608     Argument() { }
00609     Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
00610   };
00611 
00612 protected:
00613   /// Word-like arguments.
00614   ArrayRef<Argument> Args;
00615 
00616   /// Paragraph argument.
00617   ParagraphComment *Paragraph;
00618 
00619   BlockCommandComment(CommentKind K,
00620                       SourceLocation LocBegin,
00621                       SourceLocation LocEnd,
00622                       unsigned CommandID,
00623                       CommandMarkerKind CommandMarker) :
00624       BlockContentComment(K, LocBegin, LocEnd),
00625       Paragraph(nullptr) {
00626     setLocation(getCommandNameBeginLoc());
00627     BlockCommandCommentBits.CommandID = CommandID;
00628     BlockCommandCommentBits.CommandMarker = CommandMarker;
00629   }
00630 
00631 public:
00632   BlockCommandComment(SourceLocation LocBegin,
00633                       SourceLocation LocEnd,
00634                       unsigned CommandID,
00635                       CommandMarkerKind CommandMarker) :
00636       BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
00637       Paragraph(nullptr) {
00638     setLocation(getCommandNameBeginLoc());
00639     BlockCommandCommentBits.CommandID = CommandID;
00640     BlockCommandCommentBits.CommandMarker = CommandMarker;
00641   }
00642 
00643   static bool classof(const Comment *C) {
00644     return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
00645            C->getCommentKind() <= LastBlockCommandCommentConstant;
00646   }
00647 
00648   child_iterator child_begin() const {
00649     return reinterpret_cast<child_iterator>(&Paragraph);
00650   }
00651 
00652   child_iterator child_end() const {
00653     return reinterpret_cast<child_iterator>(&Paragraph + 1);
00654   }
00655 
00656   unsigned getCommandID() const {
00657     return BlockCommandCommentBits.CommandID;
00658   }
00659 
00660   StringRef getCommandName(const CommandTraits &Traits) const {
00661     return Traits.getCommandInfo(getCommandID())->Name;
00662   }
00663 
00664   SourceLocation getCommandNameBeginLoc() const {
00665     return getLocStart().getLocWithOffset(1);
00666   }
00667 
00668   SourceRange getCommandNameRange(const CommandTraits &Traits) const {
00669     StringRef Name = getCommandName(Traits);
00670     return SourceRange(getCommandNameBeginLoc(),
00671                        getLocStart().getLocWithOffset(1 + Name.size()));
00672   }
00673 
00674   unsigned getNumArgs() const {
00675     return Args.size();
00676   }
00677 
00678   StringRef getArgText(unsigned Idx) const {
00679     return Args[Idx].Text;
00680   }
00681 
00682   SourceRange getArgRange(unsigned Idx) const {
00683     return Args[Idx].Range;
00684   }
00685 
00686   void setArgs(ArrayRef<Argument> A) {
00687     Args = A;
00688     if (Args.size() > 0) {
00689       SourceLocation NewLocEnd = Args.back().Range.getEnd();
00690       if (NewLocEnd.isValid())
00691         setSourceRange(SourceRange(getLocStart(), NewLocEnd));
00692     }
00693   }
00694 
00695   ParagraphComment *getParagraph() const LLVM_READONLY {
00696     return Paragraph;
00697   }
00698 
00699   bool hasNonWhitespaceParagraph() const {
00700     return Paragraph && !Paragraph->isWhitespace();
00701   }
00702 
00703   void setParagraph(ParagraphComment *PC) {
00704     Paragraph = PC;
00705     SourceLocation NewLocEnd = PC->getLocEnd();
00706     if (NewLocEnd.isValid())
00707       setSourceRange(SourceRange(getLocStart(), NewLocEnd));
00708   }
00709 
00710   CommandMarkerKind getCommandMarker() const LLVM_READONLY {
00711     return static_cast<CommandMarkerKind>(
00712         BlockCommandCommentBits.CommandMarker);
00713   }
00714 };
00715 
00716 /// Doxygen \\param command.
00717 class ParamCommandComment : public BlockCommandComment {
00718 private:
00719   /// Parameter index in the function declaration.
00720   unsigned ParamIndex;
00721 
00722 public:
00723   enum : unsigned {
00724     InvalidParamIndex = ~0U,
00725     VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
00726   };
00727 
00728   ParamCommandComment(SourceLocation LocBegin,
00729                       SourceLocation LocEnd,
00730                       unsigned CommandID,
00731                       CommandMarkerKind CommandMarker) :
00732       BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
00733                           CommandID, CommandMarker),
00734       ParamIndex(InvalidParamIndex) {
00735     ParamCommandCommentBits.Direction = In;
00736     ParamCommandCommentBits.IsDirectionExplicit = false;
00737   }
00738 
00739   static bool classof(const Comment *C) {
00740     return C->getCommentKind() == ParamCommandCommentKind;
00741   }
00742 
00743   enum PassDirection {
00744     In,
00745     Out,
00746     InOut
00747   };
00748 
00749   static const char *getDirectionAsString(PassDirection D);
00750 
00751   PassDirection getDirection() const LLVM_READONLY {
00752     return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
00753   }
00754 
00755   bool isDirectionExplicit() const LLVM_READONLY {
00756     return ParamCommandCommentBits.IsDirectionExplicit;
00757   }
00758 
00759   void setDirection(PassDirection Direction, bool Explicit) {
00760     ParamCommandCommentBits.Direction = Direction;
00761     ParamCommandCommentBits.IsDirectionExplicit = Explicit;
00762   }
00763 
00764   bool hasParamName() const {
00765     return getNumArgs() > 0;
00766   }
00767 
00768   StringRef getParamName(const FullComment *FC) const;
00769 
00770   StringRef getParamNameAsWritten() const {
00771     return Args[0].Text;
00772   }
00773 
00774   SourceRange getParamNameRange() const {
00775     return Args[0].Range;
00776   }
00777 
00778   bool isParamIndexValid() const LLVM_READONLY {
00779     return ParamIndex != InvalidParamIndex;
00780   }
00781 
00782   bool isVarArgParam() const LLVM_READONLY {
00783     return ParamIndex == VarArgParamIndex;
00784   }
00785 
00786   void setIsVarArgParam() {
00787     ParamIndex = VarArgParamIndex;
00788     assert(isParamIndexValid());
00789   }
00790 
00791   unsigned getParamIndex() const LLVM_READONLY {
00792     assert(isParamIndexValid());
00793     assert(!isVarArgParam());
00794     return ParamIndex;
00795   }
00796 
00797   void setParamIndex(unsigned Index) {
00798     ParamIndex = Index;
00799     assert(isParamIndexValid());
00800     assert(!isVarArgParam());
00801   }
00802 };
00803 
00804 /// Doxygen \\tparam command, describes a template parameter.
00805 class TParamCommandComment : public BlockCommandComment {
00806 private:
00807   /// If this template parameter name was resolved (found in template parameter
00808   /// list), then this stores a list of position indexes in all template
00809   /// parameter lists.
00810   ///
00811   /// For example:
00812   /// \verbatim
00813   ///     template<typename C, template<typename T> class TT>
00814   ///     void test(TT<int> aaa);
00815   /// \endverbatim
00816   /// For C:  Position = { 0 }
00817   /// For TT: Position = { 1 }
00818   /// For T:  Position = { 1, 0 }
00819   ArrayRef<unsigned> Position;
00820 
00821 public:
00822   TParamCommandComment(SourceLocation LocBegin,
00823                        SourceLocation LocEnd,
00824                        unsigned CommandID,
00825                        CommandMarkerKind CommandMarker) :
00826       BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
00827                           CommandMarker)
00828   { }
00829 
00830   static bool classof(const Comment *C) {
00831     return C->getCommentKind() == TParamCommandCommentKind;
00832   }
00833 
00834   bool hasParamName() const {
00835     return getNumArgs() > 0;
00836   }
00837 
00838   StringRef getParamName(const FullComment *FC) const;
00839 
00840   StringRef getParamNameAsWritten() const {
00841     return Args[0].Text;
00842   }
00843 
00844   SourceRange getParamNameRange() const {
00845     return Args[0].Range;
00846   }
00847 
00848   bool isPositionValid() const LLVM_READONLY {
00849     return !Position.empty();
00850   }
00851 
00852   unsigned getDepth() const {
00853     assert(isPositionValid());
00854     return Position.size();
00855   }
00856 
00857   unsigned getIndex(unsigned Depth) const {
00858     assert(isPositionValid());
00859     return Position[Depth];
00860   }
00861 
00862   void setPosition(ArrayRef<unsigned> NewPosition) {
00863     Position = NewPosition;
00864     assert(isPositionValid());
00865   }
00866 };
00867 
00868 /// A line of text contained in a verbatim block.
00869 class VerbatimBlockLineComment : public Comment {
00870   StringRef Text;
00871 
00872 public:
00873   VerbatimBlockLineComment(SourceLocation LocBegin,
00874                            StringRef Text) :
00875       Comment(VerbatimBlockLineCommentKind,
00876               LocBegin,
00877               LocBegin.getLocWithOffset(Text.size())),
00878       Text(Text)
00879   { }
00880 
00881   static bool classof(const Comment *C) {
00882     return C->getCommentKind() == VerbatimBlockLineCommentKind;
00883   }
00884 
00885   child_iterator child_begin() const { return nullptr; }
00886 
00887   child_iterator child_end() const { return nullptr; }
00888 
00889   StringRef getText() const LLVM_READONLY {
00890     return Text;
00891   }
00892 };
00893 
00894 /// A verbatim block command (e. g., preformatted code).  Verbatim block has an
00895 /// opening and a closing command and contains multiple lines of text
00896 /// (VerbatimBlockLineComment nodes).
00897 class VerbatimBlockComment : public BlockCommandComment {
00898 protected:
00899   StringRef CloseName;
00900   SourceLocation CloseNameLocBegin;
00901   ArrayRef<VerbatimBlockLineComment *> Lines;
00902 
00903 public:
00904   VerbatimBlockComment(SourceLocation LocBegin,
00905                        SourceLocation LocEnd,
00906                        unsigned CommandID) :
00907       BlockCommandComment(VerbatimBlockCommentKind,
00908                           LocBegin, LocEnd, CommandID,
00909                           CMK_At) // FIXME: improve source fidelity.
00910   { }
00911 
00912   static bool classof(const Comment *C) {
00913     return C->getCommentKind() == VerbatimBlockCommentKind;
00914   }
00915 
00916   child_iterator child_begin() const {
00917     return reinterpret_cast<child_iterator>(Lines.begin());
00918   }
00919 
00920   child_iterator child_end() const {
00921     return reinterpret_cast<child_iterator>(Lines.end());
00922   }
00923 
00924   void setCloseName(StringRef Name, SourceLocation LocBegin) {
00925     CloseName = Name;
00926     CloseNameLocBegin = LocBegin;
00927   }
00928 
00929   void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
00930     Lines = L;
00931   }
00932 
00933   StringRef getCloseName() const {
00934     return CloseName;
00935   }
00936 
00937   unsigned getNumLines() const {
00938     return Lines.size();
00939   }
00940 
00941   StringRef getText(unsigned LineIdx) const {
00942     return Lines[LineIdx]->getText();
00943   }
00944 };
00945 
00946 /// A verbatim line command.  Verbatim line has an opening command, a single
00947 /// line of text (up to the newline after the opening command) and has no
00948 /// closing command.
00949 class VerbatimLineComment : public BlockCommandComment {
00950 protected:
00951   StringRef Text;
00952   SourceLocation TextBegin;
00953 
00954 public:
00955   VerbatimLineComment(SourceLocation LocBegin,
00956                       SourceLocation LocEnd,
00957                       unsigned CommandID,
00958                       SourceLocation TextBegin,
00959                       StringRef Text) :
00960       BlockCommandComment(VerbatimLineCommentKind,
00961                           LocBegin, LocEnd,
00962                           CommandID,
00963                           CMK_At), // FIXME: improve source fidelity.
00964       Text(Text),
00965       TextBegin(TextBegin)
00966   { }
00967 
00968   static bool classof(const Comment *C) {
00969     return C->getCommentKind() == VerbatimLineCommentKind;
00970   }
00971 
00972   child_iterator child_begin() const { return nullptr; }
00973 
00974   child_iterator child_end() const { return nullptr; }
00975 
00976   StringRef getText() const {
00977     return Text;
00978   }
00979 
00980   SourceRange getTextRange() const {
00981     return SourceRange(TextBegin, getLocEnd());
00982   }
00983 };
00984 
00985 /// Information about the declaration, useful to clients of FullComment.
00986 struct DeclInfo {
00987   /// Declaration the comment is actually attached to (in the source).
00988   /// Should not be NULL.
00989   const Decl *CommentDecl;
00990   
00991   /// CurrentDecl is the declaration with which the FullComment is associated.
00992   ///
00993   /// It can be different from \c CommentDecl.  It happens when we we decide
00994   /// that the comment originally attached to \c CommentDecl is fine for
00995   /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
00996   /// \c CommentDecl).
00997   ///
00998   /// The information in the DeclInfo corresponds to CurrentDecl.
00999   const Decl *CurrentDecl;
01000   
01001   /// Parameters that can be referenced by \\param if \c CommentDecl is something
01002   /// that we consider a "function".
01003   ArrayRef<const ParmVarDecl *> ParamVars;
01004 
01005   /// Function return type if \c CommentDecl is something that we consider
01006   /// a "function".
01007   QualType ReturnType;
01008 
01009   /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
01010   /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
01011   /// true).
01012   const TemplateParameterList *TemplateParameters;
01013 
01014   /// A simplified description of \c CommentDecl kind that should be good enough
01015   /// for documentation rendering purposes.
01016   enum DeclKind {
01017     /// Everything else not explicitly mentioned below.
01018     OtherKind,
01019 
01020     /// Something that we consider a "function":
01021     /// \li function,
01022     /// \li function template,
01023     /// \li function template specialization,
01024     /// \li member function,
01025     /// \li member function template,
01026     /// \li member function template specialization,
01027     /// \li ObjC method,
01028     /// \li a typedef for a function pointer, member function pointer,
01029     ///     ObjC block.
01030     FunctionKind,
01031 
01032     /// Something that we consider a "class":
01033     /// \li class/struct,
01034     /// \li class template,
01035     /// \li class template (partial) specialization.
01036     ClassKind,
01037 
01038     /// Something that we consider a "variable":
01039     /// \li namespace scope variables;
01040     /// \li static and non-static class data members;
01041     /// \li enumerators.
01042     VariableKind,
01043 
01044     /// A C++ namespace.
01045     NamespaceKind,
01046 
01047     /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
01048     /// see \c TypedefNameDecl.
01049     TypedefKind,
01050 
01051     /// An enumeration or scoped enumeration.
01052     EnumKind
01053   };
01054 
01055   /// What kind of template specialization \c CommentDecl is.
01056   enum TemplateDeclKind {
01057     NotTemplate,
01058     Template,
01059     TemplateSpecialization,
01060     TemplatePartialSpecialization
01061   };
01062 
01063   /// If false, only \c CommentDecl is valid.
01064   unsigned IsFilled : 1;
01065 
01066   /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
01067   unsigned Kind : 3;
01068 
01069   /// Is \c CommentDecl a template declaration.
01070   unsigned TemplateKind : 2;
01071 
01072   /// Is \c CommentDecl an ObjCMethodDecl.
01073   unsigned IsObjCMethod : 1;
01074 
01075   /// Is \c CommentDecl a non-static member function of C++ class or
01076   /// instance method of ObjC class.
01077   /// Can be true only if \c IsFunctionDecl is true.
01078   unsigned IsInstanceMethod : 1;
01079 
01080   /// Is \c CommentDecl a static member function of C++ class or
01081   /// class method of ObjC class.
01082   /// Can be true only if \c IsFunctionDecl is true.
01083   unsigned IsClassMethod : 1;
01084 
01085   void fill();
01086 
01087   DeclKind getKind() const LLVM_READONLY {
01088     return static_cast<DeclKind>(Kind);
01089   }
01090 
01091   TemplateDeclKind getTemplateKind() const LLVM_READONLY {
01092     return static_cast<TemplateDeclKind>(TemplateKind);
01093   }
01094 };
01095 
01096 /// A full comment attached to a declaration, contains block content.
01097 class FullComment : public Comment {
01098   ArrayRef<BlockContentComment *> Blocks;
01099   DeclInfo *ThisDeclInfo;
01100 
01101 public:
01102   FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
01103       Comment(FullCommentKind, SourceLocation(), SourceLocation()),
01104       Blocks(Blocks), ThisDeclInfo(D) {
01105     if (Blocks.empty())
01106       return;
01107 
01108     setSourceRange(SourceRange(Blocks.front()->getLocStart(),
01109                                Blocks.back()->getLocEnd()));
01110     setLocation(Blocks.front()->getLocStart());
01111   }
01112 
01113   static bool classof(const Comment *C) {
01114     return C->getCommentKind() == FullCommentKind;
01115   }
01116 
01117   child_iterator child_begin() const {
01118     return reinterpret_cast<child_iterator>(Blocks.begin());
01119   }
01120 
01121   child_iterator child_end() const {
01122     return reinterpret_cast<child_iterator>(Blocks.end()); 
01123   }
01124 
01125   const Decl *getDecl() const LLVM_READONLY {
01126     return ThisDeclInfo->CommentDecl;
01127   }
01128   
01129   const DeclInfo *getDeclInfo() const LLVM_READONLY {
01130     if (!ThisDeclInfo->IsFilled)
01131       ThisDeclInfo->fill();
01132     return ThisDeclInfo;
01133   }
01134   
01135   ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
01136   
01137 };
01138 } // end namespace comments
01139 } // end namespace clang
01140 
01141 #endif
01142