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