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