/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Index/USRGeneration.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- USRGeneration.cpp - Routines for USR generation --------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "clang/Index/USRGeneration.h" |
10 | | #include "clang/AST/ASTContext.h" |
11 | | #include "clang/AST/Attr.h" |
12 | | #include "clang/AST/DeclTemplate.h" |
13 | | #include "clang/AST/DeclVisitor.h" |
14 | | #include "clang/Basic/FileManager.h" |
15 | | #include "clang/Lex/PreprocessingRecord.h" |
16 | | #include "llvm/Support/Path.h" |
17 | | #include "llvm/Support/raw_ostream.h" |
18 | | |
19 | | using namespace clang; |
20 | | using namespace clang::index; |
21 | | |
22 | | //===----------------------------------------------------------------------===// |
23 | | // USR generation. |
24 | | //===----------------------------------------------------------------------===// |
25 | | |
26 | | /// \returns true on error. |
27 | | static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, |
28 | 2.46k | const SourceManager &SM, bool IncludeOffset) { |
29 | 2.46k | if (Loc.isInvalid()) { |
30 | 0 | return true; |
31 | 0 | } |
32 | 2.46k | Loc = SM.getExpansionLoc(Loc); |
33 | 2.46k | const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc); |
34 | 2.46k | OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first); |
35 | 2.46k | if (FE) { |
36 | 2.40k | OS << llvm::sys::path::filename(FE->getName()); |
37 | 2.40k | } else { |
38 | | // This case really isn't interesting. |
39 | 55 | return true; |
40 | 55 | } |
41 | 2.40k | if (IncludeOffset) { |
42 | | // Use the offest into the FileID to represent the location. Using |
43 | | // a line/column can cause us to look back at the original source file, |
44 | | // which is expensive. |
45 | 1.86k | OS << '@' << Decomposed.second; |
46 | 1.86k | } |
47 | 2.40k | return false; |
48 | 2.46k | } |
49 | | |
50 | 20.6k | static StringRef GetExternalSourceContainer(const NamedDecl *D) { |
51 | 20.6k | if (!D) |
52 | 1.22k | return StringRef(); |
53 | 19.4k | if (auto *attr = D->getExternalSourceSymbolAttr()) { |
54 | 61 | return attr->getDefinedIn(); |
55 | 61 | } |
56 | 19.3k | return StringRef(); |
57 | 19.4k | } |
58 | | |
59 | | namespace { |
60 | | class USRGenerator : public ConstDeclVisitor<USRGenerator> { |
61 | | SmallVectorImpl<char> &Buf; |
62 | | llvm::raw_svector_ostream Out; |
63 | | bool IgnoreResults; |
64 | | ASTContext *Context; |
65 | | bool generatedLoc; |
66 | | |
67 | | llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; |
68 | | |
69 | | public: |
70 | | explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf) |
71 | | : Buf(Buf), |
72 | | Out(Buf), |
73 | | IgnoreResults(false), |
74 | | Context(Ctx), |
75 | | generatedLoc(false) |
76 | 20.9k | { |
77 | | // Add the USR space prefix. |
78 | 20.9k | Out << getUSRSpacePrefix(); |
79 | 20.9k | } |
80 | | |
81 | 20.9k | bool ignoreResults() const { return IgnoreResults; } |
82 | | |
83 | | // Visitation methods from generating USRs from AST elements. |
84 | | void VisitDeclContext(const DeclContext *D); |
85 | | void VisitFieldDecl(const FieldDecl *D); |
86 | | void VisitFunctionDecl(const FunctionDecl *D); |
87 | | void VisitNamedDecl(const NamedDecl *D); |
88 | | void VisitNamespaceDecl(const NamespaceDecl *D); |
89 | | void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); |
90 | | void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); |
91 | | void VisitClassTemplateDecl(const ClassTemplateDecl *D); |
92 | | void VisitObjCContainerDecl(const ObjCContainerDecl *CD, |
93 | | const ObjCCategoryDecl *CatD = nullptr); |
94 | | void VisitObjCMethodDecl(const ObjCMethodDecl *MD); |
95 | | void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); |
96 | | void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); |
97 | | void VisitTagDecl(const TagDecl *D); |
98 | | void VisitTypedefDecl(const TypedefDecl *D); |
99 | | void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); |
100 | | void VisitVarDecl(const VarDecl *D); |
101 | | void VisitBindingDecl(const BindingDecl *D); |
102 | | void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); |
103 | | void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); |
104 | | void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); |
105 | | void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); |
106 | | void VisitConceptDecl(const ConceptDecl *D); |
107 | | |
108 | 1 | void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { |
109 | 1 | IgnoreResults = true; // No USRs for linkage specs themselves. |
110 | 1 | } |
111 | | |
112 | 1 | void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { |
113 | 1 | IgnoreResults = true; |
114 | 1 | } |
115 | | |
116 | 3 | void VisitUsingDecl(const UsingDecl *D) { |
117 | 3 | VisitDeclContext(D->getDeclContext()); |
118 | 3 | Out << "@UD@"; |
119 | | |
120 | 3 | bool EmittedDeclName = !EmitDeclName(D); |
121 | 3 | assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls"); |
122 | 3 | (void)EmittedDeclName; |
123 | 3 | } |
124 | | |
125 | | bool ShouldGenerateLocation(const NamedDecl *D); |
126 | | |
127 | 1.63k | bool isLocal(const NamedDecl *D) { |
128 | 1.63k | return D->getParentFunctionOrMethod() != nullptr; |
129 | 1.63k | } |
130 | | |
131 | | void GenExtSymbolContainer(const NamedDecl *D); |
132 | | |
133 | | /// Generate the string component containing the location of the |
134 | | /// declaration. |
135 | | bool GenLoc(const Decl *D, bool IncludeOffset); |
136 | | |
137 | | /// String generation methods used both by the visitation methods |
138 | | /// and from other clients that want to directly generate USRs. These |
139 | | /// methods do not construct complete USRs (which incorporate the parents |
140 | | /// of an AST element), but only the fragments concerning the AST element |
141 | | /// itself. |
142 | | |
143 | | /// Generate a USR for an Objective-C class. |
144 | | void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn, |
145 | 1.29k | StringRef CategoryContextExtSymbolDefinedIn) { |
146 | 1.29k | generateUSRForObjCClass(cls, Out, ExtSymDefinedIn, |
147 | 1.29k | CategoryContextExtSymbolDefinedIn); |
148 | 1.29k | } |
149 | | |
150 | | /// Generate a USR for an Objective-C class category. |
151 | | void GenObjCCategory(StringRef cls, StringRef cat, |
152 | 43 | StringRef clsExt, StringRef catExt) { |
153 | 43 | generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt); |
154 | 43 | } |
155 | | |
156 | | /// Generate a USR fragment for an Objective-C property. |
157 | 219 | void GenObjCProperty(StringRef prop, bool isClassProp) { |
158 | 219 | generateUSRForObjCProperty(prop, isClassProp, Out); |
159 | 219 | } |
160 | | |
161 | | /// Generate a USR for an Objective-C protocol. |
162 | 152 | void GenObjCProtocol(StringRef prot, StringRef ext) { |
163 | 152 | generateUSRForObjCProtocol(prot, Out, ext); |
164 | 152 | } |
165 | | |
166 | | void VisitType(QualType T); |
167 | | void VisitTemplateParameterList(const TemplateParameterList *Params); |
168 | | void VisitTemplateName(TemplateName Name); |
169 | | void VisitTemplateArgument(const TemplateArgument &Arg); |
170 | | |
171 | | void VisitMSGuidDecl(const MSGuidDecl *D); |
172 | | |
173 | | /// Emit a Decl's name using NamedDecl::printName() and return true if |
174 | | /// the decl had no name. |
175 | | bool EmitDeclName(const NamedDecl *D); |
176 | | }; |
177 | | } // end anonymous namespace |
178 | | |
179 | | //===----------------------------------------------------------------------===// |
180 | | // Generating USRs from ASTS. |
181 | | //===----------------------------------------------------------------------===// |
182 | | |
183 | 15.6k | bool USRGenerator::EmitDeclName(const NamedDecl *D) { |
184 | 15.6k | DeclarationName N = D->getDeclName(); |
185 | 15.6k | if (N.isEmpty()) |
186 | 155 | return true; |
187 | 15.4k | Out << N; |
188 | 15.4k | return false; |
189 | 15.6k | } |
190 | | |
191 | 24.1k | bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) { |
192 | 24.1k | if (D->isExternallyVisible()) |
193 | 22.4k | return false; |
194 | 1.69k | if (D->getParentFunctionOrMethod()) |
195 | 1.07k | return true; |
196 | 624 | SourceLocation Loc = D->getLocation(); |
197 | 624 | if (Loc.isInvalid()) |
198 | 6 | return false; |
199 | 618 | const SourceManager &SM = Context->getSourceManager(); |
200 | 618 | return !SM.isInSystemHeader(Loc); |
201 | 624 | } |
202 | | |
203 | 34.3k | void USRGenerator::VisitDeclContext(const DeclContext *DC) { |
204 | 34.3k | if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) |
205 | 15.5k | Visit(D); |
206 | 18.8k | else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs. |
207 | 9 | VisitDeclContext(DC->getParent()); |
208 | 34.3k | } |
209 | | |
210 | 545 | void USRGenerator::VisitFieldDecl(const FieldDecl *D) { |
211 | | // The USR for an ivar declared in a class extension is based on the |
212 | | // ObjCInterfaceDecl, not the ObjCCategoryDecl. |
213 | 545 | if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) |
214 | 61 | Visit(ID); |
215 | 484 | else |
216 | 484 | VisitDeclContext(D->getDeclContext()); |
217 | 545 | Out << (isa<ObjCIvarDecl>(D) ? "@"61 : "@FI@"484 ); |
218 | 545 | if (EmitDeclName(D)) { |
219 | | // Bit fields can be anonymous. |
220 | 0 | IgnoreResults = true; |
221 | 0 | return; |
222 | 0 | } |
223 | 545 | } |
224 | | |
225 | 9.22k | void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { |
226 | 9.22k | if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))35 ) |
227 | 0 | return; |
228 | | |
229 | 9.22k | if (D->getType().isNull()) { |
230 | 0 | IgnoreResults = true; |
231 | 0 | return; |
232 | 0 | } |
233 | | |
234 | 9.22k | const unsigned StartSize = Buf.size(); |
235 | 9.22k | VisitDeclContext(D->getDeclContext()); |
236 | 9.22k | if (Buf.size() == StartSize) |
237 | 3.95k | GenExtSymbolContainer(D); |
238 | | |
239 | 9.22k | bool IsTemplate = false; |
240 | 9.22k | if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { |
241 | 443 | IsTemplate = true; |
242 | 443 | Out << "@FT@"; |
243 | 443 | VisitTemplateParameterList(FunTmpl->getTemplateParameters()); |
244 | 443 | } else |
245 | 8.78k | Out << "@F@"; |
246 | | |
247 | 9.22k | PrintingPolicy Policy(Context->getLangOpts()); |
248 | | // Forward references can have different template argument names. Suppress the |
249 | | // template argument names in constructors to make their USR more stable. |
250 | 9.22k | Policy.SuppressTemplateArgsInCXXConstructors = true; |
251 | 9.22k | D->getDeclName().print(Out, Policy); |
252 | | |
253 | 9.22k | ASTContext &Ctx = *Context; |
254 | 9.22k | if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()8.81k ) && |
255 | 9.22k | !D->hasAttr<OverloadableAttr>()420 ) |
256 | 414 | return; |
257 | | |
258 | 8.81k | if (const TemplateArgumentList * |
259 | 8.81k | SpecArgs = D->getTemplateSpecializationArgs()) { |
260 | 54 | Out << '<'; |
261 | 136 | for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I82 ) { |
262 | 82 | Out << '#'; |
263 | 82 | VisitTemplateArgument(SpecArgs->get(I)); |
264 | 82 | } |
265 | 54 | Out << '>'; |
266 | 54 | } |
267 | | |
268 | | // Mangle in type information for the arguments. |
269 | 8.81k | for (auto *PD : D->parameters()) { |
270 | 2.55k | Out << '#'; |
271 | 2.55k | VisitType(PD->getType()); |
272 | 2.55k | } |
273 | 8.81k | if (D->isVariadic()) |
274 | 9 | Out << '.'; |
275 | 8.81k | if (IsTemplate) { |
276 | | // Function templates can be overloaded by return type, for example: |
277 | | // \code |
278 | | // template <class T> typename T::A foo() {} |
279 | | // template <class T> typename T::B foo() {} |
280 | | // \endcode |
281 | 442 | Out << '#'; |
282 | 442 | VisitType(D->getReturnType()); |
283 | 442 | } |
284 | 8.81k | Out << '#'; |
285 | 8.81k | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { |
286 | 4.92k | if (MD->isStatic()) |
287 | 812 | Out << 'S'; |
288 | | // FIXME: OpenCL: Need to consider address spaces |
289 | 4.92k | if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers()) |
290 | 152 | Out << (char)('0' + quals); |
291 | 4.92k | switch (MD->getRefQualifier()) { |
292 | 4.91k | case RQ_None: break; |
293 | 1 | case RQ_LValue: Out << '&'; break; |
294 | 1 | case RQ_RValue: Out << "&&"; break; |
295 | 4.92k | } |
296 | 4.92k | } |
297 | 8.81k | } |
298 | | |
299 | 1.15k | void USRGenerator::VisitNamedDecl(const NamedDecl *D) { |
300 | 1.15k | VisitDeclContext(D->getDeclContext()); |
301 | 1.15k | Out << "@"; |
302 | | |
303 | 1.15k | if (EmitDeclName(D)) { |
304 | | // The string can be empty if the declaration has no name; e.g., it is |
305 | | // the ParmDecl with no name for declaration of a function pointer type, |
306 | | // e.g.: void (*f)(void *); |
307 | | // In this case, don't generate a USR. |
308 | 0 | IgnoreResults = true; |
309 | 0 | } |
310 | 1.15k | } |
311 | | |
312 | 1.95k | void USRGenerator::VisitVarDecl(const VarDecl *D) { |
313 | | // VarDecls can be declared 'extern' within a function or method body, |
314 | | // but their enclosing DeclContext is the function, not the TU. We need |
315 | | // to check the storage class to correctly generate the USR. |
316 | 1.95k | if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))1.06k ) |
317 | 0 | return; |
318 | | |
319 | 1.95k | VisitDeclContext(D->getDeclContext()); |
320 | | |
321 | 1.95k | if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) { |
322 | 20 | Out << "@VT"; |
323 | 20 | VisitTemplateParameterList(VarTmpl->getTemplateParameters()); |
324 | 1.93k | } else if (const VarTemplatePartialSpecializationDecl *PartialSpec |
325 | 1.93k | = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { |
326 | 11 | Out << "@VP"; |
327 | 11 | VisitTemplateParameterList(PartialSpec->getTemplateParameters()); |
328 | 11 | } |
329 | | |
330 | | // Variables always have simple names. |
331 | 1.95k | StringRef s = D->getName(); |
332 | | |
333 | | // The string can be empty if the declaration has no name; e.g., it is |
334 | | // the ParmDecl with no name for declaration of a function pointer type, e.g.: |
335 | | // void (*f)(void *); |
336 | | // In this case, don't generate a USR. |
337 | 1.95k | if (s.empty()) |
338 | 73 | IgnoreResults = true; |
339 | 1.88k | else |
340 | 1.88k | Out << '@' << s; |
341 | | |
342 | | // For a template specialization, mangle the template arguments. |
343 | 1.95k | if (const VarTemplateSpecializationDecl *Spec |
344 | 1.95k | = dyn_cast<VarTemplateSpecializationDecl>(D)) { |
345 | 46 | const TemplateArgumentList &Args = Spec->getTemplateArgs(); |
346 | 46 | Out << '>'; |
347 | 133 | for (unsigned I = 0, N = Args.size(); I != N; ++I87 ) { |
348 | 87 | Out << '#'; |
349 | 87 | VisitTemplateArgument(Args.get(I)); |
350 | 87 | } |
351 | 46 | } |
352 | 1.95k | } |
353 | | |
354 | 12 | void USRGenerator::VisitBindingDecl(const BindingDecl *D) { |
355 | 12 | if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true)2 ) |
356 | 0 | return; |
357 | 12 | VisitNamedDecl(D); |
358 | 12 | } |
359 | | |
360 | | void USRGenerator::VisitNonTypeTemplateParmDecl( |
361 | 23 | const NonTypeTemplateParmDecl *D) { |
362 | 23 | GenLoc(D, /*IncludeOffset=*/true); |
363 | 23 | } |
364 | | |
365 | | void USRGenerator::VisitTemplateTemplateParmDecl( |
366 | 2 | const TemplateTemplateParmDecl *D) { |
367 | 2 | GenLoc(D, /*IncludeOffset=*/true); |
368 | 2 | } |
369 | | |
370 | 7.59k | void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { |
371 | 7.59k | if (D->isAnonymousNamespace()) { |
372 | 14 | Out << "@aN"; |
373 | 14 | return; |
374 | 14 | } |
375 | | |
376 | 7.58k | VisitDeclContext(D->getDeclContext()); |
377 | 7.58k | if (!IgnoreResults) |
378 | 7.58k | Out << "@N@" << D->getName(); |
379 | 7.58k | } |
380 | | |
381 | 194 | void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { |
382 | 194 | VisitFunctionDecl(D->getTemplatedDecl()); |
383 | 194 | } |
384 | | |
385 | 662 | void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { |
386 | 662 | VisitTagDecl(D->getTemplatedDecl()); |
387 | 662 | } |
388 | | |
389 | 19 | void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { |
390 | 19 | VisitDeclContext(D->getDeclContext()); |
391 | 19 | if (!IgnoreResults) |
392 | 19 | Out << "@NA@" << D->getName(); |
393 | 19 | } |
394 | | |
395 | 601 | static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) { |
396 | 601 | if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) |
397 | 55 | return CD; |
398 | 546 | if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) |
399 | 6 | return ICD->getCategoryDecl(); |
400 | 540 | return nullptr; |
401 | 546 | } |
402 | | |
403 | 410 | void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { |
404 | 410 | const DeclContext *container = D->getDeclContext(); |
405 | 410 | if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { |
406 | 10 | Visit(pd); |
407 | 10 | } |
408 | 400 | else { |
409 | | // The USR for a method declared in a class extension or category is based on |
410 | | // the ObjCInterfaceDecl, not the ObjCCategoryDecl. |
411 | 400 | const ObjCInterfaceDecl *ID = D->getClassInterface(); |
412 | 400 | if (!ID) { |
413 | 1 | IgnoreResults = true; |
414 | 1 | return; |
415 | 1 | } |
416 | 399 | auto *CD = getCategoryContext(D); |
417 | 399 | VisitObjCContainerDecl(ID, CD); |
418 | 399 | } |
419 | | // Ideally we would use 'GenObjCMethod', but this is such a hot path |
420 | | // for Objective-C code that we don't want to use |
421 | | // DeclarationName::getAsString(). |
422 | 409 | Out << (D->isInstanceMethod() ? "(im)"356 : "(cm)"53 ) |
423 | 409 | << DeclarationName(D->getSelector()); |
424 | 409 | } |
425 | | |
426 | | void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D, |
427 | 1.49k | const ObjCCategoryDecl *CatD) { |
428 | 1.49k | switch (D->getKind()) { |
429 | 0 | default: |
430 | 0 | llvm_unreachable("Invalid ObjC container."); |
431 | 1.17k | case Decl::ObjCInterface: |
432 | 1.29k | case Decl::ObjCImplementation: |
433 | 1.29k | GenObjCClass(D->getName(), GetExternalSourceContainer(D), |
434 | 1.29k | GetExternalSourceContainer(CatD)); |
435 | 1.29k | break; |
436 | 41 | case Decl::ObjCCategory: { |
437 | 41 | const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); |
438 | 41 | const ObjCInterfaceDecl *ID = CD->getClassInterface(); |
439 | 41 | if (!ID) { |
440 | | // Handle invalid code where the @interface might not |
441 | | // have been specified. |
442 | | // FIXME: We should be able to generate this USR even if the |
443 | | // @interface isn't available. |
444 | 1 | IgnoreResults = true; |
445 | 1 | return; |
446 | 1 | } |
447 | | // Specially handle class extensions, which are anonymous categories. |
448 | | // We want to mangle in the location to uniquely distinguish them. |
449 | 40 | if (CD->IsClassExtension()) { |
450 | 6 | Out << "objc(ext)" << ID->getName() << '@'; |
451 | 6 | GenLoc(CD, /*IncludeOffset=*/true); |
452 | 6 | } |
453 | 34 | else |
454 | 34 | GenObjCCategory(ID->getName(), CD->getName(), |
455 | 34 | GetExternalSourceContainer(ID), |
456 | 34 | GetExternalSourceContainer(CD)); |
457 | | |
458 | 40 | break; |
459 | 41 | } |
460 | 9 | case Decl::ObjCCategoryImpl: { |
461 | 9 | const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); |
462 | 9 | const ObjCInterfaceDecl *ID = CD->getClassInterface(); |
463 | 9 | if (!ID) { |
464 | | // Handle invalid code where the @interface might not |
465 | | // have been specified. |
466 | | // FIXME: We should be able to generate this USR even if the |
467 | | // @interface isn't available. |
468 | 0 | IgnoreResults = true; |
469 | 0 | return; |
470 | 0 | } |
471 | 9 | GenObjCCategory(ID->getName(), CD->getName(), |
472 | 9 | GetExternalSourceContainer(ID), |
473 | 9 | GetExternalSourceContainer(CD)); |
474 | 9 | break; |
475 | 9 | } |
476 | 152 | case Decl::ObjCProtocol: { |
477 | 152 | const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D); |
478 | 152 | GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD)); |
479 | 152 | break; |
480 | 9 | } |
481 | 1.49k | } |
482 | 1.49k | } |
483 | | |
484 | 219 | void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { |
485 | | // The USR for a property declared in a class extension or category is based |
486 | | // on the ObjCInterfaceDecl, not the ObjCCategoryDecl. |
487 | 219 | if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) |
488 | 202 | VisitObjCContainerDecl(ID, getCategoryContext(D)); |
489 | 17 | else |
490 | 17 | Visit(cast<Decl>(D->getDeclContext())); |
491 | 219 | GenObjCProperty(D->getName(), D->isClassProperty()); |
492 | 219 | } |
493 | | |
494 | 1 | void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { |
495 | 1 | if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { |
496 | 1 | VisitObjCPropertyDecl(PD); |
497 | 1 | return; |
498 | 1 | } |
499 | | |
500 | 0 | IgnoreResults = true; |
501 | 0 | } |
502 | | |
503 | 13.9k | void USRGenerator::VisitTagDecl(const TagDecl *D) { |
504 | | // Add the location of the tag decl to handle resolution across |
505 | | // translation units. |
506 | 13.9k | if (!isa<EnumDecl>(D) && |
507 | 13.9k | ShouldGenerateLocation(D)12.4k && GenLoc(D, /*IncludeOffset=*/isLocal(D))45 ) |
508 | 0 | return; |
509 | | |
510 | 13.9k | GenExtSymbolContainer(D); |
511 | | |
512 | 13.9k | D = D->getCanonicalDecl(); |
513 | 13.9k | VisitDeclContext(D->getDeclContext()); |
514 | | |
515 | 13.9k | bool AlreadyStarted = false; |
516 | 13.9k | if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { |
517 | 12.2k | if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { |
518 | 2.31k | AlreadyStarted = true; |
519 | | |
520 | 2.31k | switch (D->getTagKind()) { |
521 | 0 | case TTK_Interface: |
522 | 912 | case TTK_Class: |
523 | 2.31k | case TTK_Struct: Out << "@ST"; break; |
524 | 0 | case TTK_Union: Out << "@UT"; break; |
525 | 0 | case TTK_Enum: llvm_unreachable("enum template"); |
526 | 2.31k | } |
527 | 2.31k | VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); |
528 | 9.97k | } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec |
529 | 9.97k | = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { |
530 | 52 | AlreadyStarted = true; |
531 | | |
532 | 52 | switch (D->getTagKind()) { |
533 | 0 | case TTK_Interface: |
534 | 35 | case TTK_Class: |
535 | 52 | case TTK_Struct: Out << "@SP"; break; |
536 | 0 | case TTK_Union: Out << "@UP"; break; |
537 | 0 | case TTK_Enum: llvm_unreachable("enum partial specialization"); |
538 | 52 | } |
539 | 52 | VisitTemplateParameterList(PartialSpec->getTemplateParameters()); |
540 | 52 | } |
541 | 12.2k | } |
542 | | |
543 | 13.9k | if (!AlreadyStarted) { |
544 | 11.5k | switch (D->getTagKind()) { |
545 | 0 | case TTK_Interface: |
546 | 4.62k | case TTK_Class: |
547 | 10.0k | case TTK_Struct: Out << "@S"; break; |
548 | 18 | case TTK_Union: Out << "@U"; break; |
549 | 1.45k | case TTK_Enum: Out << "@E"; break; |
550 | 11.5k | } |
551 | 11.5k | } |
552 | | |
553 | 13.9k | Out << '@'; |
554 | 13.9k | assert(Buf.size() > 0); |
555 | 13.9k | const unsigned off = Buf.size() - 1; |
556 | | |
557 | 13.9k | if (EmitDeclName(D)) { |
558 | 155 | if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { |
559 | 46 | Buf[off] = 'A'; |
560 | 46 | Out << '@' << *TD; |
561 | 109 | } else { |
562 | 109 | if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()41 ) { |
563 | 31 | printLoc(Out, D->getLocation(), Context->getSourceManager(), true); |
564 | 78 | } else { |
565 | 78 | Buf[off] = 'a'; |
566 | 78 | if (auto *ED = dyn_cast<EnumDecl>(D)) { |
567 | | // Distinguish USRs of anonymous enums by using their first |
568 | | // enumerator. |
569 | 32 | auto enum_range = ED->enumerators(); |
570 | 32 | if (enum_range.begin() != enum_range.end()) { |
571 | 32 | Out << '@' << **enum_range.begin(); |
572 | 32 | } |
573 | 32 | } |
574 | 78 | } |
575 | 109 | } |
576 | 155 | } |
577 | | |
578 | | // For a class template specialization, mangle the template arguments. |
579 | 13.9k | if (const ClassTemplateSpecializationDecl *Spec |
580 | 13.9k | = dyn_cast<ClassTemplateSpecializationDecl>(D)) { |
581 | 690 | const TemplateArgumentList &Args = Spec->getTemplateArgs(); |
582 | 690 | Out << '>'; |
583 | 1.54k | for (unsigned I = 0, N = Args.size(); I != N; ++I858 ) { |
584 | 858 | Out << '#'; |
585 | 858 | VisitTemplateArgument(Args.get(I)); |
586 | 858 | } |
587 | 690 | } |
588 | 13.9k | } |
589 | | |
590 | 543 | void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { |
591 | 543 | if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))462 ) |
592 | 0 | return; |
593 | 543 | const DeclContext *DC = D->getDeclContext(); |
594 | 543 | if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) |
595 | 314 | Visit(DCN); |
596 | 543 | Out << "@T@"; |
597 | 543 | Out << D->getName(); |
598 | 543 | } |
599 | | |
600 | 602 | void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { |
601 | 602 | GenLoc(D, /*IncludeOffset=*/true); |
602 | 602 | } |
603 | | |
604 | 17.8k | void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) { |
605 | 17.8k | StringRef Container = GetExternalSourceContainer(D); |
606 | 17.8k | if (!Container.empty()) |
607 | 3 | Out << "@M@" << Container; |
608 | 17.8k | } |
609 | | |
610 | 2.25k | bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { |
611 | 2.25k | if (generatedLoc) |
612 | 14 | return IgnoreResults; |
613 | 2.24k | generatedLoc = true; |
614 | | |
615 | | // Guard against null declarations in invalid code. |
616 | 2.24k | if (!D) { |
617 | 0 | IgnoreResults = true; |
618 | 0 | return true; |
619 | 0 | } |
620 | | |
621 | | // Use the location of canonical decl. |
622 | 2.24k | D = D->getCanonicalDecl(); |
623 | | |
624 | 2.24k | IgnoreResults = |
625 | 2.24k | IgnoreResults || printLoc(Out, D->getBeginLoc(), |
626 | 2.24k | Context->getSourceManager(), IncludeOffset); |
627 | | |
628 | 2.24k | return IgnoreResults; |
629 | 2.24k | } |
630 | | |
631 | 13 | static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) { |
632 | | // FIXME: Encode the qualifier, don't just print it. |
633 | 13 | PrintingPolicy PO(Ctx.getLangOpts()); |
634 | 13 | PO.SuppressTagKeyword = true; |
635 | 13 | PO.SuppressUnwrittenScope = true; |
636 | 13 | PO.ConstantArraySizeAsWritten = false; |
637 | 13 | PO.AnonymousTagLocations = false; |
638 | 13 | NNS->print(Out, PO); |
639 | 13 | } |
640 | | |
641 | 4.67k | void USRGenerator::VisitType(QualType T) { |
642 | | // This method mangles in USR information for types. It can possibly |
643 | | // just reuse the naming-mangling logic used by codegen, although the |
644 | | // requirements for USRs might not be the same. |
645 | 4.67k | ASTContext &Ctx = *Context; |
646 | | |
647 | 5.46k | do { |
648 | 5.46k | T = Ctx.getCanonicalType(T); |
649 | 5.46k | Qualifiers Q = T.getQualifiers(); |
650 | 5.46k | unsigned qVal = 0; |
651 | 5.46k | if (Q.hasConst()) |
652 | 353 | qVal |= 0x1; |
653 | 5.46k | if (Q.hasVolatile()) |
654 | 0 | qVal |= 0x2; |
655 | 5.46k | if (Q.hasRestrict()) |
656 | 0 | qVal |= 0x4; |
657 | 5.46k | if(qVal) |
658 | 353 | Out << ((char) ('0' + qVal)); |
659 | | |
660 | | // Mangle in ObjC GC qualifiers? |
661 | | |
662 | 5.46k | if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { |
663 | 9 | Out << 'P'; |
664 | 9 | T = Expansion->getPattern(); |
665 | 9 | } |
666 | | |
667 | 5.46k | if (const BuiltinType *BT = T->getAs<BuiltinType>()) { |
668 | 3.08k | switch (BT->getKind()) { |
669 | 547 | case BuiltinType::Void: |
670 | 547 | Out << 'v'; break; |
671 | 103 | case BuiltinType::Bool: |
672 | 103 | Out << 'b'; break; |
673 | 3 | case BuiltinType::UChar: |
674 | 3 | Out << 'c'; break; |
675 | 0 | case BuiltinType::Char8: |
676 | 0 | Out << 'u'; break; |
677 | 0 | case BuiltinType::Char16: |
678 | 0 | Out << 'q'; break; |
679 | 0 | case BuiltinType::Char32: |
680 | 0 | Out << 'w'; break; |
681 | 0 | case BuiltinType::UShort: |
682 | 0 | Out << 's'; break; |
683 | 24 | case BuiltinType::UInt: |
684 | 24 | Out << 'i'; break; |
685 | 4 | case BuiltinType::ULong: |
686 | 4 | Out << 'l'; break; |
687 | 4 | case BuiltinType::ULongLong: |
688 | 4 | Out << 'k'; break; |
689 | 0 | case BuiltinType::UInt128: |
690 | 0 | Out << 'j'; break; |
691 | 0 | case BuiltinType::Char_U: |
692 | 64 | case BuiltinType::Char_S: |
693 | 64 | Out << 'C'; break; |
694 | 2 | case BuiltinType::SChar: |
695 | 2 | Out << 'r'; break; |
696 | 0 | case BuiltinType::WChar_S: |
697 | 0 | case BuiltinType::WChar_U: |
698 | 0 | Out << 'W'; break; |
699 | 0 | case BuiltinType::Short: |
700 | 0 | Out << 'S'; break; |
701 | 2.10k | case BuiltinType::Int: |
702 | 2.10k | Out << 'I'; break; |
703 | 1 | case BuiltinType::Long: |
704 | 1 | Out << 'L'; break; |
705 | 0 | case BuiltinType::LongLong: |
706 | 0 | Out << 'K'; break; |
707 | 0 | case BuiltinType::Int128: |
708 | 0 | Out << 'J'; break; |
709 | 0 | case BuiltinType::Float16: |
710 | 0 | case BuiltinType::Half: |
711 | 0 | Out << 'h'; break; |
712 | 63 | case BuiltinType::Float: |
713 | 63 | Out << 'f'; break; |
714 | 121 | case BuiltinType::Double: |
715 | 121 | Out << 'd'; break; |
716 | 0 | case BuiltinType::LongDouble: |
717 | 0 | Out << 'D'; break; |
718 | 0 | case BuiltinType::Float128: |
719 | 0 | Out << 'Q'; break; |
720 | 0 | case BuiltinType::NullPtr: |
721 | 0 | Out << 'n'; break; |
722 | 0 | #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ |
723 | 1 | case BuiltinType::Id: \ |
724 | 1 | Out << "@BT@" << #Suffix << "_" << #ImgType; break; |
725 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
726 | 0 | #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ |
727 | 1 | case BuiltinType::Id: \ |
728 | 1 | Out << "@BT@" << #ExtType; break; |
729 | 0 | #include "clang/Basic/OpenCLExtensionTypes.def" |
730 | 0 | case BuiltinType::OCLEvent: |
731 | 0 | Out << "@BT@OCLEvent"; break; |
732 | 0 | case BuiltinType::OCLClkEvent: |
733 | 0 | Out << "@BT@OCLClkEvent"; break; |
734 | 0 | case BuiltinType::OCLQueue: |
735 | 0 | Out << "@BT@OCLQueue"; break; |
736 | 0 | case BuiltinType::OCLReserveID: |
737 | 0 | Out << "@BT@OCLReserveID"; break; |
738 | 0 | case BuiltinType::OCLSampler: |
739 | 0 | Out << "@BT@OCLSampler"; break; |
740 | 0 | #define SVE_TYPE(Name, Id, SingletonId) \ |
741 | 1 | case BuiltinType::Id: \ |
742 | 1 | Out << "@BT@" << Name; break; |
743 | 0 | #include "clang/Basic/AArch64SVEACLETypes.def" |
744 | 0 | #define PPC_VECTOR_TYPE(Name, Id, Size) \ |
745 | 1 | case BuiltinType::Id: \ |
746 | 1 | Out << "@BT@" << #Name; break; |
747 | 0 | #include "clang/Basic/PPCTypes.def" |
748 | 0 | #define RVV_TYPE(Name, Id, SingletonId) \ |
749 | 1 | case BuiltinType::Id: \ |
750 | 1 | Out << "@BT@" << Name; break; |
751 | 0 | #include "clang/Basic/RISCVVTypes.def" |
752 | 0 | #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: |
753 | 0 | #include "clang/Basic/WebAssemblyReferenceTypes.def" |
754 | 0 | case BuiltinType::ShortAccum: |
755 | 0 | Out << "@BT@ShortAccum"; break; |
756 | 1 | case BuiltinType::Accum: |
757 | 1 | Out << "@BT@Accum"; break; |
758 | 0 | case BuiltinType::LongAccum: |
759 | 0 | Out << "@BT@LongAccum"; break; |
760 | 0 | case BuiltinType::UShortAccum: |
761 | 0 | Out << "@BT@UShortAccum"; break; |
762 | 0 | case BuiltinType::UAccum: |
763 | 0 | Out << "@BT@UAccum"; break; |
764 | 0 | case BuiltinType::ULongAccum: |
765 | 0 | Out << "@BT@ULongAccum"; break; |
766 | 0 | case BuiltinType::ShortFract: |
767 | 0 | Out << "@BT@ShortFract"; break; |
768 | 0 | case BuiltinType::Fract: |
769 | 0 | Out << "@BT@Fract"; break; |
770 | 0 | case BuiltinType::LongFract: |
771 | 0 | Out << "@BT@LongFract"; break; |
772 | 0 | case BuiltinType::UShortFract: |
773 | 0 | Out << "@BT@UShortFract"; break; |
774 | 0 | case BuiltinType::UFract: |
775 | 0 | Out << "@BT@UFract"; break; |
776 | 0 | case BuiltinType::ULongFract: |
777 | 0 | Out << "@BT@ULongFract"; break; |
778 | 0 | case BuiltinType::SatShortAccum: |
779 | 0 | Out << "@BT@SatShortAccum"; break; |
780 | 0 | case BuiltinType::SatAccum: |
781 | 0 | Out << "@BT@SatAccum"; break; |
782 | 0 | case BuiltinType::SatLongAccum: |
783 | 0 | Out << "@BT@SatLongAccum"; break; |
784 | 0 | case BuiltinType::SatUShortAccum: |
785 | 0 | Out << "@BT@SatUShortAccum"; break; |
786 | 0 | case BuiltinType::SatUAccum: |
787 | 0 | Out << "@BT@SatUAccum"; break; |
788 | 0 | case BuiltinType::SatULongAccum: |
789 | 0 | Out << "@BT@SatULongAccum"; break; |
790 | 0 | case BuiltinType::SatShortFract: |
791 | 0 | Out << "@BT@SatShortFract"; break; |
792 | 0 | case BuiltinType::SatFract: |
793 | 0 | Out << "@BT@SatFract"; break; |
794 | 0 | case BuiltinType::SatLongFract: |
795 | 0 | Out << "@BT@SatLongFract"; break; |
796 | 0 | case BuiltinType::SatUShortFract: |
797 | 0 | Out << "@BT@SatUShortFract"; break; |
798 | 0 | case BuiltinType::SatUFract: |
799 | 0 | Out << "@BT@SatUFract"; break; |
800 | 0 | case BuiltinType::SatULongFract: |
801 | 0 | Out << "@BT@SatULongFract"; break; |
802 | 1 | case BuiltinType::BFloat16: |
803 | 1 | Out << "@BT@__bf16"; break; |
804 | 1 | case BuiltinType::Ibm128: |
805 | 1 | Out << "@BT@__ibm128"; break; |
806 | 29 | case BuiltinType::ObjCId: |
807 | 29 | Out << 'o'; break; |
808 | 0 | case BuiltinType::ObjCClass: |
809 | 0 | Out << 'O'; break; |
810 | 0 | case BuiltinType::ObjCSel: |
811 | 0 | Out << 'e'; break; |
812 | 0 | #define BUILTIN_TYPE(Id, SingletonId) |
813 | 0 | #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: |
814 | 0 | #include "clang/AST/BuiltinTypes.def" |
815 | 0 | case BuiltinType::Dependent: |
816 | | // If you're adding a new builtin type, please add its name prefixed |
817 | | // with "@BT@" to `Out` (see cases above). |
818 | 0 | IgnoreResults = true; |
819 | 0 | break; |
820 | 3.08k | } |
821 | 3.08k | return; |
822 | 3.08k | } |
823 | | |
824 | | // If we have already seen this (non-built-in) type, use a substitution |
825 | | // encoding. |
826 | 2.38k | llvm::DenseMap<const Type *, unsigned>::iterator Substitution |
827 | 2.38k | = TypeSubstitutions.find(T.getTypePtr()); |
828 | 2.38k | if (Substitution != TypeSubstitutions.end()) { |
829 | 172 | Out << 'S' << Substitution->second << '_'; |
830 | 172 | return; |
831 | 2.21k | } else { |
832 | | // Record this as a substitution. |
833 | 2.21k | unsigned Number = TypeSubstitutions.size(); |
834 | 2.21k | TypeSubstitutions[T.getTypePtr()] = Number; |
835 | 2.21k | } |
836 | | |
837 | 2.21k | if (const PointerType *PT = T->getAs<PointerType>()) { |
838 | 225 | Out << '*'; |
839 | 225 | T = PT->getPointeeType(); |
840 | 225 | continue; |
841 | 225 | } |
842 | 1.98k | if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { |
843 | 5 | Out << '*'; |
844 | 5 | T = OPT->getPointeeType(); |
845 | 5 | continue; |
846 | 5 | } |
847 | 1.98k | if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { |
848 | 79 | Out << "&&"; |
849 | 79 | T = RT->getPointeeType(); |
850 | 79 | continue; |
851 | 79 | } |
852 | 1.90k | if (const ReferenceType *RT = T->getAs<ReferenceType>()) { |
853 | 473 | Out << '&'; |
854 | 473 | T = RT->getPointeeType(); |
855 | 473 | continue; |
856 | 473 | } |
857 | 1.43k | if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { |
858 | 59 | Out << 'F'; |
859 | 59 | VisitType(FT->getReturnType()); |
860 | 59 | Out << '('; |
861 | 59 | for (const auto &I : FT->param_types()) { |
862 | 42 | Out << '#'; |
863 | 42 | VisitType(I); |
864 | 42 | } |
865 | 59 | Out << ')'; |
866 | 59 | if (FT->isVariadic()) |
867 | 0 | Out << '.'; |
868 | 59 | return; |
869 | 59 | } |
870 | 1.37k | if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { |
871 | 0 | Out << 'B'; |
872 | 0 | T = BT->getPointeeType(); |
873 | 0 | continue; |
874 | 0 | } |
875 | 1.37k | if (const ComplexType *CT = T->getAs<ComplexType>()) { |
876 | 0 | Out << '<'; |
877 | 0 | T = CT->getElementType(); |
878 | 0 | continue; |
879 | 0 | } |
880 | 1.37k | if (const TagType *TT = T->getAs<TagType>()) { |
881 | 557 | Out << '$'; |
882 | 557 | VisitTagDecl(TT->getDecl()); |
883 | 557 | return; |
884 | 557 | } |
885 | 814 | if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { |
886 | 2 | Out << '$'; |
887 | 2 | VisitObjCInterfaceDecl(OIT->getDecl()); |
888 | 2 | return; |
889 | 2 | } |
890 | 812 | if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) { |
891 | 29 | Out << 'Q'; |
892 | 29 | VisitType(OIT->getBaseType()); |
893 | 29 | for (auto *Prot : OIT->getProtocols()) |
894 | 32 | VisitObjCProtocolDecl(Prot); |
895 | 29 | return; |
896 | 29 | } |
897 | 783 | if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { |
898 | 712 | Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); |
899 | 712 | return; |
900 | 712 | } |
901 | 71 | if (const TemplateSpecializationType *Spec |
902 | 71 | = T->getAs<TemplateSpecializationType>()) { |
903 | 56 | Out << '>'; |
904 | 56 | VisitTemplateName(Spec->getTemplateName()); |
905 | 56 | Out << Spec->template_arguments().size(); |
906 | 56 | for (const auto &Arg : Spec->template_arguments()) |
907 | 96 | VisitTemplateArgument(Arg); |
908 | 56 | return; |
909 | 56 | } |
910 | 15 | if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { |
911 | 2 | Out << '^'; |
912 | 2 | printQualifier(Out, Ctx, DNT->getQualifier()); |
913 | 2 | Out << ':' << DNT->getIdentifier()->getName(); |
914 | 2 | return; |
915 | 2 | } |
916 | 13 | if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) { |
917 | 6 | T = InjT->getInjectedSpecializationType(); |
918 | 6 | continue; |
919 | 6 | } |
920 | 7 | if (const auto *VT = T->getAs<VectorType>()) { |
921 | 4 | Out << (T->isExtVectorType() ? ']'2 : '['2 ); |
922 | 4 | Out << VT->getNumElements(); |
923 | 4 | T = VT->getElementType(); |
924 | 4 | continue; |
925 | 4 | } |
926 | 3 | if (const auto *const AT = dyn_cast<ArrayType>(T)) { |
927 | 3 | Out << '{'; |
928 | 3 | switch (AT->getSizeModifier()) { |
929 | 0 | case ArrayType::Static: |
930 | 0 | Out << 's'; |
931 | 0 | break; |
932 | 0 | case ArrayType::Star: |
933 | 0 | Out << '*'; |
934 | 0 | break; |
935 | 3 | case ArrayType::Normal: |
936 | 3 | Out << 'n'; |
937 | 3 | break; |
938 | 3 | } |
939 | 3 | if (const auto *const CAT = dyn_cast<ConstantArrayType>(T)) |
940 | 3 | Out << CAT->getSize(); |
941 | | |
942 | 3 | T = AT->getElementType(); |
943 | 3 | continue; |
944 | 3 | } |
945 | | |
946 | | // Unhandled type. |
947 | 0 | Out << ' '; |
948 | 0 | break; |
949 | 795 | } while (true); |
950 | 4.67k | } |
951 | | |
952 | | void USRGenerator::VisitTemplateParameterList( |
953 | 2.91k | const TemplateParameterList *Params) { |
954 | 2.91k | if (!Params) |
955 | 0 | return; |
956 | 2.91k | Out << '>' << Params->size(); |
957 | 2.91k | for (TemplateParameterList::const_iterator P = Params->begin(), |
958 | 2.91k | PEnd = Params->end(); |
959 | 6.34k | P != PEnd; ++P3.43k ) { |
960 | 3.43k | Out << '#'; |
961 | 3.43k | if (isa<TemplateTypeParmDecl>(*P)) { |
962 | 3.27k | if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) |
963 | 38 | Out<< 'p'; |
964 | 3.27k | Out << 'T'; |
965 | 3.27k | continue; |
966 | 3.27k | } |
967 | | |
968 | 151 | if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { |
969 | 85 | if (NTTP->isParameterPack()) |
970 | 0 | Out << 'p'; |
971 | 85 | Out << 'N'; |
972 | 85 | VisitType(NTTP->getType()); |
973 | 85 | continue; |
974 | 85 | } |
975 | | |
976 | 66 | TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); |
977 | 66 | if (TTP->isParameterPack()) |
978 | 0 | Out << 'p'; |
979 | 66 | Out << 't'; |
980 | 66 | VisitTemplateParameterList(TTP->getTemplateParameters()); |
981 | 66 | } |
982 | 2.91k | } |
983 | | |
984 | 56 | void USRGenerator::VisitTemplateName(TemplateName Name) { |
985 | 56 | if (TemplateDecl *Template = Name.getAsTemplateDecl()) { |
986 | 56 | if (TemplateTemplateParmDecl *TTP |
987 | 56 | = dyn_cast<TemplateTemplateParmDecl>(Template)) { |
988 | 3 | Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); |
989 | 3 | return; |
990 | 3 | } |
991 | | |
992 | 53 | Visit(Template); |
993 | 53 | return; |
994 | 56 | } |
995 | | |
996 | | // FIXME: Visit dependent template names. |
997 | 56 | } |
998 | | |
999 | 1.12k | void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { |
1000 | 1.12k | switch (Arg.getKind()) { |
1001 | 0 | case TemplateArgument::Null: |
1002 | 0 | break; |
1003 | | |
1004 | 4 | case TemplateArgument::Declaration: |
1005 | 4 | Visit(Arg.getAsDecl()); |
1006 | 4 | break; |
1007 | | |
1008 | 0 | case TemplateArgument::NullPtr: |
1009 | 0 | break; |
1010 | | |
1011 | 0 | case TemplateArgument::TemplateExpansion: |
1012 | 0 | Out << 'P'; // pack expansion of... |
1013 | 0 | [[fallthrough]]; |
1014 | 0 | case TemplateArgument::Template: |
1015 | 0 | VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); |
1016 | 0 | break; |
1017 | | |
1018 | 2 | case TemplateArgument::Expression: |
1019 | | // FIXME: Visit expressions. |
1020 | 2 | break; |
1021 | | |
1022 | 2 | case TemplateArgument::Pack: |
1023 | 2 | Out << 'p' << Arg.pack_size(); |
1024 | 2 | for (const auto &P : Arg.pack_elements()) |
1025 | 6 | VisitTemplateArgument(P); |
1026 | 2 | break; |
1027 | | |
1028 | 1.05k | case TemplateArgument::Type: |
1029 | 1.05k | VisitType(Arg.getAsType()); |
1030 | 1.05k | break; |
1031 | | |
1032 | 64 | case TemplateArgument::Integral: |
1033 | 64 | Out << 'V'; |
1034 | 64 | VisitType(Arg.getIntegralType()); |
1035 | 64 | Out << Arg.getAsIntegral(); |
1036 | 64 | break; |
1037 | 1.12k | } |
1038 | 1.12k | } |
1039 | | |
1040 | 8 | void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { |
1041 | 8 | if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) |
1042 | 0 | return; |
1043 | 8 | VisitDeclContext(D->getDeclContext()); |
1044 | 8 | Out << "@UUV@"; |
1045 | 8 | printQualifier(Out, D->getASTContext(), D->getQualifier()); |
1046 | 8 | EmitDeclName(D); |
1047 | 8 | } |
1048 | | |
1049 | 3 | void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { |
1050 | 3 | if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) |
1051 | 0 | return; |
1052 | 3 | VisitDeclContext(D->getDeclContext()); |
1053 | 3 | Out << "@UUT@"; |
1054 | 3 | printQualifier(Out, D->getASTContext(), D->getQualifier()); |
1055 | 3 | Out << D->getName(); // Simple name. |
1056 | 3 | } |
1057 | | |
1058 | 3 | void USRGenerator::VisitConceptDecl(const ConceptDecl *D) { |
1059 | 3 | if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))0 ) |
1060 | 0 | return; |
1061 | 3 | VisitDeclContext(D->getDeclContext()); |
1062 | 3 | Out << "@CT@"; |
1063 | 3 | EmitDeclName(D); |
1064 | 3 | } |
1065 | | |
1066 | 1 | void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) { |
1067 | 1 | VisitDeclContext(D->getDeclContext()); |
1068 | 1 | Out << "@MG@"; |
1069 | 1 | D->NamedDecl::printName(Out); |
1070 | 1 | } |
1071 | | |
1072 | | //===----------------------------------------------------------------------===// |
1073 | | // USR generation functions. |
1074 | | //===----------------------------------------------------------------------===// |
1075 | | |
1076 | | static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn, |
1077 | | StringRef CatSymDefinedIn, |
1078 | 1.33k | raw_ostream &OS) { |
1079 | 1.33k | if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty()1.29k ) |
1080 | 1.29k | return; |
1081 | 40 | if (CatSymDefinedIn.empty()) { |
1082 | 26 | OS << "@M@" << ClsSymDefinedIn << '@'; |
1083 | 26 | return; |
1084 | 26 | } |
1085 | 14 | OS << "@CM@" << CatSymDefinedIn << '@'; |
1086 | 14 | if (ClsSymDefinedIn != CatSymDefinedIn) { |
1087 | 13 | OS << ClsSymDefinedIn << '@'; |
1088 | 13 | } |
1089 | 14 | } |
1090 | | |
1091 | | void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, |
1092 | | StringRef ExtSymDefinedIn, |
1093 | 1.29k | StringRef CategoryContextExtSymbolDefinedIn) { |
1094 | 1.29k | combineClassAndCategoryExtContainers(ExtSymDefinedIn, |
1095 | 1.29k | CategoryContextExtSymbolDefinedIn, OS); |
1096 | 1.29k | OS << "objc(cs)" << Cls; |
1097 | 1.29k | } |
1098 | | |
1099 | | void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, |
1100 | | raw_ostream &OS, |
1101 | | StringRef ClsSymDefinedIn, |
1102 | 44 | StringRef CatSymDefinedIn) { |
1103 | 44 | combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS); |
1104 | 44 | OS << "objc(cy)" << Cls << '@' << Cat; |
1105 | 44 | } |
1106 | | |
1107 | 1 | void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) { |
1108 | 1 | OS << '@' << Ivar; |
1109 | 1 | } |
1110 | | |
1111 | | void clang::index::generateUSRForObjCMethod(StringRef Sel, |
1112 | | bool IsInstanceMethod, |
1113 | 2 | raw_ostream &OS) { |
1114 | 2 | OS << (IsInstanceMethod ? "(im)"1 : "(cm)"1 ) << Sel; |
1115 | 2 | } |
1116 | | |
1117 | | void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp, |
1118 | 220 | raw_ostream &OS) { |
1119 | 220 | OS << (isClassProp ? "(cpy)"14 : "(py)"206 ) << Prop; |
1120 | 220 | } |
1121 | | |
1122 | | void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, |
1123 | 153 | StringRef ExtSymDefinedIn) { |
1124 | 153 | if (!ExtSymDefinedIn.empty()) |
1125 | 4 | OS << "@M@" << ExtSymDefinedIn << '@'; |
1126 | 153 | OS << "objc(pl)" << Prot; |
1127 | 153 | } |
1128 | | |
1129 | | void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, |
1130 | 0 | StringRef ExtSymDefinedIn) { |
1131 | 0 | if (!ExtSymDefinedIn.empty()) |
1132 | 0 | OS << "@M@" << ExtSymDefinedIn; |
1133 | 0 | OS << "@E@" << EnumName; |
1134 | 0 | } |
1135 | | |
1136 | | void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName, |
1137 | 0 | raw_ostream &OS) { |
1138 | 0 | OS << '@' << EnumConstantName; |
1139 | 0 | } |
1140 | | |
1141 | | bool clang::index::generateUSRForDecl(const Decl *D, |
1142 | 20.5k | SmallVectorImpl<char> &Buf) { |
1143 | 20.5k | if (!D) |
1144 | 4 | return true; |
1145 | | // We don't ignore decls with invalid source locations. Implicit decls, like |
1146 | | // C++'s operator new function, can have invalid locations but it is fine to |
1147 | | // create USRs that can identify them. |
1148 | | |
1149 | | // Check if the declaration has explicit external USR specified. |
1150 | 20.5k | auto *CD = D->getCanonicalDecl(); |
1151 | 20.5k | if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) { |
1152 | 25 | if (!ExternalSymAttr->getUSR().empty()) { |
1153 | 9 | llvm::raw_svector_ostream Out(Buf); |
1154 | 9 | Out << ExternalSymAttr->getUSR(); |
1155 | 9 | return false; |
1156 | 9 | } |
1157 | 25 | } |
1158 | 20.5k | USRGenerator UG(&D->getASTContext(), Buf); |
1159 | 20.5k | UG.Visit(D); |
1160 | 20.5k | return UG.ignoreResults(); |
1161 | 20.5k | } |
1162 | | |
1163 | | bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD, |
1164 | | const SourceManager &SM, |
1165 | 3.06k | SmallVectorImpl<char> &Buf) { |
1166 | 3.06k | if (!MD) |
1167 | 0 | return true; |
1168 | 3.06k | return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(), |
1169 | 3.06k | SM, Buf); |
1170 | | |
1171 | 3.06k | } |
1172 | | |
1173 | | bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc, |
1174 | | const SourceManager &SM, |
1175 | 24.0k | SmallVectorImpl<char> &Buf) { |
1176 | 24.0k | if (MacroName.empty()) |
1177 | 0 | return true; |
1178 | | |
1179 | 24.0k | llvm::raw_svector_ostream Out(Buf); |
1180 | | |
1181 | | // Assume that system headers are sane. Don't put source location |
1182 | | // information into the USR if the macro comes from a system header. |
1183 | 24.0k | bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc)24.0k ; |
1184 | | |
1185 | 24.0k | Out << getUSRSpacePrefix(); |
1186 | 24.0k | if (ShouldGenerateLocation) |
1187 | 187 | printLoc(Out, Loc, SM, /*IncludeOffset=*/true); |
1188 | 24.0k | Out << "@macro@"; |
1189 | 24.0k | Out << MacroName; |
1190 | 24.0k | return false; |
1191 | 24.0k | } |
1192 | | |
1193 | | bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx, |
1194 | 342 | SmallVectorImpl<char> &Buf) { |
1195 | 342 | if (T.isNull()) |
1196 | 0 | return true; |
1197 | 342 | T = T.getCanonicalType(); |
1198 | | |
1199 | 342 | USRGenerator UG(&Ctx, Buf); |
1200 | 342 | UG.VisitType(T); |
1201 | 342 | return UG.ignoreResults(); |
1202 | 342 | } |
1203 | | |
1204 | | bool clang::index::generateFullUSRForModule(const Module *Mod, |
1205 | 17 | raw_ostream &OS) { |
1206 | 17 | if (!Mod->Parent) |
1207 | 9 | return generateFullUSRForTopLevelModuleName(Mod->Name, OS); |
1208 | 8 | if (generateFullUSRForModule(Mod->Parent, OS)) |
1209 | 0 | return true; |
1210 | 8 | return generateUSRFragmentForModule(Mod, OS); |
1211 | 8 | } |
1212 | | |
1213 | | bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName, |
1214 | 9 | raw_ostream &OS) { |
1215 | 9 | OS << getUSRSpacePrefix(); |
1216 | 9 | return generateUSRFragmentForModuleName(ModName, OS); |
1217 | 9 | } |
1218 | | |
1219 | | bool clang::index::generateUSRFragmentForModule(const Module *Mod, |
1220 | 8 | raw_ostream &OS) { |
1221 | 8 | return generateUSRFragmentForModuleName(Mod->Name, OS); |
1222 | 8 | } |
1223 | | |
1224 | | bool clang::index::generateUSRFragmentForModuleName(StringRef ModName, |
1225 | 17 | raw_ostream &OS) { |
1226 | 17 | OS << "@M@" << ModName; |
1227 | 17 | return false; |
1228 | 17 | } |