xref: /freebsd/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp (revision 3c4ba5f55438f7afd4f4b0b56f88f2bb505fd6a6)
1 //===- DeclarationName.cpp - Declaration names implementation -------------===//
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 // This file implements the DeclarationName and DeclarationNameTable
10 // classes.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/DeclarationName.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/DeclTemplate.h"
20 #include "clang/AST/OpenMPClause.h"
21 #include "clang/AST/PrettyPrinter.h"
22 #include "clang/AST/Type.h"
23 #include "clang/AST/TypeLoc.h"
24 #include "clang/AST/TypeOrdering.h"
25 #include "clang/Basic/IdentifierTable.h"
26 #include "clang/Basic/LLVM.h"
27 #include "clang/Basic/LangOptions.h"
28 #include "clang/Basic/OperatorKinds.h"
29 #include "clang/Basic/SourceLocation.h"
30 #include "llvm/ADT/FoldingSet.h"
31 #include "llvm/Support/Casting.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <algorithm>
36 #include <cassert>
37 #include <cstdint>
38 #include <string>
39 
40 using namespace clang;
41 
42 static int compareInt(unsigned A, unsigned B) {
43   return (A < B ? -1 : (A > B ? 1 : 0));
44 }
45 
46 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
47   if (LHS.getNameKind() != RHS.getNameKind())
48     return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
49 
50   switch (LHS.getNameKind()) {
51   case DeclarationName::Identifier: {
52     IdentifierInfo *LII = LHS.castAsIdentifierInfo();
53     IdentifierInfo *RII = RHS.castAsIdentifierInfo();
54     if (!LII)
55       return RII ? -1 : 0;
56     if (!RII)
57       return 1;
58 
59     return LII->getName().compare(RII->getName());
60   }
61 
62   case DeclarationName::ObjCZeroArgSelector:
63   case DeclarationName::ObjCOneArgSelector:
64   case DeclarationName::ObjCMultiArgSelector: {
65     Selector LHSSelector = LHS.getObjCSelector();
66     Selector RHSSelector = RHS.getObjCSelector();
67     // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
68     if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
69         RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
70       return LHSSelector.getAsIdentifierInfo()->getName().compare(
71           RHSSelector.getAsIdentifierInfo()->getName());
72     }
73     unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
74     for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
75       switch (LHSSelector.getNameForSlot(I).compare(
76           RHSSelector.getNameForSlot(I))) {
77       case -1:
78         return -1;
79       case 1:
80         return 1;
81       default:
82         break;
83       }
84     }
85 
86     return compareInt(LN, RN);
87   }
88 
89   case DeclarationName::CXXConstructorName:
90   case DeclarationName::CXXDestructorName:
91   case DeclarationName::CXXConversionFunctionName:
92     if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
93       return -1;
94     if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
95       return 1;
96     return 0;
97 
98   case DeclarationName::CXXDeductionGuideName:
99     // We never want to compare deduction guide names for templates from
100     // different scopes, so just compare the template-name.
101     return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(),
102                    RHS.getCXXDeductionGuideTemplate()->getDeclName());
103 
104   case DeclarationName::CXXOperatorName:
105     return compareInt(LHS.getCXXOverloadedOperator(),
106                       RHS.getCXXOverloadedOperator());
107 
108   case DeclarationName::CXXLiteralOperatorName:
109     return LHS.getCXXLiteralIdentifier()->getName().compare(
110         RHS.getCXXLiteralIdentifier()->getName());
111 
112   case DeclarationName::CXXUsingDirective:
113     return 0;
114   }
115 
116   llvm_unreachable("Invalid DeclarationName Kind!");
117 }
118 
119 static void printCXXConstructorDestructorName(QualType ClassType,
120                                               raw_ostream &OS,
121                                               PrintingPolicy Policy) {
122   // We know we're printing C++ here. Ensure we print types properly.
123   Policy.adjustForCPlusPlus();
124 
125   if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
126     OS << *ClassRec->getDecl();
127     return;
128   }
129   if (Policy.SuppressTemplateArgsInCXXConstructors) {
130     if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
131       OS << *InjTy->getDecl();
132       return;
133     }
134   }
135   ClassType.print(OS, Policy);
136 }
137 
138 void DeclarationName::print(raw_ostream &OS,
139                             const PrintingPolicy &Policy) const {
140   switch (getNameKind()) {
141   case DeclarationName::Identifier:
142     if (const IdentifierInfo *II = getAsIdentifierInfo()) {
143       StringRef Name = II->getName();
144       // If this is a mangled OpenMP variant name we strip off the mangling for
145       // printing. It should not be visible to the user at all.
146       if (II->isMangledOpenMPVariantName()) {
147         std::pair<StringRef, StringRef> NameContextPair =
148             Name.split(getOpenMPVariantManglingSeparatorStr());
149         OS << NameContextPair.first << "["
150            << OMPTraitInfo(NameContextPair.second) << "]";
151       } else {
152         OS << Name;
153       }
154     }
155     return;
156 
157   case DeclarationName::ObjCZeroArgSelector:
158   case DeclarationName::ObjCOneArgSelector:
159   case DeclarationName::ObjCMultiArgSelector:
160     getObjCSelector().print(OS);
161     return;
162 
163   case DeclarationName::CXXConstructorName:
164     return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
165 
166   case DeclarationName::CXXDestructorName:
167     OS << '~';
168     return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
169 
170   case DeclarationName::CXXDeductionGuideName:
171     OS << "<deduction guide for ";
172     getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
173     OS << '>';
174     return;
175 
176   case DeclarationName::CXXOperatorName: {
177     const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());
178     assert(OpName && "not an overloaded operator");
179 
180     OS << "operator";
181     if (OpName[0] >= 'a' && OpName[0] <= 'z')
182       OS << ' ';
183     OS << OpName;
184     return;
185   }
186 
187   case DeclarationName::CXXLiteralOperatorName:
188     OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
189     return;
190 
191   case DeclarationName::CXXConversionFunctionName: {
192     OS << "operator ";
193     QualType Type = getCXXNameType();
194     if (const RecordType *Rec = Type->getAs<RecordType>()) {
195       OS << *Rec->getDecl();
196       return;
197     }
198     // We know we're printing C++ here, ensure we print 'bool' properly.
199     PrintingPolicy CXXPolicy = Policy;
200     CXXPolicy.adjustForCPlusPlus();
201     Type.print(OS, CXXPolicy);
202     return;
203   }
204   case DeclarationName::CXXUsingDirective:
205     OS << "<using-directive>";
206     return;
207   }
208 
209   llvm_unreachable("Unexpected declaration name kind");
210 }
211 
212 namespace clang {
213 
214 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
215   LangOptions LO;
216   N.print(OS, PrintingPolicy(LO));
217   return OS;
218 }
219 
220 } // namespace clang
221 
222 bool DeclarationName::isDependentName() const {
223   QualType T = getCXXNameType();
224   if (!T.isNull() && T->isDependentType())
225     return true;
226 
227   // A class-scope deduction guide in a dependent context has a dependent name.
228   auto *TD = getCXXDeductionGuideTemplate();
229   if (TD && TD->getDeclContext()->isDependentContext())
230     return true;
231 
232   return false;
233 }
234 
235 std::string DeclarationName::getAsString() const {
236   std::string Result;
237   llvm::raw_string_ostream OS(Result);
238   OS << *this;
239   return Result;
240 }
241 
242 void *DeclarationName::getFETokenInfoSlow() const {
243   switch (getNameKind()) {
244   case Identifier:
245     llvm_unreachable("case Identifier already handled by getFETokenInfo!");
246   case CXXConstructorName:
247   case CXXDestructorName:
248   case CXXConversionFunctionName:
249     return castAsCXXSpecialNameExtra()->FETokenInfo;
250   case CXXOperatorName:
251     return castAsCXXOperatorIdName()->FETokenInfo;
252   case CXXDeductionGuideName:
253     return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
254   case CXXLiteralOperatorName:
255     return castAsCXXLiteralOperatorIdName()->FETokenInfo;
256   default:
257     llvm_unreachable("DeclarationName has no FETokenInfo!");
258   }
259 }
260 
261 void DeclarationName::setFETokenInfoSlow(void *T) {
262   switch (getNameKind()) {
263   case Identifier:
264     llvm_unreachable("case Identifier already handled by setFETokenInfo!");
265   case CXXConstructorName:
266   case CXXDestructorName:
267   case CXXConversionFunctionName:
268     castAsCXXSpecialNameExtra()->FETokenInfo = T;
269     break;
270   case CXXOperatorName:
271     castAsCXXOperatorIdName()->FETokenInfo = T;
272     break;
273   case CXXDeductionGuideName:
274     castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
275     break;
276   case CXXLiteralOperatorName:
277     castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
278     break;
279   default:
280     llvm_unreachable("DeclarationName has no FETokenInfo!");
281   }
282 }
283 
284 LLVM_DUMP_METHOD void DeclarationName::dump() const {
285   llvm::errs() << *this << '\n';
286 }
287 
288 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
289   // Initialize the overloaded operator names.
290   for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
291     CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
292 }
293 
294 DeclarationName
295 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
296   Template = cast<TemplateDecl>(Template->getCanonicalDecl());
297 
298   llvm::FoldingSetNodeID ID;
299   ID.AddPointer(Template);
300 
301   void *InsertPos = nullptr;
302   if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
303     return DeclarationName(Name);
304 
305   auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
306   CXXDeductionGuideNames.InsertNode(Name, InsertPos);
307   return DeclarationName(Name);
308 }
309 
310 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
311   // The type of constructors is unqualified.
312   Ty = Ty.getUnqualifiedType();
313   // Do we already have this C++ constructor name ?
314   llvm::FoldingSetNodeID ID;
315   ID.AddPointer(Ty.getAsOpaquePtr());
316   void *InsertPos = nullptr;
317   if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
318     return {Name, DeclarationName::StoredCXXConstructorName};
319 
320   // We have to create it.
321   auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
322   CXXConstructorNames.InsertNode(SpecialName, InsertPos);
323   return {SpecialName, DeclarationName::StoredCXXConstructorName};
324 }
325 
326 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
327   // The type of destructors is unqualified.
328   Ty = Ty.getUnqualifiedType();
329   // Do we already have this C++ destructor name ?
330   llvm::FoldingSetNodeID ID;
331   ID.AddPointer(Ty.getAsOpaquePtr());
332   void *InsertPos = nullptr;
333   if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
334     return {Name, DeclarationName::StoredCXXDestructorName};
335 
336   // We have to create it.
337   auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
338   CXXDestructorNames.InsertNode(SpecialName, InsertPos);
339   return {SpecialName, DeclarationName::StoredCXXDestructorName};
340 }
341 
342 DeclarationName
343 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
344   // Do we already have this C++ conversion function name ?
345   llvm::FoldingSetNodeID ID;
346   ID.AddPointer(Ty.getAsOpaquePtr());
347   void *InsertPos = nullptr;
348   if (auto *Name =
349           CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
350     return {Name, DeclarationName::StoredCXXConversionFunctionName};
351 
352   // We have to create it.
353   auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
354   CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
355   return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
356 }
357 
358 DeclarationName
359 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
360                                         CanQualType Ty) {
361   switch (Kind) {
362   case DeclarationName::CXXConstructorName:
363     return getCXXConstructorName(Ty);
364   case DeclarationName::CXXDestructorName:
365     return getCXXDestructorName(Ty);
366   case DeclarationName::CXXConversionFunctionName:
367     return getCXXConversionFunctionName(Ty);
368   default:
369     llvm_unreachable("Invalid kind in getCXXSpecialName!");
370   }
371 }
372 
373 DeclarationName
374 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
375   llvm::FoldingSetNodeID ID;
376   ID.AddPointer(II);
377 
378   void *InsertPos = nullptr;
379   if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
380     return DeclarationName(Name);
381 
382   auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
383   CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
384   return DeclarationName(LiteralName);
385 }
386 
387 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
388   switch (Name.getNameKind()) {
389   case DeclarationName::Identifier:
390   case DeclarationName::CXXDeductionGuideName:
391     break;
392   case DeclarationName::CXXConstructorName:
393   case DeclarationName::CXXDestructorName:
394   case DeclarationName::CXXConversionFunctionName:
395     setNamedTypeLoc(nullptr);
396     break;
397   case DeclarationName::CXXOperatorName:
398     setCXXOperatorNameRange(SourceRange());
399     break;
400   case DeclarationName::CXXLiteralOperatorName:
401     setCXXLiteralOperatorNameLoc(SourceLocation());
402     break;
403   case DeclarationName::ObjCZeroArgSelector:
404   case DeclarationName::ObjCOneArgSelector:
405   case DeclarationName::ObjCMultiArgSelector:
406     // FIXME: ?
407     break;
408   case DeclarationName::CXXUsingDirective:
409     break;
410   }
411 }
412 
413 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
414   switch (Name.getNameKind()) {
415   case DeclarationName::Identifier:
416   case DeclarationName::ObjCZeroArgSelector:
417   case DeclarationName::ObjCOneArgSelector:
418   case DeclarationName::ObjCMultiArgSelector:
419   case DeclarationName::CXXOperatorName:
420   case DeclarationName::CXXLiteralOperatorName:
421   case DeclarationName::CXXUsingDirective:
422   case DeclarationName::CXXDeductionGuideName:
423     return false;
424 
425   case DeclarationName::CXXConstructorName:
426   case DeclarationName::CXXDestructorName:
427   case DeclarationName::CXXConversionFunctionName:
428     if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
429       return TInfo->getType()->containsUnexpandedParameterPack();
430 
431     return Name.getCXXNameType()->containsUnexpandedParameterPack();
432   }
433   llvm_unreachable("All name kinds handled.");
434 }
435 
436 bool DeclarationNameInfo::isInstantiationDependent() const {
437   switch (Name.getNameKind()) {
438   case DeclarationName::Identifier:
439   case DeclarationName::ObjCZeroArgSelector:
440   case DeclarationName::ObjCOneArgSelector:
441   case DeclarationName::ObjCMultiArgSelector:
442   case DeclarationName::CXXOperatorName:
443   case DeclarationName::CXXLiteralOperatorName:
444   case DeclarationName::CXXUsingDirective:
445   case DeclarationName::CXXDeductionGuideName:
446     return false;
447 
448   case DeclarationName::CXXConstructorName:
449   case DeclarationName::CXXDestructorName:
450   case DeclarationName::CXXConversionFunctionName:
451     if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
452       return TInfo->getType()->isInstantiationDependentType();
453 
454     return Name.getCXXNameType()->isInstantiationDependentType();
455   }
456   llvm_unreachable("All name kinds handled.");
457 }
458 
459 std::string DeclarationNameInfo::getAsString() const {
460   std::string Result;
461   llvm::raw_string_ostream OS(Result);
462   OS << *this;
463   return Result;
464 }
465 
466 raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
467   LangOptions LO;
468   DNInfo.printName(OS, PrintingPolicy(LangOptions()));
469   return OS;
470 }
471 
472 void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
473   switch (Name.getNameKind()) {
474   case DeclarationName::Identifier:
475   case DeclarationName::ObjCZeroArgSelector:
476   case DeclarationName::ObjCOneArgSelector:
477   case DeclarationName::ObjCMultiArgSelector:
478   case DeclarationName::CXXOperatorName:
479   case DeclarationName::CXXLiteralOperatorName:
480   case DeclarationName::CXXUsingDirective:
481   case DeclarationName::CXXDeductionGuideName:
482     Name.print(OS, Policy);
483     return;
484 
485   case DeclarationName::CXXConstructorName:
486   case DeclarationName::CXXDestructorName:
487   case DeclarationName::CXXConversionFunctionName:
488     if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
489       if (Name.getNameKind() == DeclarationName::CXXDestructorName)
490         OS << '~';
491       else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
492         OS << "operator ";
493       LangOptions LO;
494       Policy.adjustForCPlusPlus();
495       Policy.SuppressScope = true;
496       OS << TInfo->getType().getAsString(Policy);
497     } else
498       Name.print(OS, Policy);
499     return;
500   }
501   llvm_unreachable("Unexpected declaration name kind");
502 }
503 
504 SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
505   switch (Name.getNameKind()) {
506   case DeclarationName::Identifier:
507   case DeclarationName::CXXDeductionGuideName:
508     return NameLoc;
509 
510   case DeclarationName::CXXOperatorName:
511     return LocInfo.getCXXOperatorNameEndLoc();
512 
513   case DeclarationName::CXXLiteralOperatorName:
514     return LocInfo.getCXXLiteralOperatorNameLoc();
515 
516   case DeclarationName::CXXConstructorName:
517   case DeclarationName::CXXDestructorName:
518   case DeclarationName::CXXConversionFunctionName:
519     if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
520       return TInfo->getTypeLoc().getEndLoc();
521     else
522       return NameLoc;
523 
524     // DNInfo work in progress: FIXME.
525   case DeclarationName::ObjCZeroArgSelector:
526   case DeclarationName::ObjCOneArgSelector:
527   case DeclarationName::ObjCMultiArgSelector:
528   case DeclarationName::CXXUsingDirective:
529     return NameLoc;
530   }
531   llvm_unreachable("Unexpected declaration name kind");
532 }
533