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 : 2;
98 unsigned CommandID : CommandInfo::NumCommandIDBits;
100 enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
101 CommandInfo::NumCommandIDBits };
103 class HTMLTagCommentBitfields {
104 friend class HTMLTagComment;
106 unsigned : NumInlineContentCommentBits;
108 /// True if we found that this tag is malformed in some way.
109 unsigned IsMalformed : 1;
111 enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };
113 class HTMLStartTagCommentBitfields {
114 friend class HTMLStartTagComment;
116 unsigned : NumHTMLTagCommentBits;
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;
122 enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
124 class ParagraphCommentBitfields {
125 friend class ParagraphComment;
127 unsigned : NumCommentBits;
129 /// True if \c IsWhitespace field contains a valid value.
130 mutable unsigned IsWhitespaceValid : 1;
132 /// True if this comment AST node contains only whitespace.
133 mutable unsigned IsWhitespace : 1;
135 enum { NumParagraphCommentBits = NumCommentBits + 2 };
137 class BlockCommandCommentBitfields {
138 friend class BlockCommandComment;
140 unsigned : NumCommentBits;
142 unsigned CommandID : CommandInfo::NumCommandIDBits;
144 /// Describes the syntax that was used in a documentation command.
145 /// Contains values from CommandMarkerKind enum.
146 unsigned CommandMarker : 1;
148 enum { NumBlockCommandCommentBits = NumCommentBits +
149 CommandInfo::NumCommandIDBits + 1 };
151 class ParamCommandCommentBitfields {
152 friend class ParamCommandComment;
154 unsigned : NumBlockCommandCommentBits;
156 /// Parameter passing direction, see ParamCommandComment::PassDirection.
157 unsigned Direction : 2;
159 /// True if direction was specified explicitly in the comment.
160 unsigned IsDirectionExplicit : 1;
162 enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
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;
176 void setSourceRange(SourceRange SR) {
180 void setLocation(SourceLocation L) {
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"
196 Comment(CommentKind K,
197 SourceLocation LocBegin,
198 SourceLocation LocEnd) :
199 Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
200 CommentBits.Kind = K;
203 CommentKind getCommentKind() const {
204 return static_cast<CommentKind>(CommentBits.Kind);
207 const char *getCommentKindName() const;
210 void dumpColor() const;
211 void dump(const ASTContext &Context) const;
212 void dump(raw_ostream &OS, const CommandTraits *Traits,
213 const SourceManager *SM) const;
215 SourceRange getSourceRange() const LLVM_READONLY { return Range; }
217 SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
219 SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
221 SourceLocation getLocation() const LLVM_READONLY { return Loc; }
223 typedef Comment * const *child_iterator;
225 child_iterator child_begin() const;
226 child_iterator child_end() const;
228 // TODO: const child iterator
230 unsigned child_count() const {
231 return child_end() - child_begin();
235 /// Inline content (contained within a block).
237 class InlineContentComment : public Comment {
239 InlineContentComment(CommentKind K,
240 SourceLocation LocBegin,
241 SourceLocation LocEnd) :
242 Comment(K, LocBegin, LocEnd) {
243 InlineContentCommentBits.HasTrailingNewline = 0;
247 static bool classof(const Comment *C) {
248 return C->getCommentKind() >= FirstInlineContentCommentConstant &&
249 C->getCommentKind() <= LastInlineContentCommentConstant;
252 void addTrailingNewline() {
253 InlineContentCommentBits.HasTrailingNewline = 1;
256 bool hasTrailingNewline() const {
257 return InlineContentCommentBits.HasTrailingNewline;
262 class TextComment : public InlineContentComment {
266 TextComment(SourceLocation LocBegin,
267 SourceLocation LocEnd,
269 InlineContentComment(TextCommentKind, LocBegin, LocEnd),
271 TextCommentBits.IsWhitespaceValid = false;
274 static bool classof(const Comment *C) {
275 return C->getCommentKind() == TextCommentKind;
278 child_iterator child_begin() const { return nullptr; }
280 child_iterator child_end() const { return nullptr; }
282 StringRef getText() const LLVM_READONLY { return Text; }
284 bool isWhitespace() const {
285 if (TextCommentBits.IsWhitespaceValid)
286 return TextCommentBits.IsWhitespace;
288 TextCommentBits.IsWhitespace = isWhitespaceNoCache();
289 TextCommentBits.IsWhitespaceValid = true;
290 return TextCommentBits.IsWhitespace;
294 bool isWhitespaceNoCache() const;
297 /// A command with word-like arguments that is considered inline content.
298 class InlineCommandComment : public InlineContentComment {
304 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
307 /// The most appropriate rendering mode for this command, chosen on command
308 /// semantics in Doxygen.
317 /// Command arguments.
318 ArrayRef<Argument> Args;
321 InlineCommandComment(SourceLocation LocBegin,
322 SourceLocation LocEnd,
325 ArrayRef<Argument> Args) :
326 InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
328 InlineCommandCommentBits.RenderKind = RK;
329 InlineCommandCommentBits.CommandID = CommandID;
332 static bool classof(const Comment *C) {
333 return C->getCommentKind() == InlineCommandCommentKind;
336 child_iterator child_begin() const { return nullptr; }
338 child_iterator child_end() const { return nullptr; }
340 unsigned getCommandID() const {
341 return InlineCommandCommentBits.CommandID;
344 StringRef getCommandName(const CommandTraits &Traits) const {
345 return Traits.getCommandInfo(getCommandID())->Name;
348 SourceRange getCommandNameRange() const {
349 return SourceRange(getBeginLoc().getLocWithOffset(-1), getEndLoc());
352 RenderKind getRenderKind() const {
353 return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
356 unsigned getNumArgs() const {
360 StringRef getArgText(unsigned Idx) const {
361 return Args[Idx].Text;
364 SourceRange getArgRange(unsigned Idx) const {
365 return Args[Idx].Range;
369 /// Abstract class for opening and closing HTML tags. HTML tags are always
370 /// treated as inline content (regardless HTML semantics).
371 class HTMLTagComment : public InlineContentComment {
374 SourceRange TagNameRange;
376 HTMLTagComment(CommentKind K,
377 SourceLocation LocBegin,
378 SourceLocation LocEnd,
380 SourceLocation TagNameBegin,
381 SourceLocation TagNameEnd) :
382 InlineContentComment(K, LocBegin, LocEnd),
384 TagNameRange(TagNameBegin, TagNameEnd) {
385 setLocation(TagNameBegin);
386 HTMLTagCommentBits.IsMalformed = 0;
390 static bool classof(const Comment *C) {
391 return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
392 C->getCommentKind() <= LastHTMLTagCommentConstant;
395 StringRef getTagName() const LLVM_READONLY { return TagName; }
397 SourceRange getTagNameSourceRange() const LLVM_READONLY {
398 SourceLocation L = getLocation();
399 return SourceRange(L.getLocWithOffset(1),
400 L.getLocWithOffset(1 + TagName.size()));
403 bool isMalformed() const {
404 return HTMLTagCommentBits.IsMalformed;
407 void setIsMalformed() {
408 HTMLTagCommentBits.IsMalformed = 1;
412 /// An opening HTML tag with attributes.
413 class HTMLStartTagComment : public HTMLTagComment {
417 SourceLocation NameLocBegin;
420 SourceLocation EqualsLoc;
422 SourceRange ValueRange;
427 Attribute(SourceLocation NameLocBegin, StringRef Name) :
428 NameLocBegin(NameLocBegin), Name(Name),
429 EqualsLoc(SourceLocation()),
430 ValueRange(SourceRange()), Value(StringRef())
433 Attribute(SourceLocation NameLocBegin, StringRef Name,
434 SourceLocation EqualsLoc,
435 SourceRange ValueRange, StringRef Value) :
436 NameLocBegin(NameLocBegin), Name(Name),
437 EqualsLoc(EqualsLoc),
438 ValueRange(ValueRange), Value(Value)
441 SourceLocation getNameLocEnd() const {
442 return NameLocBegin.getLocWithOffset(Name.size());
445 SourceRange getNameRange() const {
446 return SourceRange(NameLocBegin, getNameLocEnd());
451 ArrayRef<Attribute> Attributes;
454 HTMLStartTagComment(SourceLocation LocBegin,
456 HTMLTagComment(HTMLStartTagCommentKind,
457 LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
459 LocBegin.getLocWithOffset(1),
460 LocBegin.getLocWithOffset(1 + TagName.size())) {
461 HTMLStartTagCommentBits.IsSelfClosing = false;
464 static bool classof(const Comment *C) {
465 return C->getCommentKind() == HTMLStartTagCommentKind;
468 child_iterator child_begin() const { return nullptr; }
470 child_iterator child_end() const { return nullptr; }
472 unsigned getNumAttrs() const {
473 return Attributes.size();
476 const Attribute &getAttr(unsigned Idx) const {
477 return Attributes[Idx];
480 void setAttrs(ArrayRef<Attribute> Attrs) {
482 if (!Attrs.empty()) {
483 const Attribute &Attr = Attrs.back();
484 SourceLocation L = Attr.ValueRange.getEnd();
488 Range.setEnd(Attr.getNameLocEnd());
493 void setGreaterLoc(SourceLocation GreaterLoc) {
494 Range.setEnd(GreaterLoc);
497 bool isSelfClosing() const {
498 return HTMLStartTagCommentBits.IsSelfClosing;
501 void setSelfClosing() {
502 HTMLStartTagCommentBits.IsSelfClosing = true;
506 /// A closing HTML tag.
507 class HTMLEndTagComment : public HTMLTagComment {
509 HTMLEndTagComment(SourceLocation LocBegin,
510 SourceLocation LocEnd,
512 HTMLTagComment(HTMLEndTagCommentKind,
515 LocBegin.getLocWithOffset(2),
516 LocBegin.getLocWithOffset(2 + TagName.size()))
519 static bool classof(const Comment *C) {
520 return C->getCommentKind() == HTMLEndTagCommentKind;
523 child_iterator child_begin() const { return nullptr; }
525 child_iterator child_end() const { return nullptr; }
528 /// Block content (contains inline content).
530 class BlockContentComment : public Comment {
532 BlockContentComment(CommentKind K,
533 SourceLocation LocBegin,
534 SourceLocation LocEnd) :
535 Comment(K, LocBegin, LocEnd)
539 static bool classof(const Comment *C) {
540 return C->getCommentKind() >= FirstBlockContentCommentConstant &&
541 C->getCommentKind() <= LastBlockContentCommentConstant;
545 /// A single paragraph that contains inline content.
546 class ParagraphComment : public BlockContentComment {
547 ArrayRef<InlineContentComment *> Content;
550 ParagraphComment(ArrayRef<InlineContentComment *> Content) :
551 BlockContentComment(ParagraphCommentKind,
555 if (Content.empty()) {
556 ParagraphCommentBits.IsWhitespace = true;
557 ParagraphCommentBits.IsWhitespaceValid = true;
561 ParagraphCommentBits.IsWhitespaceValid = false;
563 setSourceRange(SourceRange(Content.front()->getBeginLoc(),
564 Content.back()->getEndLoc()));
565 setLocation(Content.front()->getBeginLoc());
568 static bool classof(const Comment *C) {
569 return C->getCommentKind() == ParagraphCommentKind;
572 child_iterator child_begin() const {
573 return reinterpret_cast<child_iterator>(Content.begin());
576 child_iterator child_end() const {
577 return reinterpret_cast<child_iterator>(Content.end());
580 bool isWhitespace() const {
581 if (ParagraphCommentBits.IsWhitespaceValid)
582 return ParagraphCommentBits.IsWhitespace;
584 ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
585 ParagraphCommentBits.IsWhitespaceValid = true;
586 return ParagraphCommentBits.IsWhitespace;
590 bool isWhitespaceNoCache() const;
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).
596 class BlockCommandComment : public BlockContentComment {
603 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
607 /// Word-like arguments.
608 ArrayRef<Argument> Args;
610 /// Paragraph argument.
611 ParagraphComment *Paragraph;
613 BlockCommandComment(CommentKind K,
614 SourceLocation LocBegin,
615 SourceLocation LocEnd,
617 CommandMarkerKind CommandMarker) :
618 BlockContentComment(K, LocBegin, LocEnd),
620 setLocation(getCommandNameBeginLoc());
621 BlockCommandCommentBits.CommandID = CommandID;
622 BlockCommandCommentBits.CommandMarker = CommandMarker;
626 BlockCommandComment(SourceLocation LocBegin,
627 SourceLocation LocEnd,
629 CommandMarkerKind CommandMarker) :
630 BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
632 setLocation(getCommandNameBeginLoc());
633 BlockCommandCommentBits.CommandID = CommandID;
634 BlockCommandCommentBits.CommandMarker = CommandMarker;
637 static bool classof(const Comment *C) {
638 return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
639 C->getCommentKind() <= LastBlockCommandCommentConstant;
642 child_iterator child_begin() const {
643 return reinterpret_cast<child_iterator>(&Paragraph);
646 child_iterator child_end() const {
647 return reinterpret_cast<child_iterator>(&Paragraph + 1);
650 unsigned getCommandID() const {
651 return BlockCommandCommentBits.CommandID;
654 StringRef getCommandName(const CommandTraits &Traits) const {
655 return Traits.getCommandInfo(getCommandID())->Name;
658 SourceLocation getCommandNameBeginLoc() const {
659 return getBeginLoc().getLocWithOffset(1);
662 SourceRange getCommandNameRange(const CommandTraits &Traits) const {
663 StringRef Name = getCommandName(Traits);
664 return SourceRange(getCommandNameBeginLoc(),
665 getBeginLoc().getLocWithOffset(1 + Name.size()));
668 unsigned getNumArgs() const {
672 StringRef getArgText(unsigned Idx) const {
673 return Args[Idx].Text;
676 SourceRange getArgRange(unsigned Idx) const {
677 return Args[Idx].Range;
680 void setArgs(ArrayRef<Argument> A) {
682 if (Args.size() > 0) {
683 SourceLocation NewLocEnd = Args.back().Range.getEnd();
684 if (NewLocEnd.isValid())
685 setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
689 ParagraphComment *getParagraph() const LLVM_READONLY {
693 bool hasNonWhitespaceParagraph() const {
694 return Paragraph && !Paragraph->isWhitespace();
697 void setParagraph(ParagraphComment *PC) {
699 SourceLocation NewLocEnd = PC->getEndLoc();
700 if (NewLocEnd.isValid())
701 setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
704 CommandMarkerKind getCommandMarker() const LLVM_READONLY {
705 return static_cast<CommandMarkerKind>(
706 BlockCommandCommentBits.CommandMarker);
710 /// Doxygen \\param command.
711 class ParamCommandComment : public BlockCommandComment {
713 /// Parameter index in the function declaration.
718 InvalidParamIndex = ~0U,
719 VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
722 ParamCommandComment(SourceLocation LocBegin,
723 SourceLocation LocEnd,
725 CommandMarkerKind CommandMarker) :
726 BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
727 CommandID, CommandMarker),
728 ParamIndex(InvalidParamIndex) {
729 ParamCommandCommentBits.Direction = In;
730 ParamCommandCommentBits.IsDirectionExplicit = false;
733 static bool classof(const Comment *C) {
734 return C->getCommentKind() == ParamCommandCommentKind;
743 static const char *getDirectionAsString(PassDirection D);
745 PassDirection getDirection() const LLVM_READONLY {
746 return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
749 bool isDirectionExplicit() const LLVM_READONLY {
750 return ParamCommandCommentBits.IsDirectionExplicit;
753 void setDirection(PassDirection Direction, bool Explicit) {
754 ParamCommandCommentBits.Direction = Direction;
755 ParamCommandCommentBits.IsDirectionExplicit = Explicit;
758 bool hasParamName() const {
759 return getNumArgs() > 0;
762 StringRef getParamName(const FullComment *FC) const;
764 StringRef getParamNameAsWritten() const {
768 SourceRange getParamNameRange() const {
769 return Args[0].Range;
772 bool isParamIndexValid() const LLVM_READONLY {
773 return ParamIndex != InvalidParamIndex;
776 bool isVarArgParam() const LLVM_READONLY {
777 return ParamIndex == VarArgParamIndex;
780 void setIsVarArgParam() {
781 ParamIndex = VarArgParamIndex;
782 assert(isParamIndexValid());
785 unsigned getParamIndex() const LLVM_READONLY {
786 assert(isParamIndexValid());
787 assert(!isVarArgParam());
791 void setParamIndex(unsigned Index) {
793 assert(isParamIndexValid());
794 assert(!isVarArgParam());
798 /// Doxygen \\tparam command, describes a template parameter.
799 class TParamCommandComment : public BlockCommandComment {
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
807 /// template<typename C, template<typename T> class TT>
808 /// void test(TT<int> aaa);
810 /// For C: Position = { 0 }
811 /// For TT: Position = { 1 }
812 /// For T: Position = { 1, 0 }
813 ArrayRef<unsigned> Position;
816 TParamCommandComment(SourceLocation LocBegin,
817 SourceLocation LocEnd,
819 CommandMarkerKind CommandMarker) :
820 BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
824 static bool classof(const Comment *C) {
825 return C->getCommentKind() == TParamCommandCommentKind;
828 bool hasParamName() const {
829 return getNumArgs() > 0;
832 StringRef getParamName(const FullComment *FC) const;
834 StringRef getParamNameAsWritten() const {
838 SourceRange getParamNameRange() const {
839 return Args[0].Range;
842 bool isPositionValid() const LLVM_READONLY {
843 return !Position.empty();
846 unsigned getDepth() const {
847 assert(isPositionValid());
848 return Position.size();
851 unsigned getIndex(unsigned Depth) const {
852 assert(isPositionValid());
853 return Position[Depth];
856 void setPosition(ArrayRef<unsigned> NewPosition) {
857 Position = NewPosition;
858 assert(isPositionValid());
862 /// A line of text contained in a verbatim block.
863 class VerbatimBlockLineComment : public Comment {
867 VerbatimBlockLineComment(SourceLocation LocBegin,
869 Comment(VerbatimBlockLineCommentKind,
871 LocBegin.getLocWithOffset(Text.size())),
875 static bool classof(const Comment *C) {
876 return C->getCommentKind() == VerbatimBlockLineCommentKind;
879 child_iterator child_begin() const { return nullptr; }
881 child_iterator child_end() const { return nullptr; }
883 StringRef getText() const LLVM_READONLY {
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).
891 class VerbatimBlockComment : public BlockCommandComment {
894 SourceLocation CloseNameLocBegin;
895 ArrayRef<VerbatimBlockLineComment *> Lines;
898 VerbatimBlockComment(SourceLocation LocBegin,
899 SourceLocation LocEnd,
900 unsigned CommandID) :
901 BlockCommandComment(VerbatimBlockCommentKind,
902 LocBegin, LocEnd, CommandID,
903 CMK_At) // FIXME: improve source fidelity.
906 static bool classof(const Comment *C) {
907 return C->getCommentKind() == VerbatimBlockCommentKind;
910 child_iterator child_begin() const {
911 return reinterpret_cast<child_iterator>(Lines.begin());
914 child_iterator child_end() const {
915 return reinterpret_cast<child_iterator>(Lines.end());
918 void setCloseName(StringRef Name, SourceLocation LocBegin) {
920 CloseNameLocBegin = LocBegin;
923 void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
927 StringRef getCloseName() const {
931 unsigned getNumLines() const {
935 StringRef getText(unsigned LineIdx) const {
936 return Lines[LineIdx]->getText();
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
943 class VerbatimLineComment : public BlockCommandComment {
946 SourceLocation TextBegin;
949 VerbatimLineComment(SourceLocation LocBegin,
950 SourceLocation LocEnd,
952 SourceLocation TextBegin,
954 BlockCommandComment(VerbatimLineCommentKind,
957 CMK_At), // FIXME: improve source fidelity.
962 static bool classof(const Comment *C) {
963 return C->getCommentKind() == VerbatimLineCommentKind;
966 child_iterator child_begin() const { return nullptr; }
968 child_iterator child_end() const { return nullptr; }
970 StringRef getText() const {
974 SourceRange getTextRange() const {
975 return SourceRange(TextBegin, getEndLoc());
979 /// Information about the declaration, useful to clients of FullComment.
981 /// Declaration the comment is actually attached to (in the source).
982 /// Should not be NULL.
983 const Decl *CommentDecl;
985 /// CurrentDecl is the declaration with which the FullComment is associated.
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
992 /// The information in the DeclInfo corresponds to CurrentDecl.
993 const Decl *CurrentDecl;
995 /// Parameters that can be referenced by \\param if \c CommentDecl is something
996 /// that we consider a "function".
997 ArrayRef<const ParmVarDecl *> ParamVars;
999 /// Function return type if \c CommentDecl is something that we consider
1001 QualType ReturnType;
1003 /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
1004 /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
1006 const TemplateParameterList *TemplateParameters;
1008 /// A simplified description of \c CommentDecl kind that should be good enough
1009 /// for documentation rendering purposes.
1011 /// Everything else not explicitly mentioned below.
1014 /// Something that we consider a "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,
1026 /// Something that we consider a "class":
1027 /// \li class/struct,
1028 /// \li class template,
1029 /// \li class template (partial) specialization.
1032 /// Something that we consider a "variable":
1033 /// \li namespace scope variables;
1034 /// \li static and non-static class data members;
1035 /// \li enumerators.
1038 /// A C++ namespace.
1041 /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
1042 /// see \c TypedefNameDecl.
1045 /// An enumeration or scoped enumeration.
1049 /// What kind of template specialization \c CommentDecl is.
1050 enum TemplateDeclKind {
1053 TemplateSpecialization,
1054 TemplatePartialSpecialization
1057 /// If false, only \c CommentDecl is valid.
1058 unsigned IsFilled : 1;
1060 /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
1063 /// Is \c CommentDecl a template declaration.
1064 unsigned TemplateKind : 2;
1066 /// Is \c CommentDecl an ObjCMethodDecl.
1067 unsigned IsObjCMethod : 1;
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;
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;
1081 DeclKind getKind() const LLVM_READONLY {
1082 return static_cast<DeclKind>(Kind);
1085 TemplateDeclKind getTemplateKind() const LLVM_READONLY {
1086 return static_cast<TemplateDeclKind>(TemplateKind);
1090 /// A full comment attached to a declaration, contains block content.
1091 class FullComment : public Comment {
1092 ArrayRef<BlockContentComment *> Blocks;
1093 DeclInfo *ThisDeclInfo;
1096 FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
1097 Comment(FullCommentKind, SourceLocation(), SourceLocation()),
1098 Blocks(Blocks), ThisDeclInfo(D) {
1103 SourceRange(Blocks.front()->getBeginLoc(), Blocks.back()->getEndLoc()));
1104 setLocation(Blocks.front()->getBeginLoc());
1107 static bool classof(const Comment *C) {
1108 return C->getCommentKind() == FullCommentKind;
1111 child_iterator child_begin() const {
1112 return reinterpret_cast<child_iterator>(Blocks.begin());
1115 child_iterator child_end() const {
1116 return reinterpret_cast<child_iterator>(Blocks.end());
1119 const Decl *getDecl() const LLVM_READONLY {
1120 return ThisDeclInfo->CommentDecl;
1123 const DeclInfo *getDeclInfo() const LLVM_READONLY {
1124 if (!ThisDeclInfo->IsFilled)
1125 ThisDeclInfo->fill();
1126 return ThisDeclInfo;
1129 ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
1132 } // end namespace comments
1133 } // end namespace clang