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