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