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