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