• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
compareInt(unsigned A,unsigned B)42 static int compareInt(unsigned A, unsigned B) {
43   return (A < B ? -1 : (A > B ? 1 : 0));
44 }
45 
compare(DeclarationName LHS,DeclarationName RHS)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 
printCXXConstructorDestructorName(QualType ClassType,raw_ostream & OS,PrintingPolicy Policy)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 
print(raw_ostream & OS,const PrintingPolicy & Policy) const138 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 
operator <<(raw_ostream & OS,DeclarationName N)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 
isDependentName() const222 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 
getAsString() const235 std::string DeclarationName::getAsString() const {
236   std::string Result;
237   llvm::raw_string_ostream OS(Result);
238   OS << *this;
239   return OS.str();
240 }
241 
getFETokenInfoSlow() const242 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 
setFETokenInfoSlow(void * T)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 
dump() const284 LLVM_DUMP_METHOD void DeclarationName::dump() const {
285   llvm::errs() << *this << '\n';
286 }
287 
DeclarationNameTable(const ASTContext & C)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
getCXXDeductionGuideName(TemplateDecl * Template)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 
getCXXConstructorName(CanQualType Ty)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 
getCXXDestructorName(CanQualType Ty)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
getCXXConversionFunctionName(CanQualType Ty)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
getCXXSpecialName(DeclarationName::NameKind Kind,CanQualType Ty)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
getCXXLiteralOperatorName(IdentifierInfo * II)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 
DeclarationNameLoc(DeclarationName Name)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     NamedType.TInfo = nullptr;
396     break;
397   case DeclarationName::CXXOperatorName:
398     CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
399     CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
400     break;
401   case DeclarationName::CXXLiteralOperatorName:
402     CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
403     break;
404   case DeclarationName::ObjCZeroArgSelector:
405   case DeclarationName::ObjCOneArgSelector:
406   case DeclarationName::ObjCMultiArgSelector:
407     // FIXME: ?
408     break;
409   case DeclarationName::CXXUsingDirective:
410     break;
411   }
412 }
413 
containsUnexpandedParameterPack() const414 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
415   switch (Name.getNameKind()) {
416   case DeclarationName::Identifier:
417   case DeclarationName::ObjCZeroArgSelector:
418   case DeclarationName::ObjCOneArgSelector:
419   case DeclarationName::ObjCMultiArgSelector:
420   case DeclarationName::CXXOperatorName:
421   case DeclarationName::CXXLiteralOperatorName:
422   case DeclarationName::CXXUsingDirective:
423   case DeclarationName::CXXDeductionGuideName:
424     return false;
425 
426   case DeclarationName::CXXConstructorName:
427   case DeclarationName::CXXDestructorName:
428   case DeclarationName::CXXConversionFunctionName:
429     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
430       return TInfo->getType()->containsUnexpandedParameterPack();
431 
432     return Name.getCXXNameType()->containsUnexpandedParameterPack();
433   }
434   llvm_unreachable("All name kinds handled.");
435 }
436 
isInstantiationDependent() const437 bool DeclarationNameInfo::isInstantiationDependent() const {
438   switch (Name.getNameKind()) {
439   case DeclarationName::Identifier:
440   case DeclarationName::ObjCZeroArgSelector:
441   case DeclarationName::ObjCOneArgSelector:
442   case DeclarationName::ObjCMultiArgSelector:
443   case DeclarationName::CXXOperatorName:
444   case DeclarationName::CXXLiteralOperatorName:
445   case DeclarationName::CXXUsingDirective:
446   case DeclarationName::CXXDeductionGuideName:
447     return false;
448 
449   case DeclarationName::CXXConstructorName:
450   case DeclarationName::CXXDestructorName:
451   case DeclarationName::CXXConversionFunctionName:
452     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
453       return TInfo->getType()->isInstantiationDependentType();
454 
455     return Name.getCXXNameType()->isInstantiationDependentType();
456   }
457   llvm_unreachable("All name kinds handled.");
458 }
459 
getAsString() const460 std::string DeclarationNameInfo::getAsString() const {
461   std::string Result;
462   llvm::raw_string_ostream OS(Result);
463   OS << *this;
464   return OS.str();
465 }
466 
operator <<(raw_ostream & OS,DeclarationNameInfo DNInfo)467 raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
468   LangOptions LO;
469   DNInfo.printName(OS, PrintingPolicy(LangOptions()));
470   return OS;
471 }
472 
printName(raw_ostream & OS,PrintingPolicy Policy) const473 void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
474   switch (Name.getNameKind()) {
475   case DeclarationName::Identifier:
476   case DeclarationName::ObjCZeroArgSelector:
477   case DeclarationName::ObjCOneArgSelector:
478   case DeclarationName::ObjCMultiArgSelector:
479   case DeclarationName::CXXOperatorName:
480   case DeclarationName::CXXLiteralOperatorName:
481   case DeclarationName::CXXUsingDirective:
482   case DeclarationName::CXXDeductionGuideName:
483     Name.print(OS, Policy);
484     return;
485 
486   case DeclarationName::CXXConstructorName:
487   case DeclarationName::CXXDestructorName:
488   case DeclarationName::CXXConversionFunctionName:
489     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
490       if (Name.getNameKind() == DeclarationName::CXXDestructorName)
491         OS << '~';
492       else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
493         OS << "operator ";
494       LangOptions LO;
495       Policy.adjustForCPlusPlus();
496       Policy.SuppressScope = true;
497       OS << TInfo->getType().getAsString(Policy);
498     } else
499       Name.print(OS, Policy);
500     return;
501   }
502   llvm_unreachable("Unexpected declaration name kind");
503 }
504 
getEndLocPrivate() const505 SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
506   switch (Name.getNameKind()) {
507   case DeclarationName::Identifier:
508   case DeclarationName::CXXDeductionGuideName:
509     return NameLoc;
510 
511   case DeclarationName::CXXOperatorName: {
512     unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
513     return SourceLocation::getFromRawEncoding(raw);
514   }
515 
516   case DeclarationName::CXXLiteralOperatorName: {
517     unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
518     return SourceLocation::getFromRawEncoding(raw);
519   }
520 
521   case DeclarationName::CXXConstructorName:
522   case DeclarationName::CXXDestructorName:
523   case DeclarationName::CXXConversionFunctionName:
524     if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
525       return TInfo->getTypeLoc().getEndLoc();
526     else
527       return NameLoc;
528 
529     // DNInfo work in progress: FIXME.
530   case DeclarationName::ObjCZeroArgSelector:
531   case DeclarationName::ObjCOneArgSelector:
532   case DeclarationName::ObjCMultiArgSelector:
533   case DeclarationName::CXXUsingDirective:
534     return NameLoc;
535   }
536   llvm_unreachable("Unexpected declaration name kind");
537 }
538