Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file defines comment AST nodes.
  10. //
  11. //===----------------------------------------------------------------------===//
  12.  
  13. #ifndef LLVM_CLANG_AST_COMMENT_H
  14. #define LLVM_CLANG_AST_COMMENT_H
  15.  
  16. #include "clang/AST/CommentCommandTraits.h"
  17. #include "clang/AST/DeclObjC.h"
  18. #include "clang/AST/Type.h"
  19. #include "clang/Basic/SourceLocation.h"
  20. #include "llvm/ADT/ArrayRef.h"
  21. #include "llvm/ADT/StringRef.h"
  22.  
  23. namespace clang {
  24. class Decl;
  25. class ParmVarDecl;
  26. class TemplateParameterList;
  27.  
  28. namespace comments {
  29. class FullComment;
  30.  
  31. /// Describes the syntax that was used in a documentation command.
  32. ///
  33. /// Exact values of this enumeration are important because they used to select
  34. /// parts of diagnostic messages.  Audit diagnostics before changing or adding
  35. /// a new value.
  36. enum CommandMarkerKind {
  37.   /// Command started with a backslash character:
  38.   /// \code
  39.   ///   \foo
  40.   /// \endcode
  41.   CMK_Backslash = 0,
  42.  
  43.   /// Command started with an 'at' character:
  44.   /// \code
  45.   ///   @foo
  46.   /// \endcode
  47.   CMK_At = 1
  48. };
  49.  
  50. /// Any part of the comment.
  51. /// Abstract class.
  52. class Comment {
  53. protected:
  54.   /// Preferred location to show caret.
  55.   SourceLocation Loc;
  56.  
  57.   /// Source range of this AST node.
  58.   SourceRange Range;
  59.  
  60.   class CommentBitfields {
  61.     friend class Comment;
  62.  
  63.     /// Type of this AST node.
  64.     unsigned Kind : 8;
  65.   };
  66.   enum { NumCommentBits = 8 };
  67.  
  68.   class InlineContentCommentBitfields {
  69.     friend class InlineContentComment;
  70.  
  71.     unsigned : NumCommentBits;
  72.  
  73.     /// True if there is a newline after this inline content node.
  74.     /// (There is no separate AST node for a newline.)
  75.     unsigned HasTrailingNewline : 1;
  76.   };
  77.   enum { NumInlineContentCommentBits = NumCommentBits + 1 };
  78.  
  79.   class TextCommentBitfields {
  80.     friend class TextComment;
  81.  
  82.     unsigned : NumInlineContentCommentBits;
  83.  
  84.     /// True if \c IsWhitespace field contains a valid value.
  85.     mutable unsigned IsWhitespaceValid : 1;
  86.  
  87.     /// True if this comment AST node contains only whitespace.
  88.     mutable unsigned IsWhitespace : 1;
  89.   };
  90.   enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
  91.  
  92.   class InlineCommandCommentBitfields {
  93.     friend class InlineCommandComment;
  94.  
  95.     unsigned : NumInlineContentCommentBits;
  96.  
  97.     unsigned RenderKind : 3;
  98.  
  99.     unsigned CommandID : CommandInfo::NumCommandIDBits;
  100.   };
  101.   enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 3 +
  102.                                        CommandInfo::NumCommandIDBits };
  103.  
  104.   class HTMLTagCommentBitfields {
  105.     friend class HTMLTagComment;
  106.  
  107.     unsigned : NumInlineContentCommentBits;
  108.  
  109.     /// True if we found that this tag is malformed in some way.
  110.     unsigned IsMalformed : 1;
  111.   };
  112.   enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };
  113.  
  114.   class HTMLStartTagCommentBitfields {
  115.     friend class HTMLStartTagComment;
  116.  
  117.     unsigned : NumHTMLTagCommentBits;
  118.  
  119.     /// True if this tag is self-closing (e. g., <br />).  This is based on tag
  120.     /// spelling in comment (plain <br> would not set this flag).
  121.     unsigned IsSelfClosing : 1;
  122.   };
  123.   enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
  124.  
  125.   class ParagraphCommentBitfields {
  126.     friend class ParagraphComment;
  127.  
  128.     unsigned : NumCommentBits;
  129.  
  130.     /// True if \c IsWhitespace field contains a valid value.
  131.     mutable unsigned IsWhitespaceValid : 1;
  132.  
  133.     /// True if this comment AST node contains only whitespace.
  134.     mutable unsigned IsWhitespace : 1;
  135.   };
  136.   enum { NumParagraphCommentBits = NumCommentBits + 2 };
  137.  
  138.   class BlockCommandCommentBitfields {
  139.     friend class BlockCommandComment;
  140.  
  141.     unsigned : NumCommentBits;
  142.  
  143.     unsigned CommandID : CommandInfo::NumCommandIDBits;
  144.  
  145.     /// Describes the syntax that was used in a documentation command.
  146.     /// Contains values from CommandMarkerKind enum.
  147.     unsigned CommandMarker : 1;
  148.   };
  149.   enum { NumBlockCommandCommentBits = NumCommentBits +
  150.                                       CommandInfo::NumCommandIDBits + 1 };
  151.  
  152.   class ParamCommandCommentBitfields {
  153.     friend class ParamCommandComment;
  154.  
  155.     unsigned : NumBlockCommandCommentBits;
  156.  
  157.     /// Parameter passing direction, see ParamCommandComment::PassDirection.
  158.     unsigned Direction : 2;
  159.  
  160.     /// True if direction was specified explicitly in the comment.
  161.     unsigned IsDirectionExplicit : 1;
  162.   };
  163.   enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
  164.  
  165.   union {
  166.     CommentBitfields CommentBits;
  167.     InlineContentCommentBitfields InlineContentCommentBits;
  168.     TextCommentBitfields TextCommentBits;
  169.     InlineCommandCommentBitfields InlineCommandCommentBits;
  170.     HTMLTagCommentBitfields HTMLTagCommentBits;
  171.     HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
  172.     ParagraphCommentBitfields ParagraphCommentBits;
  173.     BlockCommandCommentBitfields BlockCommandCommentBits;
  174.     ParamCommandCommentBitfields ParamCommandCommentBits;
  175.   };
  176.  
  177.   void setSourceRange(SourceRange SR) {
  178.     Range = SR;
  179.   }
  180.  
  181.   void setLocation(SourceLocation L) {
  182.     Loc = L;
  183.   }
  184.  
  185. public:
  186.   enum CommentKind {
  187.     NoCommentKind = 0,
  188. #define COMMENT(CLASS, PARENT) CLASS##Kind,
  189. #define COMMENT_RANGE(BASE, FIRST, LAST) \
  190.     First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
  191. #define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
  192.     First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
  193. #define ABSTRACT_COMMENT(COMMENT)
  194. #include "clang/AST/CommentNodes.inc"
  195.   };
  196.  
  197.   struct Argument {
  198.     SourceRange Range;
  199.     StringRef Text;
  200.   };
  201.  
  202.   Comment(CommentKind K,
  203.           SourceLocation LocBegin,
  204.           SourceLocation LocEnd) :
  205.       Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
  206.     CommentBits.Kind = K;
  207.   }
  208.  
  209.   CommentKind getCommentKind() const {
  210.     return static_cast<CommentKind>(CommentBits.Kind);
  211.   }
  212.  
  213.   const char *getCommentKindName() const;
  214.  
  215.   void dump() const;
  216.   void dumpColor() const;
  217.   void dump(raw_ostream &OS, const ASTContext &Context) const;
  218.  
  219.   SourceRange getSourceRange() const LLVM_READONLY { return Range; }
  220.  
  221.   SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  222.  
  223.   SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
  224.  
  225.   SourceLocation getLocation() const LLVM_READONLY { return Loc; }
  226.  
  227.   typedef Comment * const *child_iterator;
  228.  
  229.   child_iterator child_begin() const;
  230.   child_iterator child_end() const;
  231.  
  232.   // TODO: const child iterator
  233.  
  234.   unsigned child_count() const {
  235.     return child_end() - child_begin();
  236.   }
  237. };
  238.  
  239. /// Inline content (contained within a block).
  240. /// Abstract class.
  241. class InlineContentComment : public Comment {
  242. protected:
  243.   InlineContentComment(CommentKind K,
  244.                        SourceLocation LocBegin,
  245.                        SourceLocation LocEnd) :
  246.       Comment(K, LocBegin, LocEnd) {
  247.     InlineContentCommentBits.HasTrailingNewline = 0;
  248.   }
  249.  
  250. public:
  251.   static bool classof(const Comment *C) {
  252.     return C->getCommentKind() >= FirstInlineContentCommentConstant &&
  253.            C->getCommentKind() <= LastInlineContentCommentConstant;
  254.   }
  255.  
  256.   void addTrailingNewline() {
  257.     InlineContentCommentBits.HasTrailingNewline = 1;
  258.   }
  259.  
  260.   bool hasTrailingNewline() const {
  261.     return InlineContentCommentBits.HasTrailingNewline;
  262.   }
  263. };
  264.  
  265. /// Plain text.
  266. class TextComment : public InlineContentComment {
  267.   StringRef Text;
  268.  
  269. public:
  270.   TextComment(SourceLocation LocBegin,
  271.               SourceLocation LocEnd,
  272.               StringRef Text) :
  273.       InlineContentComment(TextCommentKind, LocBegin, LocEnd),
  274.       Text(Text) {
  275.     TextCommentBits.IsWhitespaceValid = false;
  276.   }
  277.  
  278.   static bool classof(const Comment *C) {
  279.     return C->getCommentKind() == TextCommentKind;
  280.   }
  281.  
  282.   child_iterator child_begin() const { return nullptr; }
  283.  
  284.   child_iterator child_end() const { return nullptr; }
  285.  
  286.   StringRef getText() const LLVM_READONLY { return Text; }
  287.  
  288.   bool isWhitespace() const {
  289.     if (TextCommentBits.IsWhitespaceValid)
  290.       return TextCommentBits.IsWhitespace;
  291.  
  292.     TextCommentBits.IsWhitespace = isWhitespaceNoCache();
  293.     TextCommentBits.IsWhitespaceValid = true;
  294.     return TextCommentBits.IsWhitespace;
  295.   }
  296.  
  297. private:
  298.   bool isWhitespaceNoCache() const;
  299. };
  300.  
  301. /// A command with word-like arguments that is considered inline content.
  302. class InlineCommandComment : public InlineContentComment {
  303. public:
  304.   /// The most appropriate rendering mode for this command, chosen on command
  305.   /// semantics in Doxygen.
  306.   enum RenderKind {
  307.     RenderNormal,
  308.     RenderBold,
  309.     RenderMonospaced,
  310.     RenderEmphasized,
  311.     RenderAnchor
  312.   };
  313.  
  314. protected:
  315.   /// Command arguments.
  316.   ArrayRef<Argument> Args;
  317.  
  318. public:
  319.   InlineCommandComment(SourceLocation LocBegin,
  320.                        SourceLocation LocEnd,
  321.                        unsigned CommandID,
  322.                        RenderKind RK,
  323.                        ArrayRef<Argument> Args) :
  324.       InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
  325.       Args(Args) {
  326.     InlineCommandCommentBits.RenderKind = RK;
  327.     InlineCommandCommentBits.CommandID = CommandID;
  328.   }
  329.  
  330.   static bool classof(const Comment *C) {
  331.     return C->getCommentKind() == InlineCommandCommentKind;
  332.   }
  333.  
  334.   child_iterator child_begin() const { return nullptr; }
  335.  
  336.   child_iterator child_end() const { return nullptr; }
  337.  
  338.   unsigned getCommandID() const {
  339.     return InlineCommandCommentBits.CommandID;
  340.   }
  341.  
  342.   StringRef getCommandName(const CommandTraits &Traits) const {
  343.     return Traits.getCommandInfo(getCommandID())->Name;
  344.   }
  345.  
  346.   SourceRange getCommandNameRange() const {
  347.     return SourceRange(getBeginLoc().getLocWithOffset(-1), getEndLoc());
  348.   }
  349.  
  350.   RenderKind getRenderKind() const {
  351.     return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
  352.   }
  353.  
  354.   unsigned getNumArgs() const {
  355.     return Args.size();
  356.   }
  357.  
  358.   StringRef getArgText(unsigned Idx) const {
  359.     return Args[Idx].Text;
  360.   }
  361.  
  362.   SourceRange getArgRange(unsigned Idx) const {
  363.     return Args[Idx].Range;
  364.   }
  365. };
  366.  
  367. /// Abstract class for opening and closing HTML tags.  HTML tags are always
  368. /// treated as inline content (regardless HTML semantics).
  369. class HTMLTagComment : public InlineContentComment {
  370. protected:
  371.   StringRef TagName;
  372.   SourceRange TagNameRange;
  373.  
  374.   HTMLTagComment(CommentKind K,
  375.                  SourceLocation LocBegin,
  376.                  SourceLocation LocEnd,
  377.                  StringRef TagName,
  378.                  SourceLocation TagNameBegin,
  379.                  SourceLocation TagNameEnd) :
  380.       InlineContentComment(K, LocBegin, LocEnd),
  381.       TagName(TagName),
  382.       TagNameRange(TagNameBegin, TagNameEnd) {
  383.     setLocation(TagNameBegin);
  384.     HTMLTagCommentBits.IsMalformed = 0;
  385.   }
  386.  
  387. public:
  388.   static bool classof(const Comment *C) {
  389.     return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
  390.            C->getCommentKind() <= LastHTMLTagCommentConstant;
  391.   }
  392.  
  393.   StringRef getTagName() const LLVM_READONLY { return TagName; }
  394.  
  395.   SourceRange getTagNameSourceRange() const LLVM_READONLY {
  396.     SourceLocation L = getLocation();
  397.     return SourceRange(L.getLocWithOffset(1),
  398.                        L.getLocWithOffset(1 + TagName.size()));
  399.   }
  400.  
  401.   bool isMalformed() const {
  402.     return HTMLTagCommentBits.IsMalformed;
  403.   }
  404.  
  405.   void setIsMalformed() {
  406.     HTMLTagCommentBits.IsMalformed = 1;
  407.   }
  408. };
  409.  
  410. /// An opening HTML tag with attributes.
  411. class HTMLStartTagComment : public HTMLTagComment {
  412. public:
  413.   class Attribute {
  414.   public:
  415.     SourceLocation NameLocBegin;
  416.     StringRef Name;
  417.  
  418.     SourceLocation EqualsLoc;
  419.  
  420.     SourceRange ValueRange;
  421.     StringRef Value;
  422.  
  423.     Attribute() { }
  424.  
  425.     Attribute(SourceLocation NameLocBegin, StringRef Name)
  426.         : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(SourceLocation()) {}
  427.  
  428.     Attribute(SourceLocation NameLocBegin, StringRef Name,
  429.               SourceLocation EqualsLoc, SourceRange ValueRange, StringRef Value)
  430.         : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(EqualsLoc),
  431.           ValueRange(ValueRange), Value(Value) {}
  432.  
  433.     SourceLocation getNameLocEnd() const {
  434.       return NameLocBegin.getLocWithOffset(Name.size());
  435.     }
  436.  
  437.     SourceRange getNameRange() const {
  438.       return SourceRange(NameLocBegin, getNameLocEnd());
  439.     }
  440.   };
  441.  
  442. private:
  443.   ArrayRef<Attribute> Attributes;
  444.  
  445. public:
  446.   HTMLStartTagComment(SourceLocation LocBegin,
  447.                       StringRef TagName) :
  448.       HTMLTagComment(HTMLStartTagCommentKind,
  449.                      LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
  450.                      TagName,
  451.                      LocBegin.getLocWithOffset(1),
  452.                      LocBegin.getLocWithOffset(1 + TagName.size())) {
  453.     HTMLStartTagCommentBits.IsSelfClosing = false;
  454.   }
  455.  
  456.   static bool classof(const Comment *C) {
  457.     return C->getCommentKind() == HTMLStartTagCommentKind;
  458.   }
  459.  
  460.   child_iterator child_begin() const { return nullptr; }
  461.  
  462.   child_iterator child_end() const { return nullptr; }
  463.  
  464.   unsigned getNumAttrs() const {
  465.     return Attributes.size();
  466.   }
  467.  
  468.   const Attribute &getAttr(unsigned Idx) const {
  469.     return Attributes[Idx];
  470.   }
  471.  
  472.   void setAttrs(ArrayRef<Attribute> Attrs) {
  473.     Attributes = Attrs;
  474.     if (!Attrs.empty()) {
  475.       const Attribute &Attr = Attrs.back();
  476.       SourceLocation L = Attr.ValueRange.getEnd();
  477.       if (L.isValid())
  478.         Range.setEnd(L);
  479.       else {
  480.         Range.setEnd(Attr.getNameLocEnd());
  481.       }
  482.     }
  483.   }
  484.  
  485.   void setGreaterLoc(SourceLocation GreaterLoc) {
  486.     Range.setEnd(GreaterLoc);
  487.   }
  488.  
  489.   bool isSelfClosing() const {
  490.     return HTMLStartTagCommentBits.IsSelfClosing;
  491.   }
  492.  
  493.   void setSelfClosing() {
  494.     HTMLStartTagCommentBits.IsSelfClosing = true;
  495.   }
  496. };
  497.  
  498. /// A closing HTML tag.
  499. class HTMLEndTagComment : public HTMLTagComment {
  500. public:
  501.   HTMLEndTagComment(SourceLocation LocBegin,
  502.                     SourceLocation LocEnd,
  503.                     StringRef TagName) :
  504.       HTMLTagComment(HTMLEndTagCommentKind,
  505.                      LocBegin, LocEnd,
  506.                      TagName,
  507.                      LocBegin.getLocWithOffset(2),
  508.                      LocBegin.getLocWithOffset(2 + TagName.size()))
  509.   { }
  510.  
  511.   static bool classof(const Comment *C) {
  512.     return C->getCommentKind() == HTMLEndTagCommentKind;
  513.   }
  514.  
  515.   child_iterator child_begin() const { return nullptr; }
  516.  
  517.   child_iterator child_end() const { return nullptr; }
  518. };
  519.  
  520. /// Block content (contains inline content).
  521. /// Abstract class.
  522. class BlockContentComment : public Comment {
  523. protected:
  524.   BlockContentComment(CommentKind K,
  525.                       SourceLocation LocBegin,
  526.                       SourceLocation LocEnd) :
  527.       Comment(K, LocBegin, LocEnd)
  528.   { }
  529.  
  530. public:
  531.   static bool classof(const Comment *C) {
  532.     return C->getCommentKind() >= FirstBlockContentCommentConstant &&
  533.            C->getCommentKind() <= LastBlockContentCommentConstant;
  534.   }
  535. };
  536.  
  537. /// A single paragraph that contains inline content.
  538. class ParagraphComment : public BlockContentComment {
  539.   ArrayRef<InlineContentComment *> Content;
  540.  
  541. public:
  542.   ParagraphComment(ArrayRef<InlineContentComment *> Content) :
  543.       BlockContentComment(ParagraphCommentKind,
  544.                           SourceLocation(),
  545.                           SourceLocation()),
  546.       Content(Content) {
  547.     if (Content.empty()) {
  548.       ParagraphCommentBits.IsWhitespace = true;
  549.       ParagraphCommentBits.IsWhitespaceValid = true;
  550.       return;
  551.     }
  552.  
  553.     ParagraphCommentBits.IsWhitespaceValid = false;
  554.  
  555.     setSourceRange(SourceRange(Content.front()->getBeginLoc(),
  556.                                Content.back()->getEndLoc()));
  557.     setLocation(Content.front()->getBeginLoc());
  558.   }
  559.  
  560.   static bool classof(const Comment *C) {
  561.     return C->getCommentKind() == ParagraphCommentKind;
  562.   }
  563.  
  564.   child_iterator child_begin() const {
  565.     return reinterpret_cast<child_iterator>(Content.begin());
  566.   }
  567.  
  568.   child_iterator child_end() const {
  569.     return reinterpret_cast<child_iterator>(Content.end());
  570.   }
  571.  
  572.   bool isWhitespace() const {
  573.     if (ParagraphCommentBits.IsWhitespaceValid)
  574.       return ParagraphCommentBits.IsWhitespace;
  575.  
  576.     ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
  577.     ParagraphCommentBits.IsWhitespaceValid = true;
  578.     return ParagraphCommentBits.IsWhitespace;
  579.   }
  580.  
  581. private:
  582.   bool isWhitespaceNoCache() const;
  583. };
  584.  
  585. /// A command that has zero or more word-like arguments (number of word-like
  586. /// arguments depends on command name) and a paragraph as an argument
  587. /// (e. g., \\brief).
  588. class BlockCommandComment : public BlockContentComment {
  589. protected:
  590.   /// Word-like arguments.
  591.   ArrayRef<Argument> Args;
  592.  
  593.   /// Paragraph argument.
  594.   ParagraphComment *Paragraph;
  595.  
  596.   BlockCommandComment(CommentKind K,
  597.                       SourceLocation LocBegin,
  598.                       SourceLocation LocEnd,
  599.                       unsigned CommandID,
  600.                       CommandMarkerKind CommandMarker) :
  601.       BlockContentComment(K, LocBegin, LocEnd),
  602.       Paragraph(nullptr) {
  603.     setLocation(getCommandNameBeginLoc());
  604.     BlockCommandCommentBits.CommandID = CommandID;
  605.     BlockCommandCommentBits.CommandMarker = CommandMarker;
  606.   }
  607.  
  608. public:
  609.   BlockCommandComment(SourceLocation LocBegin,
  610.                       SourceLocation LocEnd,
  611.                       unsigned CommandID,
  612.                       CommandMarkerKind CommandMarker) :
  613.       BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
  614.       Paragraph(nullptr) {
  615.     setLocation(getCommandNameBeginLoc());
  616.     BlockCommandCommentBits.CommandID = CommandID;
  617.     BlockCommandCommentBits.CommandMarker = CommandMarker;
  618.   }
  619.  
  620.   static bool classof(const Comment *C) {
  621.     return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
  622.            C->getCommentKind() <= LastBlockCommandCommentConstant;
  623.   }
  624.  
  625.   child_iterator child_begin() const {
  626.     return reinterpret_cast<child_iterator>(&Paragraph);
  627.   }
  628.  
  629.   child_iterator child_end() const {
  630.     return reinterpret_cast<child_iterator>(&Paragraph + 1);
  631.   }
  632.  
  633.   unsigned getCommandID() const {
  634.     return BlockCommandCommentBits.CommandID;
  635.   }
  636.  
  637.   StringRef getCommandName(const CommandTraits &Traits) const {
  638.     return Traits.getCommandInfo(getCommandID())->Name;
  639.   }
  640.  
  641.   SourceLocation getCommandNameBeginLoc() const {
  642.     return getBeginLoc().getLocWithOffset(1);
  643.   }
  644.  
  645.   SourceRange getCommandNameRange(const CommandTraits &Traits) const {
  646.     StringRef Name = getCommandName(Traits);
  647.     return SourceRange(getCommandNameBeginLoc(),
  648.                        getBeginLoc().getLocWithOffset(1 + Name.size()));
  649.   }
  650.  
  651.   unsigned getNumArgs() const {
  652.     return Args.size();
  653.   }
  654.  
  655.   StringRef getArgText(unsigned Idx) const {
  656.     return Args[Idx].Text;
  657.   }
  658.  
  659.   SourceRange getArgRange(unsigned Idx) const {
  660.     return Args[Idx].Range;
  661.   }
  662.  
  663.   void setArgs(ArrayRef<Argument> A) {
  664.     Args = A;
  665.     if (Args.size() > 0) {
  666.       SourceLocation NewLocEnd = Args.back().Range.getEnd();
  667.       if (NewLocEnd.isValid())
  668.         setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
  669.     }
  670.   }
  671.  
  672.   ParagraphComment *getParagraph() const LLVM_READONLY {
  673.     return Paragraph;
  674.   }
  675.  
  676.   bool hasNonWhitespaceParagraph() const {
  677.     return Paragraph && !Paragraph->isWhitespace();
  678.   }
  679.  
  680.   void setParagraph(ParagraphComment *PC) {
  681.     Paragraph = PC;
  682.     SourceLocation NewLocEnd = PC->getEndLoc();
  683.     if (NewLocEnd.isValid())
  684.       setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
  685.   }
  686.  
  687.   CommandMarkerKind getCommandMarker() const LLVM_READONLY {
  688.     return static_cast<CommandMarkerKind>(
  689.         BlockCommandCommentBits.CommandMarker);
  690.   }
  691. };
  692.  
  693. /// Doxygen \\param command.
  694. class ParamCommandComment : public BlockCommandComment {
  695. private:
  696.   /// Parameter index in the function declaration.
  697.   unsigned ParamIndex;
  698.  
  699. public:
  700.   enum : unsigned {
  701.     InvalidParamIndex = ~0U,
  702.     VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
  703.   };
  704.  
  705.   ParamCommandComment(SourceLocation LocBegin,
  706.                       SourceLocation LocEnd,
  707.                       unsigned CommandID,
  708.                       CommandMarkerKind CommandMarker) :
  709.       BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
  710.                           CommandID, CommandMarker),
  711.       ParamIndex(InvalidParamIndex) {
  712.     ParamCommandCommentBits.Direction = In;
  713.     ParamCommandCommentBits.IsDirectionExplicit = false;
  714.   }
  715.  
  716.   static bool classof(const Comment *C) {
  717.     return C->getCommentKind() == ParamCommandCommentKind;
  718.   }
  719.  
  720.   enum PassDirection {
  721.     In,
  722.     Out,
  723.     InOut
  724.   };
  725.  
  726.   static const char *getDirectionAsString(PassDirection D);
  727.  
  728.   PassDirection getDirection() const LLVM_READONLY {
  729.     return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
  730.   }
  731.  
  732.   bool isDirectionExplicit() const LLVM_READONLY {
  733.     return ParamCommandCommentBits.IsDirectionExplicit;
  734.   }
  735.  
  736.   void setDirection(PassDirection Direction, bool Explicit) {
  737.     ParamCommandCommentBits.Direction = Direction;
  738.     ParamCommandCommentBits.IsDirectionExplicit = Explicit;
  739.   }
  740.  
  741.   bool hasParamName() const {
  742.     return getNumArgs() > 0;
  743.   }
  744.  
  745.   StringRef getParamName(const FullComment *FC) const;
  746.  
  747.   StringRef getParamNameAsWritten() const {
  748.     return Args[0].Text;
  749.   }
  750.  
  751.   SourceRange getParamNameRange() const {
  752.     return Args[0].Range;
  753.   }
  754.  
  755.   bool isParamIndexValid() const LLVM_READONLY {
  756.     return ParamIndex != InvalidParamIndex;
  757.   }
  758.  
  759.   bool isVarArgParam() const LLVM_READONLY {
  760.     return ParamIndex == VarArgParamIndex;
  761.   }
  762.  
  763.   void setIsVarArgParam() {
  764.     ParamIndex = VarArgParamIndex;
  765.     assert(isParamIndexValid());
  766.   }
  767.  
  768.   unsigned getParamIndex() const LLVM_READONLY {
  769.     assert(isParamIndexValid());
  770.     assert(!isVarArgParam());
  771.     return ParamIndex;
  772.   }
  773.  
  774.   void setParamIndex(unsigned Index) {
  775.     ParamIndex = Index;
  776.     assert(isParamIndexValid());
  777.     assert(!isVarArgParam());
  778.   }
  779. };
  780.  
  781. /// Doxygen \\tparam command, describes a template parameter.
  782. class TParamCommandComment : public BlockCommandComment {
  783. private:
  784.   /// If this template parameter name was resolved (found in template parameter
  785.   /// list), then this stores a list of position indexes in all template
  786.   /// parameter lists.
  787.   ///
  788.   /// For example:
  789.   /// \verbatim
  790.   ///     template<typename C, template<typename T> class TT>
  791.   ///     void test(TT<int> aaa);
  792.   /// \endverbatim
  793.   /// For C:  Position = { 0 }
  794.   /// For TT: Position = { 1 }
  795.   /// For T:  Position = { 1, 0 }
  796.   ArrayRef<unsigned> Position;
  797.  
  798. public:
  799.   TParamCommandComment(SourceLocation LocBegin,
  800.                        SourceLocation LocEnd,
  801.                        unsigned CommandID,
  802.                        CommandMarkerKind CommandMarker) :
  803.       BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
  804.                           CommandMarker)
  805.   { }
  806.  
  807.   static bool classof(const Comment *C) {
  808.     return C->getCommentKind() == TParamCommandCommentKind;
  809.   }
  810.  
  811.   bool hasParamName() const {
  812.     return getNumArgs() > 0;
  813.   }
  814.  
  815.   StringRef getParamName(const FullComment *FC) const;
  816.  
  817.   StringRef getParamNameAsWritten() const {
  818.     return Args[0].Text;
  819.   }
  820.  
  821.   SourceRange getParamNameRange() const {
  822.     return Args[0].Range;
  823.   }
  824.  
  825.   bool isPositionValid() const LLVM_READONLY {
  826.     return !Position.empty();
  827.   }
  828.  
  829.   unsigned getDepth() const {
  830.     assert(isPositionValid());
  831.     return Position.size();
  832.   }
  833.  
  834.   unsigned getIndex(unsigned Depth) const {
  835.     assert(isPositionValid());
  836.     return Position[Depth];
  837.   }
  838.  
  839.   void setPosition(ArrayRef<unsigned> NewPosition) {
  840.     Position = NewPosition;
  841.     assert(isPositionValid());
  842.   }
  843. };
  844.  
  845. /// A line of text contained in a verbatim block.
  846. class VerbatimBlockLineComment : public Comment {
  847.   StringRef Text;
  848.  
  849. public:
  850.   VerbatimBlockLineComment(SourceLocation LocBegin,
  851.                            StringRef Text) :
  852.       Comment(VerbatimBlockLineCommentKind,
  853.               LocBegin,
  854.               LocBegin.getLocWithOffset(Text.size())),
  855.       Text(Text)
  856.   { }
  857.  
  858.   static bool classof(const Comment *C) {
  859.     return C->getCommentKind() == VerbatimBlockLineCommentKind;
  860.   }
  861.  
  862.   child_iterator child_begin() const { return nullptr; }
  863.  
  864.   child_iterator child_end() const { return nullptr; }
  865.  
  866.   StringRef getText() const LLVM_READONLY {
  867.     return Text;
  868.   }
  869. };
  870.  
  871. /// A verbatim block command (e. g., preformatted code).  Verbatim block has an
  872. /// opening and a closing command and contains multiple lines of text
  873. /// (VerbatimBlockLineComment nodes).
  874. class VerbatimBlockComment : public BlockCommandComment {
  875. protected:
  876.   StringRef CloseName;
  877.   SourceLocation CloseNameLocBegin;
  878.   ArrayRef<VerbatimBlockLineComment *> Lines;
  879.  
  880. public:
  881.   VerbatimBlockComment(SourceLocation LocBegin,
  882.                        SourceLocation LocEnd,
  883.                        unsigned CommandID) :
  884.       BlockCommandComment(VerbatimBlockCommentKind,
  885.                           LocBegin, LocEnd, CommandID,
  886.                           CMK_At) // FIXME: improve source fidelity.
  887.   { }
  888.  
  889.   static bool classof(const Comment *C) {
  890.     return C->getCommentKind() == VerbatimBlockCommentKind;
  891.   }
  892.  
  893.   child_iterator child_begin() const {
  894.     return reinterpret_cast<child_iterator>(Lines.begin());
  895.   }
  896.  
  897.   child_iterator child_end() const {
  898.     return reinterpret_cast<child_iterator>(Lines.end());
  899.   }
  900.  
  901.   void setCloseName(StringRef Name, SourceLocation LocBegin) {
  902.     CloseName = Name;
  903.     CloseNameLocBegin = LocBegin;
  904.   }
  905.  
  906.   void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
  907.     Lines = L;
  908.   }
  909.  
  910.   StringRef getCloseName() const {
  911.     return CloseName;
  912.   }
  913.  
  914.   unsigned getNumLines() const {
  915.     return Lines.size();
  916.   }
  917.  
  918.   StringRef getText(unsigned LineIdx) const {
  919.     return Lines[LineIdx]->getText();
  920.   }
  921. };
  922.  
  923. /// A verbatim line command.  Verbatim line has an opening command, a single
  924. /// line of text (up to the newline after the opening command) and has no
  925. /// closing command.
  926. class VerbatimLineComment : public BlockCommandComment {
  927. protected:
  928.   StringRef Text;
  929.   SourceLocation TextBegin;
  930.  
  931. public:
  932.   VerbatimLineComment(SourceLocation LocBegin,
  933.                       SourceLocation LocEnd,
  934.                       unsigned CommandID,
  935.                       SourceLocation TextBegin,
  936.                       StringRef Text) :
  937.       BlockCommandComment(VerbatimLineCommentKind,
  938.                           LocBegin, LocEnd,
  939.                           CommandID,
  940.                           CMK_At), // FIXME: improve source fidelity.
  941.       Text(Text),
  942.       TextBegin(TextBegin)
  943.   { }
  944.  
  945.   static bool classof(const Comment *C) {
  946.     return C->getCommentKind() == VerbatimLineCommentKind;
  947.   }
  948.  
  949.   child_iterator child_begin() const { return nullptr; }
  950.  
  951.   child_iterator child_end() const { return nullptr; }
  952.  
  953.   StringRef getText() const {
  954.     return Text;
  955.   }
  956.  
  957.   SourceRange getTextRange() const {
  958.     return SourceRange(TextBegin, getEndLoc());
  959.   }
  960. };
  961.  
  962. /// Information about the declaration, useful to clients of FullComment.
  963. struct DeclInfo {
  964.   /// Declaration the comment is actually attached to (in the source).
  965.   /// Should not be NULL.
  966.   const Decl *CommentDecl;
  967.  
  968.   /// CurrentDecl is the declaration with which the FullComment is associated.
  969.   ///
  970.   /// It can be different from \c CommentDecl.  It happens when we decide
  971.   /// that the comment originally attached to \c CommentDecl is fine for
  972.   /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
  973.   /// \c CommentDecl).
  974.   ///
  975.   /// The information in the DeclInfo corresponds to CurrentDecl.
  976.   const Decl *CurrentDecl;
  977.  
  978.   /// Parameters that can be referenced by \\param if \c CommentDecl is something
  979.   /// that we consider a "function".
  980.   ArrayRef<const ParmVarDecl *> ParamVars;
  981.  
  982.   /// Function return type if \c CommentDecl is something that we consider
  983.   /// a "function".
  984.   QualType ReturnType;
  985.  
  986.   /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
  987.   /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
  988.   /// true).
  989.   const TemplateParameterList *TemplateParameters;
  990.  
  991.   /// A simplified description of \c CommentDecl kind that should be good enough
  992.   /// for documentation rendering purposes.
  993.   enum DeclKind {
  994.     /// Everything else not explicitly mentioned below.
  995.     OtherKind,
  996.  
  997.     /// Something that we consider a "function":
  998.     /// \li function,
  999.     /// \li function template,
  1000.     /// \li function template specialization,
  1001.     /// \li member function,
  1002.     /// \li member function template,
  1003.     /// \li member function template specialization,
  1004.     /// \li ObjC method,
  1005.     FunctionKind,
  1006.  
  1007.     /// Something that we consider a "class":
  1008.     /// \li class/struct,
  1009.     /// \li class template,
  1010.     /// \li class template (partial) specialization.
  1011.     ClassKind,
  1012.  
  1013.     /// Something that we consider a "variable":
  1014.     /// \li namespace scope variables and variable templates;
  1015.     /// \li static and non-static class data members and member templates;
  1016.     /// \li enumerators.
  1017.     VariableKind,
  1018.  
  1019.     /// A C++ namespace.
  1020.     NamespaceKind,
  1021.  
  1022.     /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
  1023.     /// see \c TypedefNameDecl.
  1024.     TypedefKind,
  1025.  
  1026.     /// An enumeration or scoped enumeration.
  1027.     EnumKind
  1028.   };
  1029.  
  1030.   /// What kind of template specialization \c CommentDecl is.
  1031.   enum TemplateDeclKind {
  1032.     NotTemplate,
  1033.     Template,
  1034.     TemplateSpecialization,
  1035.     TemplatePartialSpecialization
  1036.   };
  1037.  
  1038.   /// If false, only \c CommentDecl is valid.
  1039.   unsigned IsFilled : 1;
  1040.  
  1041.   /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
  1042.   unsigned Kind : 3;
  1043.  
  1044.   /// Is \c CommentDecl a template declaration.
  1045.   unsigned TemplateKind : 2;
  1046.  
  1047.   /// Is \c CommentDecl an ObjCMethodDecl.
  1048.   unsigned IsObjCMethod : 1;
  1049.  
  1050.   /// Is \c CommentDecl a non-static member function of C++ class or
  1051.   /// instance method of ObjC class.
  1052.   /// Can be true only if \c IsFunctionDecl is true.
  1053.   unsigned IsInstanceMethod : 1;
  1054.  
  1055.   /// Is \c CommentDecl a static member function of C++ class or
  1056.   /// class method of ObjC class.
  1057.   /// Can be true only if \c IsFunctionDecl is true.
  1058.   unsigned IsClassMethod : 1;
  1059.  
  1060.   /// Is \c CommentDecl something we consider a "function" that's variadic.
  1061.   unsigned IsVariadic : 1;
  1062.  
  1063.   void fill();
  1064.  
  1065.   DeclKind getKind() const LLVM_READONLY {
  1066.     return static_cast<DeclKind>(Kind);
  1067.   }
  1068.  
  1069.   TemplateDeclKind getTemplateKind() const LLVM_READONLY {
  1070.     return static_cast<TemplateDeclKind>(TemplateKind);
  1071.   }
  1072.  
  1073.   bool involvesFunctionType() const { return !ReturnType.isNull(); }
  1074. };
  1075.  
  1076. /// A full comment attached to a declaration, contains block content.
  1077. class FullComment : public Comment {
  1078.   ArrayRef<BlockContentComment *> Blocks;
  1079.   DeclInfo *ThisDeclInfo;
  1080.  
  1081. public:
  1082.   FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
  1083.       Comment(FullCommentKind, SourceLocation(), SourceLocation()),
  1084.       Blocks(Blocks), ThisDeclInfo(D) {
  1085.     if (Blocks.empty())
  1086.       return;
  1087.  
  1088.     setSourceRange(
  1089.         SourceRange(Blocks.front()->getBeginLoc(), Blocks.back()->getEndLoc()));
  1090.     setLocation(Blocks.front()->getBeginLoc());
  1091.   }
  1092.  
  1093.   static bool classof(const Comment *C) {
  1094.     return C->getCommentKind() == FullCommentKind;
  1095.   }
  1096.  
  1097.   child_iterator child_begin() const {
  1098.     return reinterpret_cast<child_iterator>(Blocks.begin());
  1099.   }
  1100.  
  1101.   child_iterator child_end() const {
  1102.     return reinterpret_cast<child_iterator>(Blocks.end());
  1103.   }
  1104.  
  1105.   const Decl *getDecl() const LLVM_READONLY {
  1106.     return ThisDeclInfo->CommentDecl;
  1107.   }
  1108.  
  1109.   const DeclInfo *getDeclInfo() const LLVM_READONLY {
  1110.     if (!ThisDeclInfo->IsFilled)
  1111.       ThisDeclInfo->fill();
  1112.     return ThisDeclInfo;
  1113.   }
  1114.  
  1115.   ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
  1116.  
  1117. };
  1118. } // end namespace comments
  1119. } // end namespace clang
  1120.  
  1121. #endif
  1122.  
  1123.