1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "clang/Index/USRGeneration.h" |
10 | #include "clang/AST/ASTContext.h" |
11 | #include "clang/AST/DeclTemplate.h" |
12 | #include "clang/AST/DeclVisitor.h" |
13 | #include "clang/Lex/PreprocessingRecord.h" |
14 | #include "llvm/Support/Path.h" |
15 | #include "llvm/Support/raw_ostream.h" |
16 | |
17 | using namespace clang; |
18 | using namespace clang::index; |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, |
26 | const SourceManager &SM, bool IncludeOffset) { |
27 | if (Loc.isInvalid()) { |
28 | return true; |
29 | } |
30 | Loc = SM.getExpansionLoc(Loc); |
31 | const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc); |
32 | const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); |
33 | if (FE) { |
34 | OS << llvm::sys::path::filename(FE->getName()); |
35 | } else { |
36 | |
37 | return true; |
38 | } |
39 | if (IncludeOffset) { |
40 | |
41 | |
42 | |
43 | OS << '@' << Decomposed.second; |
44 | } |
45 | return false; |
46 | } |
47 | |
48 | static StringRef GetExternalSourceContainer(const NamedDecl *D) { |
49 | if (!D) |
50 | return StringRef(); |
51 | if (auto *attr = D->getExternalSourceSymbolAttr()) { |
52 | return attr->getDefinedIn(); |
53 | } |
54 | return StringRef(); |
55 | } |
56 | |
57 | namespace { |
58 | class USRGenerator : public ConstDeclVisitor<USRGenerator> { |
59 | SmallVectorImpl<char> &Buf; |
60 | llvm::raw_svector_ostream Out; |
61 | bool IgnoreResults; |
62 | ASTContext *Context; |
63 | bool generatedLoc; |
64 | |
65 | llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; |
66 | |
67 | public: |
68 | explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf) |
69 | : Buf(Buf), |
70 | Out(Buf), |
71 | IgnoreResults(false), |
72 | Context(Ctx), |
73 | generatedLoc(false) |
74 | { |
75 | |
76 | Out << getUSRSpacePrefix(); |
77 | } |
78 | |
79 | bool ignoreResults() const { return IgnoreResults; } |
80 | |
81 | |
82 | void VisitDeclContext(const DeclContext *D); |
83 | void VisitFieldDecl(const FieldDecl *D); |
84 | void VisitFunctionDecl(const FunctionDecl *D); |
85 | void VisitNamedDecl(const NamedDecl *D); |
86 | void VisitNamespaceDecl(const NamespaceDecl *D); |
87 | void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); |
88 | void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); |
89 | void VisitClassTemplateDecl(const ClassTemplateDecl *D); |
90 | void VisitObjCContainerDecl(const ObjCContainerDecl *CD, |
91 | const ObjCCategoryDecl *CatD = nullptr); |
92 | void VisitObjCMethodDecl(const ObjCMethodDecl *MD); |
93 | void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); |
94 | void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); |
95 | void VisitTagDecl(const TagDecl *D); |
96 | void VisitTypedefDecl(const TypedefDecl *D); |
97 | void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); |
98 | void VisitVarDecl(const VarDecl *D); |
99 | void VisitBindingDecl(const BindingDecl *D); |
100 | void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); |
101 | void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); |
102 | void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); |
103 | void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); |
104 | |
105 | void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { |
106 | IgnoreResults = true; |
107 | } |
108 | |
109 | void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { |
110 | IgnoreResults = true; |
111 | } |
112 | |
113 | void VisitUsingDecl(const UsingDecl *D) { |
114 | VisitDeclContext(D->getDeclContext()); |
115 | Out << "@UD@"; |
116 | |
117 | bool EmittedDeclName = !EmitDeclName(D); |
118 | (0) . __assert_fail ("EmittedDeclName && \"EmitDeclName can not fail for UsingDecls\"", "/home/seafit/code_projects/clang_source/clang/lib/Index/USRGeneration.cpp", 118, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls"); |
119 | (void)EmittedDeclName; |
120 | } |
121 | |
122 | bool ShouldGenerateLocation(const NamedDecl *D); |
123 | |
124 | bool isLocal(const NamedDecl *D) { |
125 | return D->getParentFunctionOrMethod() != nullptr; |
126 | } |
127 | |
128 | void GenExtSymbolContainer(const NamedDecl *D); |
129 | |
130 | |
131 | |
132 | bool GenLoc(const Decl *D, bool IncludeOffset); |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn, |
142 | StringRef CategoryContextExtSymbolDefinedIn) { |
143 | generateUSRForObjCClass(cls, Out, ExtSymDefinedIn, |
144 | CategoryContextExtSymbolDefinedIn); |
145 | } |
146 | |
147 | |
148 | void GenObjCCategory(StringRef cls, StringRef cat, |
149 | StringRef clsExt, StringRef catExt) { |
150 | generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt); |
151 | } |
152 | |
153 | |
154 | void GenObjCProperty(StringRef prop, bool isClassProp) { |
155 | generateUSRForObjCProperty(prop, isClassProp, Out); |
156 | } |
157 | |
158 | |
159 | void GenObjCProtocol(StringRef prot, StringRef ext) { |
160 | generateUSRForObjCProtocol(prot, Out, ext); |
161 | } |
162 | |
163 | void VisitType(QualType T); |
164 | void VisitTemplateParameterList(const TemplateParameterList *Params); |
165 | void VisitTemplateName(TemplateName Name); |
166 | void VisitTemplateArgument(const TemplateArgument &Arg); |
167 | |
168 | |
169 | |
170 | bool EmitDeclName(const NamedDecl *D); |
171 | }; |
172 | } |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | bool USRGenerator::EmitDeclName(const NamedDecl *D) { |
179 | const unsigned startSize = Buf.size(); |
180 | D->printName(Out); |
181 | const unsigned endSize = Buf.size(); |
182 | return startSize == endSize; |
183 | } |
184 | |
185 | bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) { |
186 | if (D->isExternallyVisible()) |
187 | return false; |
188 | if (D->getParentFunctionOrMethod()) |
189 | return true; |
190 | SourceLocation Loc = D->getLocation(); |
191 | if (Loc.isInvalid()) |
192 | return false; |
193 | const SourceManager &SM = Context->getSourceManager(); |
194 | return !SM.isInSystemHeader(Loc); |
195 | } |
196 | |
197 | void USRGenerator::VisitDeclContext(const DeclContext *DC) { |
198 | if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) |
199 | Visit(D); |
200 | else if (isa<LinkageSpecDecl>(DC)) |
201 | VisitDeclContext(DC->getParent()); |
202 | } |
203 | |
204 | void USRGenerator::VisitFieldDecl(const FieldDecl *D) { |
205 | |
206 | |
207 | if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) |
208 | Visit(ID); |
209 | else |
210 | VisitDeclContext(D->getDeclContext()); |
211 | Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@"); |
212 | if (EmitDeclName(D)) { |
213 | |
214 | IgnoreResults = true; |
215 | return; |
216 | } |
217 | } |
218 | |
219 | void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { |
220 | if (ShouldGenerateLocation(D) && GenLoc(D, (D))) |
221 | return; |
222 | |
223 | const unsigned StartSize = Buf.size(); |
224 | VisitDeclContext(D->getDeclContext()); |
225 | if (Buf.size() == StartSize) |
226 | GenExtSymbolContainer(D); |
227 | |
228 | bool IsTemplate = false; |
229 | if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { |
230 | IsTemplate = true; |
231 | Out << "@FT@"; |
232 | VisitTemplateParameterList(FunTmpl->getTemplateParameters()); |
233 | } else |
234 | Out << "@F@"; |
235 | |
236 | PrintingPolicy Policy(Context->getLangOpts()); |
237 | |
238 | |
239 | Policy.SuppressTemplateArgsInCXXConstructors = true; |
240 | D->getDeclName().print(Out, Policy); |
241 | |
242 | ASTContext &Ctx = *Context; |
243 | if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) && |
244 | !D->hasAttr<OverloadableAttr>()) |
245 | return; |
246 | |
247 | if (const TemplateArgumentList * |
248 | SpecArgs = D->getTemplateSpecializationArgs()) { |
249 | Out << '<'; |
250 | for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) { |
251 | Out << '#'; |
252 | VisitTemplateArgument(SpecArgs->get(I)); |
253 | } |
254 | Out << '>'; |
255 | } |
256 | |
257 | |
258 | for (auto PD : D->parameters()) { |
259 | Out << '#'; |
260 | VisitType(PD->getType()); |
261 | } |
262 | if (D->isVariadic()) |
263 | Out << '.'; |
264 | if (IsTemplate) { |
265 | |
266 | |
267 | |
268 | |
269 | |
270 | Out << '#'; |
271 | VisitType(D->getReturnType()); |
272 | } |
273 | Out << '#'; |
274 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { |
275 | if (MD->isStatic()) |
276 | Out << 'S'; |
277 | |
278 | if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers()) |
279 | Out << (char)('0' + quals); |
280 | switch (MD->getRefQualifier()) { |
281 | case RQ_None: break; |
282 | case RQ_LValue: Out << '&'; break; |
283 | case RQ_RValue: Out << "&&"; break; |
284 | } |
285 | } |
286 | } |
287 | |
288 | void USRGenerator::VisitNamedDecl(const NamedDecl *D) { |
289 | VisitDeclContext(D->getDeclContext()); |
290 | Out << "@"; |
291 | |
292 | if (EmitDeclName(D)) { |
293 | |
294 | |
295 | |
296 | |
297 | IgnoreResults = true; |
298 | } |
299 | } |
300 | |
301 | void USRGenerator::VisitVarDecl(const VarDecl *D) { |
302 | |
303 | |
304 | |
305 | if (ShouldGenerateLocation(D) && GenLoc(D, (D))) |
306 | return; |
307 | |
308 | VisitDeclContext(D->getDeclContext()); |
309 | |
310 | if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) { |
311 | Out << "@VT"; |
312 | VisitTemplateParameterList(VarTmpl->getTemplateParameters()); |
313 | } else if (const VarTemplatePartialSpecializationDecl *PartialSpec |
314 | = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { |
315 | Out << "@VP"; |
316 | VisitTemplateParameterList(PartialSpec->getTemplateParameters()); |
317 | } |
318 | |
319 | |
320 | StringRef s = D->getName(); |
321 | |
322 | |
323 | |
324 | |
325 | |
326 | if (s.empty()) |
327 | IgnoreResults = true; |
328 | else |
329 | Out << '@' << s; |
330 | |
331 | |
332 | if (const VarTemplateSpecializationDecl *Spec |
333 | = dyn_cast<VarTemplateSpecializationDecl>(D)) { |
334 | const TemplateArgumentList &Args = Spec->getTemplateArgs(); |
335 | Out << '>'; |
336 | for (unsigned I = 0, N = Args.size(); I != N; ++I) { |
337 | Out << '#'; |
338 | VisitTemplateArgument(Args.get(I)); |
339 | } |
340 | } |
341 | } |
342 | |
343 | void USRGenerator::VisitBindingDecl(const BindingDecl *D) { |
344 | if (isLocal(D) && GenLoc(D, )) |
345 | return; |
346 | VisitNamedDecl(D); |
347 | } |
348 | |
349 | void USRGenerator::VisitNonTypeTemplateParmDecl( |
350 | const NonTypeTemplateParmDecl *D) { |
351 | GenLoc(D, ); |
352 | } |
353 | |
354 | void USRGenerator::VisitTemplateTemplateParmDecl( |
355 | const TemplateTemplateParmDecl *D) { |
356 | GenLoc(D, ); |
357 | } |
358 | |
359 | void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { |
360 | if (D->isAnonymousNamespace()) { |
361 | Out << "@aN"; |
362 | return; |
363 | } |
364 | |
365 | VisitDeclContext(D->getDeclContext()); |
366 | if (!IgnoreResults) |
367 | Out << "@N@" << D->getName(); |
368 | } |
369 | |
370 | void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { |
371 | VisitFunctionDecl(D->getTemplatedDecl()); |
372 | } |
373 | |
374 | void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { |
375 | VisitTagDecl(D->getTemplatedDecl()); |
376 | } |
377 | |
378 | void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { |
379 | VisitDeclContext(D->getDeclContext()); |
380 | if (!IgnoreResults) |
381 | Out << "@NA@" << D->getName(); |
382 | } |
383 | |
384 | void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { |
385 | const DeclContext *container = D->getDeclContext(); |
386 | if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { |
387 | Visit(pd); |
388 | } |
389 | else { |
390 | |
391 | |
392 | const ObjCInterfaceDecl *ID = D->getClassInterface(); |
393 | if (!ID) { |
394 | IgnoreResults = true; |
395 | return; |
396 | } |
397 | auto getCategoryContext = [](const ObjCMethodDecl *D) -> |
398 | const ObjCCategoryDecl * { |
399 | if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) |
400 | return CD; |
401 | if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) |
402 | return ICD->getCategoryDecl(); |
403 | return nullptr; |
404 | }; |
405 | auto *CD = getCategoryContext(D); |
406 | VisitObjCContainerDecl(ID, CD); |
407 | } |
408 | |
409 | |
410 | |
411 | Out << (D->isInstanceMethod() ? "(im)" : "(cm)") |
412 | << DeclarationName(D->getSelector()); |
413 | } |
414 | |
415 | void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D, |
416 | const ObjCCategoryDecl *CatD) { |
417 | switch (D->getKind()) { |
418 | default: |
419 | llvm_unreachable("Invalid ObjC container."); |
420 | case Decl::ObjCInterface: |
421 | case Decl::ObjCImplementation: |
422 | GenObjCClass(D->getName(), GetExternalSourceContainer(D), |
423 | GetExternalSourceContainer(CatD)); |
424 | break; |
425 | case Decl::ObjCCategory: { |
426 | const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); |
427 | const ObjCInterfaceDecl *ID = CD->getClassInterface(); |
428 | if (!ID) { |
429 | |
430 | |
431 | |
432 | |
433 | IgnoreResults = true; |
434 | return; |
435 | } |
436 | |
437 | |
438 | if (CD->IsClassExtension()) { |
439 | Out << "objc(ext)" << ID->getName() << '@'; |
440 | GenLoc(CD, ); |
441 | } |
442 | else |
443 | GenObjCCategory(ID->getName(), CD->getName(), |
444 | GetExternalSourceContainer(ID), |
445 | GetExternalSourceContainer(CD)); |
446 | |
447 | break; |
448 | } |
449 | case Decl::ObjCCategoryImpl: { |
450 | const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); |
451 | const ObjCInterfaceDecl *ID = CD->getClassInterface(); |
452 | if (!ID) { |
453 | |
454 | |
455 | |
456 | |
457 | IgnoreResults = true; |
458 | return; |
459 | } |
460 | GenObjCCategory(ID->getName(), CD->getName(), |
461 | GetExternalSourceContainer(ID), |
462 | GetExternalSourceContainer(CD)); |
463 | break; |
464 | } |
465 | case Decl::ObjCProtocol: { |
466 | const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D); |
467 | GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD)); |
468 | break; |
469 | } |
470 | } |
471 | } |
472 | |
473 | void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { |
474 | |
475 | |
476 | if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) |
477 | Visit(ID); |
478 | else |
479 | Visit(cast<Decl>(D->getDeclContext())); |
480 | GenObjCProperty(D->getName(), D->isClassProperty()); |
481 | } |
482 | |
483 | void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { |
484 | if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { |
485 | VisitObjCPropertyDecl(PD); |
486 | return; |
487 | } |
488 | |
489 | IgnoreResults = true; |
490 | } |
491 | |
492 | void USRGenerator::VisitTagDecl(const TagDecl *D) { |
493 | |
494 | |
495 | if (!isa<EnumDecl>(D) && |
496 | ShouldGenerateLocation(D) && GenLoc(D, isLocal(D))) |
497 | return; |
498 | |
499 | GenExtSymbolContainer(D); |
500 | |
501 | D = D->getCanonicalDecl(); |
502 | VisitDeclContext(D->getDeclContext()); |
503 | |
504 | bool AlreadyStarted = false; |
505 | if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { |
506 | if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { |
507 | AlreadyStarted = true; |
508 | |
509 | switch (D->getTagKind()) { |
510 | case TTK_Interface: |
511 | case TTK_Class: |
512 | case TTK_Struct: Out << "@ST"; break; |
513 | case TTK_Union: Out << "@UT"; break; |
514 | case TTK_Enum: llvm_unreachable("enum template"); |
515 | } |
516 | VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); |
517 | } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec |
518 | = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { |
519 | AlreadyStarted = true; |
520 | |
521 | switch (D->getTagKind()) { |
522 | case TTK_Interface: |
523 | case TTK_Class: |
524 | case TTK_Struct: Out << "@SP"; break; |
525 | case TTK_Union: Out << "@UP"; break; |
526 | case TTK_Enum: llvm_unreachable("enum partial specialization"); |
527 | } |
528 | VisitTemplateParameterList(PartialSpec->getTemplateParameters()); |
529 | } |
530 | } |
531 | |
532 | if (!AlreadyStarted) { |
533 | switch (D->getTagKind()) { |
534 | case TTK_Interface: |
535 | case TTK_Class: |
536 | case TTK_Struct: Out << "@S"; break; |
537 | case TTK_Union: Out << "@U"; break; |
538 | case TTK_Enum: Out << "@E"; break; |
539 | } |
540 | } |
541 | |
542 | Out << '@'; |
543 | 0", "/home/seafit/code_projects/clang_source/clang/lib/Index/USRGeneration.cpp", 543, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Buf.size() > 0); |
544 | const unsigned off = Buf.size() - 1; |
545 | |
546 | if (EmitDeclName(D)) { |
547 | if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { |
548 | Buf[off] = 'A'; |
549 | Out << '@' << *TD; |
550 | } |
551 | else { |
552 | if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) { |
553 | printLoc(Out, D->getLocation(), Context->getSourceManager(), true); |
554 | } else { |
555 | Buf[off] = 'a'; |
556 | if (auto *ED = dyn_cast<EnumDecl>(D)) { |
557 | |
558 | auto enum_range = ED->enumerators(); |
559 | if (enum_range.begin() != enum_range.end()) { |
560 | Out << '@' << **enum_range.begin(); |
561 | } |
562 | } |
563 | } |
564 | } |
565 | } |
566 | |
567 | |
568 | if (const ClassTemplateSpecializationDecl *Spec |
569 | = dyn_cast<ClassTemplateSpecializationDecl>(D)) { |
570 | const TemplateArgumentList &Args = Spec->getTemplateArgs(); |
571 | Out << '>'; |
572 | for (unsigned I = 0, N = Args.size(); I != N; ++I) { |
573 | Out << '#'; |
574 | VisitTemplateArgument(Args.get(I)); |
575 | } |
576 | } |
577 | } |
578 | |
579 | void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { |
580 | if (ShouldGenerateLocation(D) && GenLoc(D, (D))) |
581 | return; |
582 | const DeclContext *DC = D->getDeclContext(); |
583 | if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) |
584 | Visit(DCN); |
585 | Out << "@T@"; |
586 | Out << D->getName(); |
587 | } |
588 | |
589 | void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { |
590 | GenLoc(D, ); |
591 | } |
592 | |
593 | void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) { |
594 | StringRef Container = GetExternalSourceContainer(D); |
595 | if (!Container.empty()) |
596 | Out << "@M@" << Container; |
597 | } |
598 | |
599 | bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { |
600 | if (generatedLoc) |
601 | return IgnoreResults; |
602 | generatedLoc = true; |
603 | |
604 | |
605 | if (!D) { |
606 | IgnoreResults = true; |
607 | return true; |
608 | } |
609 | |
610 | |
611 | D = D->getCanonicalDecl(); |
612 | |
613 | IgnoreResults = |
614 | IgnoreResults || printLoc(Out, D->getBeginLoc(), |
615 | Context->getSourceManager(), IncludeOffset); |
616 | |
617 | return IgnoreResults; |
618 | } |
619 | |
620 | static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) { |
621 | |
622 | PrintingPolicy PO(Ctx.getLangOpts()); |
623 | PO.SuppressTagKeyword = true; |
624 | PO.SuppressUnwrittenScope = true; |
625 | PO.ConstantArraySizeAsWritten = false; |
626 | PO.AnonymousTagLocations = false; |
627 | NNS->print(Out, PO); |
628 | } |
629 | |
630 | void USRGenerator::VisitType(QualType T) { |
631 | |
632 | |
633 | |
634 | ASTContext &Ctx = *Context; |
635 | |
636 | do { |
637 | T = Ctx.getCanonicalType(T); |
638 | Qualifiers Q = T.getQualifiers(); |
639 | unsigned qVal = 0; |
640 | if (Q.hasConst()) |
641 | qVal |= 0x1; |
642 | if (Q.hasVolatile()) |
643 | qVal |= 0x2; |
644 | if (Q.hasRestrict()) |
645 | qVal |= 0x4; |
646 | if(qVal) |
647 | Out << ((char) ('0' + qVal)); |
648 | |
649 | |
650 | |
651 | if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { |
652 | Out << 'P'; |
653 | T = Expansion->getPattern(); |
654 | } |
655 | |
656 | if (const BuiltinType *BT = T->getAs<BuiltinType>()) { |
657 | unsigned char c = '\0'; |
658 | switch (BT->getKind()) { |
659 | case BuiltinType::Void: |
660 | c = 'v'; break; |
661 | case BuiltinType::Bool: |
662 | c = 'b'; break; |
663 | case BuiltinType::UChar: |
664 | c = 'c'; break; |
665 | case BuiltinType::Char8: |
666 | c = 'u'; break; |
667 | case BuiltinType::Char16: |
668 | c = 'q'; break; |
669 | case BuiltinType::Char32: |
670 | c = 'w'; break; |
671 | case BuiltinType::UShort: |
672 | c = 's'; break; |
673 | case BuiltinType::UInt: |
674 | c = 'i'; break; |
675 | case BuiltinType::ULong: |
676 | c = 'l'; break; |
677 | case BuiltinType::ULongLong: |
678 | c = 'k'; break; |
679 | case BuiltinType::UInt128: |
680 | c = 'j'; break; |
681 | case BuiltinType::Char_U: |
682 | case BuiltinType::Char_S: |
683 | c = 'C'; break; |
684 | case BuiltinType::SChar: |
685 | c = 'r'; break; |
686 | case BuiltinType::WChar_S: |
687 | case BuiltinType::WChar_U: |
688 | c = 'W'; break; |
689 | case BuiltinType::Short: |
690 | c = 'S'; break; |
691 | case BuiltinType::Int: |
692 | c = 'I'; break; |
693 | case BuiltinType::Long: |
694 | c = 'L'; break; |
695 | case BuiltinType::LongLong: |
696 | c = 'K'; break; |
697 | case BuiltinType::Int128: |
698 | c = 'J'; break; |
699 | case BuiltinType::Float16: |
700 | case BuiltinType::Half: |
701 | c = 'h'; break; |
702 | case BuiltinType::Float: |
703 | c = 'f'; break; |
704 | case BuiltinType::Double: |
705 | c = 'd'; break; |
706 | case BuiltinType::LongDouble: |
707 | c = 'D'; break; |
708 | case BuiltinType::Float128: |
709 | c = 'Q'; break; |
710 | case BuiltinType::NullPtr: |
711 | c = 'n'; break; |
712 | #define BUILTIN_TYPE(Id, SingletonId) |
713 | #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: |
714 | #include "clang/AST/BuiltinTypes.def" |
715 | case BuiltinType::Dependent: |
716 | #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ |
717 | case BuiltinType::Id: |
718 | #include "clang/Basic/OpenCLImageTypes.def" |
719 | #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ |
720 | case BuiltinType::Id: |
721 | #include "clang/Basic/OpenCLExtensionTypes.def" |
722 | case BuiltinType::OCLEvent: |
723 | case BuiltinType::OCLClkEvent: |
724 | case BuiltinType::OCLQueue: |
725 | case BuiltinType::OCLReserveID: |
726 | case BuiltinType::OCLSampler: |
727 | case BuiltinType::ShortAccum: |
728 | case BuiltinType::Accum: |
729 | case BuiltinType::LongAccum: |
730 | case BuiltinType::UShortAccum: |
731 | case BuiltinType::UAccum: |
732 | case BuiltinType::ULongAccum: |
733 | case BuiltinType::ShortFract: |
734 | case BuiltinType::Fract: |
735 | case BuiltinType::LongFract: |
736 | case BuiltinType::UShortFract: |
737 | case BuiltinType::UFract: |
738 | case BuiltinType::ULongFract: |
739 | case BuiltinType::SatShortAccum: |
740 | case BuiltinType::SatAccum: |
741 | case BuiltinType::SatLongAccum: |
742 | case BuiltinType::SatUShortAccum: |
743 | case BuiltinType::SatUAccum: |
744 | case BuiltinType::SatULongAccum: |
745 | case BuiltinType::SatShortFract: |
746 | case BuiltinType::SatFract: |
747 | case BuiltinType::SatLongFract: |
748 | case BuiltinType::SatUShortFract: |
749 | case BuiltinType::SatUFract: |
750 | case BuiltinType::SatULongFract: |
751 | IgnoreResults = true; |
752 | return; |
753 | case BuiltinType::ObjCId: |
754 | c = 'o'; break; |
755 | case BuiltinType::ObjCClass: |
756 | c = 'O'; break; |
757 | case BuiltinType::ObjCSel: |
758 | c = 'e'; break; |
759 | } |
760 | Out << c; |
761 | return; |
762 | } |
763 | |
764 | |
765 | |
766 | llvm::DenseMap<const Type *, unsigned>::iterator Substitution |
767 | = TypeSubstitutions.find(T.getTypePtr()); |
768 | if (Substitution != TypeSubstitutions.end()) { |
769 | Out << 'S' << Substitution->second << '_'; |
770 | return; |
771 | } else { |
772 | |
773 | unsigned Number = TypeSubstitutions.size(); |
774 | TypeSubstitutions[T.getTypePtr()] = Number; |
775 | } |
776 | |
777 | if (const PointerType *PT = T->getAs<PointerType>()) { |
778 | Out << '*'; |
779 | T = PT->getPointeeType(); |
780 | continue; |
781 | } |
782 | if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { |
783 | Out << '*'; |
784 | T = OPT->getPointeeType(); |
785 | continue; |
786 | } |
787 | if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { |
788 | Out << "&&"; |
789 | T = RT->getPointeeType(); |
790 | continue; |
791 | } |
792 | if (const ReferenceType *RT = T->getAs<ReferenceType>()) { |
793 | Out << '&'; |
794 | T = RT->getPointeeType(); |
795 | continue; |
796 | } |
797 | if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { |
798 | Out << 'F'; |
799 | VisitType(FT->getReturnType()); |
800 | Out << '('; |
801 | for (const auto &I : FT->param_types()) { |
802 | Out << '#'; |
803 | VisitType(I); |
804 | } |
805 | Out << ')'; |
806 | if (FT->isVariadic()) |
807 | Out << '.'; |
808 | return; |
809 | } |
810 | if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { |
811 | Out << 'B'; |
812 | T = BT->getPointeeType(); |
813 | continue; |
814 | } |
815 | if (const ComplexType *CT = T->getAs<ComplexType>()) { |
816 | Out << '<'; |
817 | T = CT->getElementType(); |
818 | continue; |
819 | } |
820 | if (const TagType *TT = T->getAs<TagType>()) { |
821 | Out << '$'; |
822 | VisitTagDecl(TT->getDecl()); |
823 | return; |
824 | } |
825 | if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { |
826 | Out << '$'; |
827 | VisitObjCInterfaceDecl(OIT->getDecl()); |
828 | return; |
829 | } |
830 | if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) { |
831 | Out << 'Q'; |
832 | VisitType(OIT->getBaseType()); |
833 | for (auto *Prot : OIT->getProtocols()) |
834 | VisitObjCProtocolDecl(Prot); |
835 | return; |
836 | } |
837 | if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { |
838 | Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); |
839 | return; |
840 | } |
841 | if (const TemplateSpecializationType *Spec |
842 | = T->getAs<TemplateSpecializationType>()) { |
843 | Out << '>'; |
844 | VisitTemplateName(Spec->getTemplateName()); |
845 | Out << Spec->getNumArgs(); |
846 | for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) |
847 | VisitTemplateArgument(Spec->getArg(I)); |
848 | return; |
849 | } |
850 | if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { |
851 | Out << '^'; |
852 | printQualifier(Out, Ctx, DNT->getQualifier()); |
853 | Out << ':' << DNT->getIdentifier()->getName(); |
854 | return; |
855 | } |
856 | if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) { |
857 | T = InjT->getInjectedSpecializationType(); |
858 | continue; |
859 | } |
860 | if (const auto *VT = T->getAs<VectorType>()) { |
861 | Out << (T->isExtVectorType() ? ']' : '['); |
862 | Out << VT->getNumElements(); |
863 | T = VT->getElementType(); |
864 | continue; |
865 | } |
866 | if (const auto *const AT = dyn_cast<ArrayType>(T)) { |
867 | Out << '{'; |
868 | switch (AT->getSizeModifier()) { |
869 | case ArrayType::Static: |
870 | Out << 's'; |
871 | break; |
872 | case ArrayType::Star: |
873 | Out << '*'; |
874 | break; |
875 | case ArrayType::Normal: |
876 | Out << 'n'; |
877 | break; |
878 | } |
879 | if (const auto *const CAT = dyn_cast<ConstantArrayType>(T)) |
880 | Out << CAT->getSize(); |
881 | |
882 | T = AT->getElementType(); |
883 | continue; |
884 | } |
885 | |
886 | |
887 | Out << ' '; |
888 | break; |
889 | } while (true); |
890 | } |
891 | |
892 | void USRGenerator::VisitTemplateParameterList( |
893 | const TemplateParameterList *Params) { |
894 | if (!Params) |
895 | return; |
896 | Out << '>' << Params->size(); |
897 | for (TemplateParameterList::const_iterator P = Params->begin(), |
898 | PEnd = Params->end(); |
899 | P != PEnd; ++P) { |
900 | Out << '#'; |
901 | if (isa<TemplateTypeParmDecl>(*P)) { |
902 | if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) |
903 | Out<< 'p'; |
904 | Out << 'T'; |
905 | continue; |
906 | } |
907 | |
908 | if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { |
909 | if (NTTP->isParameterPack()) |
910 | Out << 'p'; |
911 | Out << 'N'; |
912 | VisitType(NTTP->getType()); |
913 | continue; |
914 | } |
915 | |
916 | TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); |
917 | if (TTP->isParameterPack()) |
918 | Out << 'p'; |
919 | Out << 't'; |
920 | VisitTemplateParameterList(TTP->getTemplateParameters()); |
921 | } |
922 | } |
923 | |
924 | void USRGenerator::VisitTemplateName(TemplateName Name) { |
925 | if (TemplateDecl *Template = Name.getAsTemplateDecl()) { |
926 | if (TemplateTemplateParmDecl *TTP |
927 | = dyn_cast<TemplateTemplateParmDecl>(Template)) { |
928 | Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); |
929 | return; |
930 | } |
931 | |
932 | Visit(Template); |
933 | return; |
934 | } |
935 | |
936 | |
937 | } |
938 | |
939 | void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { |
940 | switch (Arg.getKind()) { |
941 | case TemplateArgument::Null: |
942 | break; |
943 | |
944 | case TemplateArgument::Declaration: |
945 | Visit(Arg.getAsDecl()); |
946 | break; |
947 | |
948 | case TemplateArgument::NullPtr: |
949 | break; |
950 | |
951 | case TemplateArgument::TemplateExpansion: |
952 | Out << 'P'; |
953 | LLVM_FALLTHROUGH; |
954 | case TemplateArgument::Template: |
955 | VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); |
956 | break; |
957 | |
958 | case TemplateArgument::Expression: |
959 | |
960 | break; |
961 | |
962 | case TemplateArgument::Pack: |
963 | Out << 'p' << Arg.pack_size(); |
964 | for (const auto &P : Arg.pack_elements()) |
965 | VisitTemplateArgument(P); |
966 | break; |
967 | |
968 | case TemplateArgument::Type: |
969 | VisitType(Arg.getAsType()); |
970 | break; |
971 | |
972 | case TemplateArgument::Integral: |
973 | Out << 'V'; |
974 | VisitType(Arg.getIntegralType()); |
975 | Out << Arg.getAsIntegral(); |
976 | break; |
977 | } |
978 | } |
979 | |
980 | void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { |
981 | if (ShouldGenerateLocation(D) && GenLoc(D, (D))) |
982 | return; |
983 | VisitDeclContext(D->getDeclContext()); |
984 | Out << "@UUV@"; |
985 | printQualifier(Out, D->getASTContext(), D->getQualifier()); |
986 | EmitDeclName(D); |
987 | } |
988 | |
989 | void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { |
990 | if (ShouldGenerateLocation(D) && GenLoc(D, (D))) |
991 | return; |
992 | VisitDeclContext(D->getDeclContext()); |
993 | Out << "@UUT@"; |
994 | printQualifier(Out, D->getASTContext(), D->getQualifier()); |
995 | Out << D->getName(); |
996 | } |
997 | |
998 | |
999 | |
1000 | |
1001 | |
1002 | |
1003 | |
1004 | static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn, |
1005 | StringRef CatSymDefinedIn, |
1006 | raw_ostream &OS) { |
1007 | if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty()) |
1008 | return; |
1009 | if (CatSymDefinedIn.empty()) { |
1010 | OS << "@M@" << ClsSymDefinedIn << '@'; |
1011 | return; |
1012 | } |
1013 | OS << "@CM@" << CatSymDefinedIn << '@'; |
1014 | if (ClsSymDefinedIn != CatSymDefinedIn) { |
1015 | OS << ClsSymDefinedIn << '@'; |
1016 | } |
1017 | } |
1018 | |
1019 | void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, |
1020 | StringRef ExtSymDefinedIn, |
1021 | StringRef CategoryContextExtSymbolDefinedIn) { |
1022 | combineClassAndCategoryExtContainers(ExtSymDefinedIn, |
1023 | CategoryContextExtSymbolDefinedIn, OS); |
1024 | OS << "objc(cs)" << Cls; |
1025 | } |
1026 | |
1027 | void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, |
1028 | raw_ostream &OS, |
1029 | StringRef ClsSymDefinedIn, |
1030 | StringRef CatSymDefinedIn) { |
1031 | combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS); |
1032 | OS << "objc(cy)" << Cls << '@' << Cat; |
1033 | } |
1034 | |
1035 | void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) { |
1036 | OS << '@' << Ivar; |
1037 | } |
1038 | |
1039 | void clang::index::generateUSRForObjCMethod(StringRef Sel, |
1040 | bool IsInstanceMethod, |
1041 | raw_ostream &OS) { |
1042 | OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel; |
1043 | } |
1044 | |
1045 | void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp, |
1046 | raw_ostream &OS) { |
1047 | OS << (isClassProp ? "(cpy)" : "(py)") << Prop; |
1048 | } |
1049 | |
1050 | void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, |
1051 | StringRef ExtSymDefinedIn) { |
1052 | if (!ExtSymDefinedIn.empty()) |
1053 | OS << "@M@" << ExtSymDefinedIn << '@'; |
1054 | OS << "objc(pl)" << Prot; |
1055 | } |
1056 | |
1057 | void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, |
1058 | StringRef ExtSymDefinedIn) { |
1059 | if (!ExtSymDefinedIn.empty()) |
1060 | OS << "@M@" << ExtSymDefinedIn; |
1061 | OS << "@E@" << EnumName; |
1062 | } |
1063 | |
1064 | void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName, |
1065 | raw_ostream &OS) { |
1066 | OS << '@' << EnumConstantName; |
1067 | } |
1068 | |
1069 | bool clang::index::generateUSRForDecl(const Decl *D, |
1070 | SmallVectorImpl<char> &Buf) { |
1071 | if (!D) |
1072 | return true; |
1073 | |
1074 | |
1075 | |
1076 | |
1077 | USRGenerator UG(&D->getASTContext(), Buf); |
1078 | UG.Visit(D); |
1079 | return UG.ignoreResults(); |
1080 | } |
1081 | |
1082 | bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD, |
1083 | const SourceManager &SM, |
1084 | SmallVectorImpl<char> &Buf) { |
1085 | if (!MD) |
1086 | return true; |
1087 | return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(), |
1088 | SM, Buf); |
1089 | |
1090 | } |
1091 | |
1092 | bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc, |
1093 | const SourceManager &SM, |
1094 | SmallVectorImpl<char> &Buf) { |
1095 | |
1096 | if (MacroName.empty() || Loc.isInvalid()) |
1097 | return true; |
1098 | |
1099 | llvm::raw_svector_ostream Out(Buf); |
1100 | |
1101 | |
1102 | |
1103 | bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc); |
1104 | |
1105 | Out << getUSRSpacePrefix(); |
1106 | if (ShouldGenerateLocation) |
1107 | printLoc(Out, Loc, SM, ); |
1108 | Out << "@macro@"; |
1109 | Out << MacroName; |
1110 | return false; |
1111 | } |
1112 | |
1113 | bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx, |
1114 | SmallVectorImpl<char> &Buf) { |
1115 | if (T.isNull()) |
1116 | return true; |
1117 | T = T.getCanonicalType(); |
1118 | |
1119 | USRGenerator UG(&Ctx, Buf); |
1120 | UG.VisitType(T); |
1121 | return UG.ignoreResults(); |
1122 | } |
1123 | |
1124 | bool clang::index::generateFullUSRForModule(const Module *Mod, |
1125 | raw_ostream &OS) { |
1126 | if (!Mod->Parent) |
1127 | return generateFullUSRForTopLevelModuleName(Mod->Name, OS); |
1128 | if (generateFullUSRForModule(Mod->Parent, OS)) |
1129 | return true; |
1130 | return generateUSRFragmentForModule(Mod, OS); |
1131 | } |
1132 | |
1133 | bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName, |
1134 | raw_ostream &OS) { |
1135 | OS << getUSRSpacePrefix(); |
1136 | return generateUSRFragmentForModuleName(ModName, OS); |
1137 | } |
1138 | |
1139 | bool clang::index::generateUSRFragmentForModule(const Module *Mod, |
1140 | raw_ostream &OS) { |
1141 | return generateUSRFragmentForModuleName(Mod->Name, OS); |
1142 | } |
1143 | |
1144 | bool clang::index::generateUSRFragmentForModuleName(StringRef ModName, |
1145 | raw_ostream &OS) { |
1146 | OS << "@M@" << ModName; |
1147 | return false; |
1148 | } |
1149 | |