Clang Project

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