clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Comment.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libclangAST/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libclangAST/obj/../include/clang/AST -I /usr/src/gnu/usr.bin/clang/libclangAST/../../../llvm/clang/include -I /usr/src/gnu/usr.bin/clang/libclangAST/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libclangAST/../include -I /usr/src/gnu/usr.bin/clang/libclangAST/obj -I /usr/src/gnu/usr.bin/clang/libclangAST/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libclangAST/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libclangAST/../../../llvm/clang/lib/AST/Comment.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "clang/AST/Comment.h" |
10 | #include "clang/AST/ASTContext.h" |
11 | #include "clang/AST/Decl.h" |
12 | #include "clang/AST/DeclObjC.h" |
13 | #include "clang/AST/DeclTemplate.h" |
14 | #include "clang/Basic/CharInfo.h" |
15 | #include "llvm/Support/ErrorHandling.h" |
16 | #include <type_traits> |
17 | |
18 | namespace clang { |
19 | namespace comments { |
20 | |
21 | |
22 | |
23 | #define ABSTRACT_COMMENT(COMMENT) |
24 | #define COMMENT(CLASS, PARENT) \ |
25 | static_assert(std::is_trivially_destructible<CLASS>::value, \ |
26 | #CLASS " should be trivially destructible!"); |
27 | #include "clang/AST/CommentNodes.inc" |
28 | #undef COMMENT |
29 | #undef ABSTRACT_COMMENT |
30 | |
31 | |
32 | static_assert(std::is_trivially_destructible<DeclInfo>::value, |
33 | "DeclInfo should be trivially destructible!"); |
34 | |
35 | const char *Comment::getCommentKindName() const { |
36 | switch (getCommentKind()) { |
37 | case NoCommentKind: return "NoCommentKind"; |
38 | #define ABSTRACT_COMMENT(COMMENT) |
39 | #define COMMENT(CLASS, PARENT) \ |
40 | case CLASS##Kind: \ |
41 | return #CLASS; |
42 | #include "clang/AST/CommentNodes.inc" |
43 | #undef COMMENT |
44 | #undef ABSTRACT_COMMENT |
45 | } |
46 | llvm_unreachable("Unknown comment kind!"); |
47 | } |
48 | |
49 | namespace { |
50 | struct good {}; |
51 | struct bad {}; |
52 | |
53 | template <typename T> |
54 | good implements_child_begin_end(Comment::child_iterator (T::*)() const) { |
55 | return good(); |
56 | } |
57 | |
58 | LLVM_ATTRIBUTE_UNUSED |
59 | static inline bad implements_child_begin_end( |
60 | Comment::child_iterator (Comment::*)() const) { |
61 | return bad(); |
62 | } |
63 | |
64 | #define ASSERT_IMPLEMENTS_child_begin(function) \ |
65 | (void) good(implements_child_begin_end(function)) |
66 | |
67 | LLVM_ATTRIBUTE_UNUSED |
68 | static inline void CheckCommentASTNodes() { |
69 | #define ABSTRACT_COMMENT(COMMENT) |
70 | #define COMMENT(CLASS, PARENT) \ |
71 | ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ |
72 | ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); |
73 | #include "clang/AST/CommentNodes.inc" |
74 | #undef COMMENT |
75 | #undef ABSTRACT_COMMENT |
76 | } |
77 | |
78 | #undef ASSERT_IMPLEMENTS_child_begin |
79 | |
80 | } |
81 | |
82 | Comment::child_iterator Comment::child_begin() const { |
83 | switch (getCommentKind()) { |
84 | case NoCommentKind: llvm_unreachable("comment without a kind"); |
85 | #define ABSTRACT_COMMENT(COMMENT) |
86 | #define COMMENT(CLASS, PARENT) \ |
87 | case CLASS##Kind: \ |
88 | return static_cast<const CLASS *>(this)->child_begin(); |
89 | #include "clang/AST/CommentNodes.inc" |
90 | #undef COMMENT |
91 | #undef ABSTRACT_COMMENT |
92 | } |
93 | llvm_unreachable("Unknown comment kind!"); |
94 | } |
95 | |
96 | Comment::child_iterator Comment::child_end() const { |
97 | switch (getCommentKind()) { |
98 | case NoCommentKind: llvm_unreachable("comment without a kind"); |
99 | #define ABSTRACT_COMMENT(COMMENT) |
100 | #define COMMENT(CLASS, PARENT) \ |
101 | case CLASS##Kind: \ |
102 | return static_cast<const CLASS *>(this)->child_end(); |
103 | #include "clang/AST/CommentNodes.inc" |
104 | #undef COMMENT |
105 | #undef ABSTRACT_COMMENT |
106 | } |
107 | llvm_unreachable("Unknown comment kind!"); |
108 | } |
109 | |
110 | bool TextComment::isWhitespaceNoCache() const { |
111 | for (StringRef::const_iterator I = Text.begin(), E = Text.end(); |
112 | I != E; ++I) { |
113 | if (!clang::isWhitespace(*I)) |
114 | return false; |
115 | } |
116 | return true; |
117 | } |
118 | |
119 | bool ParagraphComment::isWhitespaceNoCache() const { |
120 | for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { |
121 | if (const TextComment *TC = dyn_cast<TextComment>(*I)) { |
122 | if (!TC->isWhitespace()) |
123 | return false; |
124 | } else |
125 | return false; |
126 | } |
127 | return true; |
128 | } |
129 | |
130 | static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { |
131 | TypeLoc TL = SrcTL.IgnoreParens(); |
132 | |
133 | |
134 | if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>()) |
135 | return AttributeTL.getModifiedLoc(); |
136 | |
137 | if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) |
138 | return QualifiedTL.getUnqualifiedLoc(); |
139 | |
140 | if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) |
141 | return PointerTL.getPointeeLoc().getUnqualifiedLoc(); |
142 | |
143 | if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) |
144 | return ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); |
145 | |
146 | if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) |
147 | return ATL.getOriginalLoc(); |
148 | if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) |
149 | return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); |
150 | if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>()) |
151 | return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); |
152 | if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) |
153 | return ETL.getNamedTypeLoc(); |
154 | |
155 | return TL; |
156 | } |
157 | |
158 | static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) { |
159 | TypeLoc PrevTL; |
160 | while (PrevTL != TL) { |
161 | PrevTL = TL; |
162 | TL = lookThroughTypedefOrTypeAliasLocs(TL); |
163 | } |
164 | |
165 | if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { |
166 | ResFTL = FTL; |
167 | return true; |
168 | } |
169 | |
170 | if (TemplateSpecializationTypeLoc STL = |
171 | TL.getAs<TemplateSpecializationTypeLoc>()) { |
172 | |
173 | |
174 | |
175 | |
176 | if (STL.getNumArgs() != 1) |
177 | return false; |
178 | TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); |
179 | if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) |
180 | return false; |
181 | TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); |
182 | TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); |
183 | if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { |
184 | ResFTL = FTL; |
185 | return true; |
186 | } |
187 | } |
188 | |
189 | return false; |
190 | } |
191 | |
192 | const char *ParamCommandComment::getDirectionAsString(PassDirection D) { |
193 | switch (D) { |
194 | case ParamCommandComment::In: |
195 | return "[in]"; |
196 | case ParamCommandComment::Out: |
197 | return "[out]"; |
198 | case ParamCommandComment::InOut: |
199 | return "[in,out]"; |
200 | } |
201 | llvm_unreachable("unknown PassDirection"); |
202 | } |
203 | |
204 | void DeclInfo::fill() { |
205 | assert(!IsFilled); |
206 | |
207 | |
208 | Kind = OtherKind; |
209 | TemplateKind = NotTemplate; |
210 | IsObjCMethod = false; |
211 | IsInstanceMethod = false; |
212 | IsClassMethod = false; |
213 | ParamVars = None; |
214 | TemplateParameters = nullptr; |
| 5 | | Null pointer value stored to field 'TemplateParameters' | |
|
215 | |
216 | if (!CommentDecl) { |
| 6 | | Assuming field 'CommentDecl' is null | |
|
| |
217 | |
218 | IsFilled = true; |
219 | return; |
220 | } |
221 | CurrentDecl = CommentDecl; |
222 | |
223 | Decl::Kind K = CommentDecl->getKind(); |
224 | switch (K) { |
225 | default: |
226 | |
227 | break; |
228 | case Decl::Function: |
229 | case Decl::CXXMethod: |
230 | case Decl::CXXConstructor: |
231 | case Decl::CXXDestructor: |
232 | case Decl::CXXConversion: { |
233 | const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); |
234 | Kind = FunctionKind; |
235 | ParamVars = FD->parameters(); |
236 | ReturnType = FD->getReturnType(); |
237 | unsigned NumLists = FD->getNumTemplateParameterLists(); |
238 | if (NumLists != 0) { |
239 | TemplateKind = TemplateSpecialization; |
240 | TemplateParameters = |
241 | FD->getTemplateParameterList(NumLists - 1); |
242 | } |
243 | |
244 | if (K == Decl::CXXMethod || K == Decl::CXXConstructor || |
245 | K == Decl::CXXDestructor || K == Decl::CXXConversion) { |
246 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); |
247 | IsInstanceMethod = MD->isInstance(); |
248 | IsClassMethod = !IsInstanceMethod; |
249 | } |
250 | break; |
251 | } |
252 | case Decl::ObjCMethod: { |
253 | const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); |
254 | Kind = FunctionKind; |
255 | ParamVars = MD->parameters(); |
256 | ReturnType = MD->getReturnType(); |
257 | IsObjCMethod = true; |
258 | IsInstanceMethod = MD->isInstanceMethod(); |
259 | IsClassMethod = !IsInstanceMethod; |
260 | break; |
261 | } |
262 | case Decl::FunctionTemplate: { |
263 | const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); |
264 | Kind = FunctionKind; |
265 | TemplateKind = Template; |
266 | const FunctionDecl *FD = FTD->getTemplatedDecl(); |
267 | ParamVars = FD->parameters(); |
268 | ReturnType = FD->getReturnType(); |
269 | TemplateParameters = FTD->getTemplateParameters(); |
270 | break; |
271 | } |
272 | case Decl::ClassTemplate: { |
273 | const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); |
274 | Kind = ClassKind; |
275 | TemplateKind = Template; |
276 | TemplateParameters = CTD->getTemplateParameters(); |
277 | break; |
278 | } |
279 | case Decl::ClassTemplatePartialSpecialization: { |
280 | const ClassTemplatePartialSpecializationDecl *CTPSD = |
281 | cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); |
282 | Kind = ClassKind; |
283 | TemplateKind = TemplatePartialSpecialization; |
284 | TemplateParameters = CTPSD->getTemplateParameters(); |
285 | break; |
286 | } |
287 | case Decl::ClassTemplateSpecialization: |
288 | Kind = ClassKind; |
289 | TemplateKind = TemplateSpecialization; |
290 | break; |
291 | case Decl::Record: |
292 | case Decl::CXXRecord: |
293 | Kind = ClassKind; |
294 | break; |
295 | case Decl::Var: |
296 | case Decl::Field: |
297 | case Decl::EnumConstant: |
298 | case Decl::ObjCIvar: |
299 | case Decl::ObjCAtDefsField: |
300 | case Decl::ObjCProperty: { |
301 | const TypeSourceInfo *TSI; |
302 | if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl)) |
303 | TSI = VD->getTypeSourceInfo(); |
304 | else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl)) |
305 | TSI = PD->getTypeSourceInfo(); |
306 | else |
307 | TSI = nullptr; |
308 | if (TSI) { |
309 | TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); |
310 | FunctionTypeLoc FTL; |
311 | if (getFunctionTypeLoc(TL, FTL)) { |
312 | ParamVars = FTL.getParams(); |
313 | ReturnType = FTL.getReturnLoc().getType(); |
314 | } |
315 | } |
316 | Kind = VariableKind; |
317 | break; |
318 | } |
319 | case Decl::Namespace: |
320 | Kind = NamespaceKind; |
321 | break; |
322 | case Decl::TypeAlias: |
323 | case Decl::Typedef: { |
324 | Kind = TypedefKind; |
325 | |
326 | |
327 | const TypeSourceInfo *TSI = |
328 | K == Decl::Typedef |
329 | ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo() |
330 | : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo(); |
331 | if (!TSI) |
332 | break; |
333 | TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); |
334 | FunctionTypeLoc FTL; |
335 | if (getFunctionTypeLoc(TL, FTL)) { |
336 | Kind = FunctionKind; |
337 | ParamVars = FTL.getParams(); |
338 | ReturnType = FTL.getReturnLoc().getType(); |
339 | } |
340 | break; |
341 | } |
342 | case Decl::TypeAliasTemplate: { |
343 | const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); |
344 | Kind = TypedefKind; |
345 | TemplateKind = Template; |
346 | TemplateParameters = TAT->getTemplateParameters(); |
347 | TypeAliasDecl *TAD = TAT->getTemplatedDecl(); |
348 | if (!TAD) |
349 | break; |
350 | |
351 | const TypeSourceInfo *TSI = TAD->getTypeSourceInfo(); |
352 | if (!TSI) |
353 | break; |
354 | TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); |
355 | FunctionTypeLoc FTL; |
356 | if (getFunctionTypeLoc(TL, FTL)) { |
357 | Kind = FunctionKind; |
358 | ParamVars = FTL.getParams(); |
359 | ReturnType = FTL.getReturnLoc().getType(); |
360 | } |
361 | break; |
362 | } |
363 | case Decl::Enum: |
364 | Kind = EnumKind; |
365 | break; |
366 | } |
367 | |
368 | IsFilled = true; |
369 | } |
370 | |
371 | StringRef ParamCommandComment::getParamName(const FullComment *FC) const { |
372 | assert(isParamIndexValid()); |
373 | if (isVarArgParam()) |
374 | return "..."; |
375 | return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); |
376 | } |
377 | |
378 | StringRef TParamCommandComment::getParamName(const FullComment *FC) const { |
379 | assert(isPositionValid()); |
380 | const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; |
| 1 | Calling 'FullComment::getDeclInfo' | |
|
| 9 | | Returning from 'FullComment::getDeclInfo' | |
|
| 10 | | 'TPL' initialized to a null pointer value | |
|
381 | for (unsigned i = 0, e = getDepth(); i != e; ++i) { |
| 11 | | Assuming 'i' is not equal to 'e' | |
|
| 12 | | Loop condition is true. Entering loop body | |
|
382 | assert(TPL && "Unknown TemplateParameterList"); |
383 | if (i == e - 1) |
| 13 | | Assuming the condition is false | |
|
| |
384 | return TPL->getParam(getIndex(i))->getName(); |
385 | const NamedDecl *Param = TPL->getParam(getIndex(i)); |
| 15 | | Called C++ object pointer is null |
|
386 | if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) |
387 | TPL = TTP->getTemplateParameters(); |
388 | } |
389 | return ""; |
390 | } |
391 | |
392 | } |
393 | } |
394 | |
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 | |