1 //===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines comment AST nodes.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_COMMENT_H
14 #define LLVM_CLANG_AST_COMMENT_H
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"
26 class TemplateParameterList;
31 /// Describes the syntax that was used in a documentation command.
33 /// Exact values of this enumeration are important because they used to select
34 /// parts of diagnostic messages. Audit diagnostics before changing or adding
36 enum CommandMarkerKind {
37 /// Command started with a backslash character:
43 /// Command started with an 'at' character:
50 /// Any part of the comment.
54 /// Preferred location to show caret.
57 /// Source range of this AST node.
60 class CommentBitfields {
63 /// Type of this AST node.
66 enum { NumCommentBits = 8 };
68 class InlineContentCommentBitfields {
69 friend class InlineContentComment;
71 unsigned : NumCommentBits;
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;
77 enum { NumInlineContentCommentBits = NumCommentBits + 1 };
79 class TextCommentBitfields {
80 friend class TextComment;
82 unsigned : NumInlineContentCommentBits;
84 /// True if \c IsWhitespace field contains a valid value.
85 mutable unsigned IsWhitespaceValid : 1;
87 /// True if this comment AST node contains only whitespace.
88 mutable unsigned IsWhitespace : 1;
90 enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
92 class InlineCommandCommentBitfields {
93 friend class InlineCommandComment;
95 unsigned : NumInlineContentCommentBits;
97 unsigned RenderKind : 3;
99 unsigned CommandID : CommandInfo::NumCommandIDBits;
101 enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 3 +
102 CommandInfo::NumCommandIDBits };
104 class HTMLTagCommentBitfields {
105 friend class HTMLTagComment;
107 unsigned : NumInlineContentCommentBits;
109 /// True if we found that this tag is malformed in some way.
110 unsigned IsMalformed : 1;
112 enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };
114 class HTMLStartTagCommentBitfields {
115 friend class HTMLStartTagComment;
117 unsigned : NumHTMLTagCommentBits;
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;
123 enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
125 class ParagraphCommentBitfields {
126 friend class ParagraphComment;
128 unsigned : NumCommentBits;
130 /// True if \c IsWhitespace field contains a valid value.
131 mutable unsigned IsWhitespaceValid : 1;
133 /// True if this comment AST node contains only whitespace.
134 mutable unsigned IsWhitespace : 1;
136 enum { NumParagraphCommentBits = NumCommentBits + 2 };
138 class BlockCommandCommentBitfields {
139 friend class BlockCommandComment;
141 unsigned : NumCommentBits;
143 unsigned CommandID : CommandInfo::NumCommandIDBits;
145 /// Describes the syntax that was used in a documentation command.
146 /// Contains values from CommandMarkerKind enum.
147 unsigned CommandMarker : 1;
149 enum { NumBlockCommandCommentBits = NumCommentBits +
150 CommandInfo::NumCommandIDBits + 1 };
152 class ParamCommandCommentBitfields {
153 friend class ParamCommandComment;
155 unsigned : NumBlockCommandCommentBits;
157 /// Parameter passing direction, see ParamCommandComment::PassDirection.
158 unsigned Direction : 2;
160 /// True if direction was specified explicitly in the comment.
161 unsigned IsDirectionExplicit : 1;
163 enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
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;
177 void setSourceRange(SourceRange SR) {
181 void setLocation(SourceLocation L) {
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"
197 Comment(CommentKind K,
198 SourceLocation LocBegin,
199 SourceLocation LocEnd) :
200 Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
201 CommentBits.Kind = K;
204 CommentKind getCommentKind() const {
205 return static_cast<CommentKind>(CommentBits.Kind);
208 const char *getCommentKindName() const;
211 void dumpColor() const;
212 void dump(const ASTContext &Context) const;
213 void dump(raw_ostream &OS, const CommandTraits *Traits,
214 const SourceManager *SM) const;
216 SourceRange getSourceRange() const LLVM_READONLY { return Range; }
218 SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
220 SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
222 SourceLocation getLocation() const LLVM_READONLY { return Loc; }
224 typedef Comment * const *child_iterator;
226 child_iterator child_begin() const;
227 child_iterator child_end() const;
229 // TODO: const child iterator
231 unsigned child_count() const {
232 return child_end() - child_begin();
236 /// Inline content (contained within a block).
238 class InlineContentComment : public Comment {
240 InlineContentComment(CommentKind K,
241 SourceLocation LocBegin,
242 SourceLocation LocEnd) :
243 Comment(K, LocBegin, LocEnd) {
244 InlineContentCommentBits.HasTrailingNewline = 0;
248 static bool classof(const Comment *C) {
249 return C->getCommentKind() >= FirstInlineContentCommentConstant &&
250 C->getCommentKind() <= LastInlineContentCommentConstant;
253 void addTrailingNewline() {
254 InlineContentCommentBits.HasTrailingNewline = 1;
257 bool hasTrailingNewline() const {
258 return InlineContentCommentBits.HasTrailingNewline;
263 class TextComment : public InlineContentComment {
267 TextComment(SourceLocation LocBegin,
268 SourceLocation LocEnd,
270 InlineContentComment(TextCommentKind, LocBegin, LocEnd),
272 TextCommentBits.IsWhitespaceValid = false;
275 static bool classof(const Comment *C) {
276 return C->getCommentKind() == TextCommentKind;
279 child_iterator child_begin() const { return nullptr; }
281 child_iterator child_end() const { return nullptr; }
283 StringRef getText() const LLVM_READONLY { return Text; }
285 bool isWhitespace() const {
286 if (TextCommentBits.IsWhitespaceValid)
287 return TextCommentBits.IsWhitespace;
289 TextCommentBits.IsWhitespace = isWhitespaceNoCache();
290 TextCommentBits.IsWhitespaceValid = true;
291 return TextCommentBits.IsWhitespace;
295 bool isWhitespaceNoCache() const;
298 /// A command with word-like arguments that is considered inline content.
299 class InlineCommandComment : public InlineContentComment {
305 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
308 /// The most appropriate rendering mode for this command, chosen on command
309 /// semantics in Doxygen.
319 /// Command arguments.
320 ArrayRef<Argument> Args;
323 InlineCommandComment(SourceLocation LocBegin,
324 SourceLocation LocEnd,
327 ArrayRef<Argument> Args) :
328 InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
330 InlineCommandCommentBits.RenderKind = RK;
331 InlineCommandCommentBits.CommandID = CommandID;
334 static bool classof(const Comment *C) {
335 return C->getCommentKind() == InlineCommandCommentKind;
338 child_iterator child_begin() const { return nullptr; }
340 child_iterator child_end() const { return nullptr; }
342 unsigned getCommandID() const {
343 return InlineCommandCommentBits.CommandID;
346 StringRef getCommandName(const CommandTraits &Traits) const {
347 return Traits.getCommandInfo(getCommandID())->Name;
350 SourceRange getCommandNameRange() const {
351 return SourceRange(getBeginLoc().getLocWithOffset(-1), getEndLoc());
354 RenderKind getRenderKind() const {
355 return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
358 unsigned getNumArgs() const {
362 StringRef getArgText(unsigned Idx) const {
363 return Args[Idx].Text;
366 SourceRange getArgRange(unsigned Idx) const {
367 return Args[Idx].Range;
371 /// Abstract class for opening and closing HTML tags. HTML tags are always
372 /// treated as inline content (regardless HTML semantics).
373 class HTMLTagComment : public InlineContentComment {
376 SourceRange TagNameRange;
378 HTMLTagComment(CommentKind K,
379 SourceLocation LocBegin,
380 SourceLocation LocEnd,
382 SourceLocation TagNameBegin,
383 SourceLocation TagNameEnd) :
384 InlineContentComment(K, LocBegin, LocEnd),
386 TagNameRange(TagNameBegin, TagNameEnd) {
387 setLocation(TagNameBegin);
388 HTMLTagCommentBits.IsMalformed = 0;
392 static bool classof(const Comment *C) {
393 return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
394 C->getCommentKind() <= LastHTMLTagCommentConstant;
397 StringRef getTagName() const LLVM_READONLY { return TagName; }
399 SourceRange getTagNameSourceRange() const LLVM_READONLY {
400 SourceLocation L = getLocation();
401 return SourceRange(L.getLocWithOffset(1),
402 L.getLocWithOffset(1 + TagName.size()));
405 bool isMalformed() const {
406 return HTMLTagCommentBits.IsMalformed;
409 void setIsMalformed() {
410 HTMLTagCommentBits.IsMalformed = 1;
414 /// An opening HTML tag with attributes.
415 class HTMLStartTagComment : public HTMLTagComment {
419 SourceLocation NameLocBegin;
422 SourceLocation EqualsLoc;
424 SourceRange ValueRange;
429 Attribute(SourceLocation NameLocBegin, StringRef Name) :
430 NameLocBegin(NameLocBegin), Name(Name),
431 EqualsLoc(SourceLocation()),
432 ValueRange(SourceRange()), Value(StringRef())
435 Attribute(SourceLocation NameLocBegin, StringRef Name,
436 SourceLocation EqualsLoc,
437 SourceRange ValueRange, StringRef Value) :
438 NameLocBegin(NameLocBegin), Name(Name),
439 EqualsLoc(EqualsLoc),
440 ValueRange(ValueRange), Value(Value)
443 SourceLocation getNameLocEnd() const {
444 return NameLocBegin.getLocWithOffset(Name.size());
447 SourceRange getNameRange() const {
448 return SourceRange(NameLocBegin, getNameLocEnd());
453 ArrayRef<Attribute> Attributes;
456 HTMLStartTagComment(SourceLocation LocBegin,
458 HTMLTagComment(HTMLStartTagCommentKind,
459 LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
461 LocBegin.getLocWithOffset(1),
462 LocBegin.getLocWithOffset(1 + TagName.size())) {
463 HTMLStartTagCommentBits.IsSelfClosing = false;
466 static bool classof(const Comment *C) {
467 return C->getCommentKind() == HTMLStartTagCommentKind;
470 child_iterator child_begin() const { return nullptr; }
472 child_iterator child_end() const { return nullptr; }
474 unsigned getNumAttrs() const {
475 return Attributes.size();
478 const Attribute &getAttr(unsigned Idx) const {
479 return Attributes[Idx];
482 void setAttrs(ArrayRef<Attribute> Attrs) {
484 if (!Attrs.empty()) {
485 const Attribute &Attr = Attrs.back();
486 SourceLocation L = Attr.ValueRange.getEnd();
490 Range.setEnd(Attr.getNameLocEnd());
495 void setGreaterLoc(SourceLocation GreaterLoc) {
496 Range.setEnd(GreaterLoc);
499 bool isSelfClosing() const {
500 return HTMLStartTagCommentBits.IsSelfClosing;
503 void setSelfClosing() {
504 HTMLStartTagCommentBits.IsSelfClosing = true;
508 /// A closing HTML tag.
509 class HTMLEndTagComment : public HTMLTagComment {
511 HTMLEndTagComment(SourceLocation LocBegin,
512 SourceLocation LocEnd,
514 HTMLTagComment(HTMLEndTagCommentKind,
517 LocBegin.getLocWithOffset(2),
518 LocBegin.getLocWithOffset(2 + TagName.size()))
521 static bool classof(const Comment *C) {
522 return C->getCommentKind() == HTMLEndTagCommentKind;
525 child_iterator child_begin() const { return nullptr; }
527 child_iterator child_end() const { return nullptr; }
530 /// Block content (contains inline content).
532 class BlockContentComment : public Comment {
534 BlockContentComment(CommentKind K,
535 SourceLocation LocBegin,
536 SourceLocation LocEnd) :
537 Comment(K, LocBegin, LocEnd)
541 static bool classof(const Comment *C) {
542 return C->getCommentKind() >= FirstBlockContentCommentConstant &&
543 C->getCommentKind() <= LastBlockContentCommentConstant;
547 /// A single paragraph that contains inline content.
548 class ParagraphComment : public BlockContentComment {
549 ArrayRef<InlineContentComment *> Content;
552 ParagraphComment(ArrayRef<InlineContentComment *> Content) :
553 BlockContentComment(ParagraphCommentKind,
557 if (Content.empty()) {
558 ParagraphCommentBits.IsWhitespace = true;
559 ParagraphCommentBits.IsWhitespaceValid = true;
563 ParagraphCommentBits.IsWhitespaceValid = false;
565 setSourceRange(SourceRange(Content.front()->getBeginLoc(),
566 Content.back()->getEndLoc()));
567 setLocation(Content.front()->getBeginLoc());
570 static bool classof(const Comment *C) {
571 return C->getCommentKind() == ParagraphCommentKind;
574 child_iterator child_begin() const {
575 return reinterpret_cast<child_iterator>(Content.begin());
578 child_iterator child_end() const {
579 return reinterpret_cast<child_iterator>(Content.end());
582 bool isWhitespace() const {
583 if (ParagraphCommentBits.IsWhitespaceValid)
584 return ParagraphCommentBits.IsWhitespace;
586 ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
587 ParagraphCommentBits.IsWhitespaceValid = true;
588 return ParagraphCommentBits.IsWhitespace;
592 bool isWhitespaceNoCache() const;
595 /// A command that has zero or more word-like arguments (number of word-like
596 /// arguments depends on command name) and a paragraph as an argument
597 /// (e. g., \\brief).
598 class BlockCommandComment : public BlockContentComment {
605 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
609 /// Word-like arguments.
610 ArrayRef<Argument> Args;
612 /// Paragraph argument.
613 ParagraphComment *Paragraph;
615 BlockCommandComment(CommentKind K,
616 SourceLocation LocBegin,
617 SourceLocation LocEnd,
619 CommandMarkerKind CommandMarker) :
620 BlockContentComment(K, LocBegin, LocEnd),
622 setLocation(getCommandNameBeginLoc());
623 BlockCommandCommentBits.CommandID = CommandID;
624 BlockCommandCommentBits.CommandMarker = CommandMarker;
628 BlockCommandComment(SourceLocation LocBegin,
629 SourceLocation LocEnd,
631 CommandMarkerKind CommandMarker) :
632 BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
634 setLocation(getCommandNameBeginLoc());
635 BlockCommandCommentBits.CommandID = CommandID;
636 BlockCommandCommentBits.CommandMarker = CommandMarker;
639 static bool classof(const Comment *C) {
640 return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
641 C->getCommentKind() <= LastBlockCommandCommentConstant;
644 child_iterator child_begin() const {
645 return reinterpret_cast<child_iterator>(&Paragraph);
648 child_iterator child_end() const {
649 return reinterpret_cast<child_iterator>(&Paragraph + 1);
652 unsigned getCommandID() const {
653 return BlockCommandCommentBits.CommandID;
656 StringRef getCommandName(const CommandTraits &Traits) const {
657 return Traits.getCommandInfo(getCommandID())->Name;
660 SourceLocation getCommandNameBeginLoc() const {
661 return getBeginLoc().getLocWithOffset(1);
664 SourceRange getCommandNameRange(const CommandTraits &Traits) const {
665 StringRef Name = getCommandName(Traits);
666 return SourceRange(getCommandNameBeginLoc(),
667 getBeginLoc().getLocWithOffset(1 + Name.size()));
670 unsigned getNumArgs() const {
674 StringRef getArgText(unsigned Idx) const {
675 return Args[Idx].Text;
678 SourceRange getArgRange(unsigned Idx) const {
679 return Args[Idx].Range;
682 void setArgs(ArrayRef<Argument> A) {
684 if (Args.size() > 0) {
685 SourceLocation NewLocEnd = Args.back().Range.getEnd();
686 if (NewLocEnd.isValid())
687 setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
691 ParagraphComment *getParagraph() const LLVM_READONLY {
695 bool hasNonWhitespaceParagraph() const {
696 return Paragraph && !Paragraph->isWhitespace();
699 void setParagraph(ParagraphComment *PC) {
701 SourceLocation NewLocEnd = PC->getEndLoc();
702 if (NewLocEnd.isValid())
703 setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
706 CommandMarkerKind getCommandMarker() const LLVM_READONLY {
707 return static_cast<CommandMarkerKind>(
708 BlockCommandCommentBits.CommandMarker);
712 /// Doxygen \\param command.
713 class ParamCommandComment : public BlockCommandComment {
715 /// Parameter index in the function declaration.
720 InvalidParamIndex = ~0U,
721 VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
724 ParamCommandComment(SourceLocation LocBegin,
725 SourceLocation LocEnd,
727 CommandMarkerKind CommandMarker) :
728 BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
729 CommandID, CommandMarker),
730 ParamIndex(InvalidParamIndex) {
731 ParamCommandCommentBits.Direction = In;
732 ParamCommandCommentBits.IsDirectionExplicit = false;
735 static bool classof(const Comment *C) {
736 return C->getCommentKind() == ParamCommandCommentKind;
745 static const char *getDirectionAsString(PassDirection D);
747 PassDirection getDirection() const LLVM_READONLY {
748 return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
751 bool isDirectionExplicit() const LLVM_READONLY {
752 return ParamCommandCommentBits.IsDirectionExplicit;
755 void setDirection(PassDirection Direction, bool Explicit) {
756 ParamCommandCommentBits.Direction = Direction;
757 ParamCommandCommentBits.IsDirectionExplicit = Explicit;
760 bool hasParamName() const {
761 return getNumArgs() > 0;
764 StringRef getParamName(const FullComment *FC) const;
766 StringRef getParamNameAsWritten() const {
770 SourceRange getParamNameRange() const {
771 return Args[0].Range;
774 bool isParamIndexValid() const LLVM_READONLY {
775 return ParamIndex != InvalidParamIndex;
778 bool isVarArgParam() const LLVM_READONLY {
779 return ParamIndex == VarArgParamIndex;
782 void setIsVarArgParam() {
783 ParamIndex = VarArgParamIndex;
784 assert(isParamIndexValid());
787 unsigned getParamIndex() const LLVM_READONLY {
788 assert(isParamIndexValid());
789 assert(!isVarArgParam());
793 void setParamIndex(unsigned Index) {
795 assert(isParamIndexValid());
796 assert(!isVarArgParam());
800 /// Doxygen \\tparam command, describes a template parameter.
801 class TParamCommandComment : public BlockCommandComment {
803 /// If this template parameter name was resolved (found in template parameter
804 /// list), then this stores a list of position indexes in all template
809 /// template<typename C, template<typename T> class TT>
810 /// void test(TT<int> aaa);
812 /// For C: Position = { 0 }
813 /// For TT: Position = { 1 }
814 /// For T: Position = { 1, 0 }
815 ArrayRef<unsigned> Position;
818 TParamCommandComment(SourceLocation LocBegin,
819 SourceLocation LocEnd,
821 CommandMarkerKind CommandMarker) :
822 BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
826 static bool classof(const Comment *C) {
827 return C->getCommentKind() == TParamCommandCommentKind;
830 bool hasParamName() const {
831 return getNumArgs() > 0;
834 StringRef getParamName(const FullComment *FC) const;
836 StringRef getParamNameAsWritten() const {
840 SourceRange getParamNameRange() const {
841 return Args[0].Range;
844 bool isPositionValid() const LLVM_READONLY {
845 return !Position.empty();
848 unsigned getDepth() const {
849 assert(isPositionValid());
850 return Position.size();
853 unsigned getIndex(unsigned Depth) const {
854 assert(isPositionValid());
855 return Position[Depth];
858 void setPosition(ArrayRef<unsigned> NewPosition) {
859 Position = NewPosition;
860 assert(isPositionValid());
864 /// A line of text contained in a verbatim block.
865 class VerbatimBlockLineComment : public Comment {
869 VerbatimBlockLineComment(SourceLocation LocBegin,
871 Comment(VerbatimBlockLineCommentKind,
873 LocBegin.getLocWithOffset(Text.size())),
877 static bool classof(const Comment *C) {
878 return C->getCommentKind() == VerbatimBlockLineCommentKind;
881 child_iterator child_begin() const { return nullptr; }
883 child_iterator child_end() const { return nullptr; }
885 StringRef getText() const LLVM_READONLY {
890 /// A verbatim block command (e. g., preformatted code). Verbatim block has an
891 /// opening and a closing command and contains multiple lines of text
892 /// (VerbatimBlockLineComment nodes).
893 class VerbatimBlockComment : public BlockCommandComment {
896 SourceLocation CloseNameLocBegin;
897 ArrayRef<VerbatimBlockLineComment *> Lines;
900 VerbatimBlockComment(SourceLocation LocBegin,
901 SourceLocation LocEnd,
902 unsigned CommandID) :
903 BlockCommandComment(VerbatimBlockCommentKind,
904 LocBegin, LocEnd, CommandID,
905 CMK_At) // FIXME: improve source fidelity.
908 static bool classof(const Comment *C) {
909 return C->getCommentKind() == VerbatimBlockCommentKind;
912 child_iterator child_begin() const {
913 return reinterpret_cast<child_iterator>(Lines.begin());
916 child_iterator child_end() const {
917 return reinterpret_cast<child_iterator>(Lines.end());
920 void setCloseName(StringRef Name, SourceLocation LocBegin) {
922 CloseNameLocBegin = LocBegin;
925 void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
929 StringRef getCloseName() const {
933 unsigned getNumLines() const {
937 StringRef getText(unsigned LineIdx) const {
938 return Lines[LineIdx]->getText();
942 /// A verbatim line command. Verbatim line has an opening command, a single
943 /// line of text (up to the newline after the opening command) and has no
945 class VerbatimLineComment : public BlockCommandComment {
948 SourceLocation TextBegin;
951 VerbatimLineComment(SourceLocation LocBegin,
952 SourceLocation LocEnd,
954 SourceLocation TextBegin,
956 BlockCommandComment(VerbatimLineCommentKind,
959 CMK_At), // FIXME: improve source fidelity.
964 static bool classof(const Comment *C) {
965 return C->getCommentKind() == VerbatimLineCommentKind;
968 child_iterator child_begin() const { return nullptr; }
970 child_iterator child_end() const { return nullptr; }
972 StringRef getText() const {
976 SourceRange getTextRange() const {
977 return SourceRange(TextBegin, getEndLoc());
981 /// Information about the declaration, useful to clients of FullComment.
983 /// Declaration the comment is actually attached to (in the source).
984 /// Should not be NULL.
985 const Decl *CommentDecl;
987 /// CurrentDecl is the declaration with which the FullComment is associated.
989 /// It can be different from \c CommentDecl. It happens when we decide
990 /// that the comment originally attached to \c CommentDecl is fine for
991 /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
994 /// The information in the DeclInfo corresponds to CurrentDecl.
995 const Decl *CurrentDecl;
997 /// Parameters that can be referenced by \\param if \c CommentDecl is something
998 /// that we consider a "function".
999 ArrayRef<const ParmVarDecl *> ParamVars;
1001 /// Function return type if \c CommentDecl is something that we consider
1003 QualType ReturnType;
1005 /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
1006 /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
1008 const TemplateParameterList *TemplateParameters;
1010 /// A simplified description of \c CommentDecl kind that should be good enough
1011 /// for documentation rendering purposes.
1013 /// Everything else not explicitly mentioned below.
1016 /// Something that we consider a "function":
1018 /// \li function template,
1019 /// \li function template specialization,
1020 /// \li member function,
1021 /// \li member function template,
1022 /// \li member function template specialization,
1023 /// \li ObjC method,
1024 /// \li a typedef for a function pointer, member function pointer,
1028 /// Something that we consider a "class":
1029 /// \li class/struct,
1030 /// \li class template,
1031 /// \li class template (partial) specialization.
1034 /// Something that we consider a "variable":
1035 /// \li namespace scope variables;
1036 /// \li static and non-static class data members;
1037 /// \li enumerators.
1040 /// A C++ namespace.
1043 /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
1044 /// see \c TypedefNameDecl.
1047 /// An enumeration or scoped enumeration.
1051 /// What kind of template specialization \c CommentDecl is.
1052 enum TemplateDeclKind {
1055 TemplateSpecialization,
1056 TemplatePartialSpecialization
1059 /// If false, only \c CommentDecl is valid.
1060 unsigned IsFilled : 1;
1062 /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
1065 /// Is \c CommentDecl a template declaration.
1066 unsigned TemplateKind : 2;
1068 /// Is \c CommentDecl an ObjCMethodDecl.
1069 unsigned IsObjCMethod : 1;
1071 /// Is \c CommentDecl a non-static member function of C++ class or
1072 /// instance method of ObjC class.
1073 /// Can be true only if \c IsFunctionDecl is true.
1074 unsigned IsInstanceMethod : 1;
1076 /// Is \c CommentDecl a static member function of C++ class or
1077 /// class method of ObjC class.
1078 /// Can be true only if \c IsFunctionDecl is true.
1079 unsigned IsClassMethod : 1;
1083 DeclKind getKind() const LLVM_READONLY {
1084 return static_cast<DeclKind>(Kind);
1087 TemplateDeclKind getTemplateKind() const LLVM_READONLY {
1088 return static_cast<TemplateDeclKind>(TemplateKind);
1092 /// A full comment attached to a declaration, contains block content.
1093 class FullComment : public Comment {
1094 ArrayRef<BlockContentComment *> Blocks;
1095 DeclInfo *ThisDeclInfo;
1098 FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
1099 Comment(FullCommentKind, SourceLocation(), SourceLocation()),
1100 Blocks(Blocks), ThisDeclInfo(D) {
1105 SourceRange(Blocks.front()->getBeginLoc(), Blocks.back()->getEndLoc()));
1106 setLocation(Blocks.front()->getBeginLoc());
1109 static bool classof(const Comment *C) {
1110 return C->getCommentKind() == FullCommentKind;
1113 child_iterator child_begin() const {
1114 return reinterpret_cast<child_iterator>(Blocks.begin());
1117 child_iterator child_end() const {
1118 return reinterpret_cast<child_iterator>(Blocks.end());
1121 const Decl *getDecl() const LLVM_READONLY {
1122 return ThisDeclInfo->CommentDecl;
1125 const DeclInfo *getDeclInfo() const LLVM_READONLY {
1126 if (!ThisDeclInfo->IsFilled)
1127 ThisDeclInfo->fill();
1128 return ThisDeclInfo;
1131 ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
1134 } // end namespace comments
1135 } // end namespace clang