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
compareInt(unsigned A,unsigned B)41 static int compareInt(unsigned A, unsigned B) {
42 return (A < B ? -1 : (A > B ? 1 : 0));
43 }
44
compare(DeclarationName LHS,DeclarationName RHS)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
printCXXConstructorDestructorName(QualType ClassType,raw_ostream & OS,PrintingPolicy Policy)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
print(raw_ostream & OS,const PrintingPolicy & Policy) const137 void DeclarationName::print(raw_ostream &OS,
138 const PrintingPolicy &Policy) const {
139 switch (getNameKind()) {
140 case DeclarationName::Identifier:
141 if (const IdentifierInfo *II = getAsIdentifierInfo())
142 OS << II->getName();
143 return;
144
145 case DeclarationName::ObjCZeroArgSelector:
146 case DeclarationName::ObjCOneArgSelector:
147 case DeclarationName::ObjCMultiArgSelector:
148 getObjCSelector().print(OS);
149 return;
150
151 case DeclarationName::CXXConstructorName:
152 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
153
154 case DeclarationName::CXXDestructorName:
155 OS << '~';
156 return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
157
158 case DeclarationName::CXXDeductionGuideName:
159 OS << "<deduction guide for ";
160 getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
161 OS << '>';
162 return;
163
164 case DeclarationName::CXXOperatorName: {
165 const char *OpName = getOperatorSpelling(getCXXOverloadedOperator());
166 assert(OpName && "not an overloaded operator");
167
168 OS << "operator";
169 if (OpName[0] >= 'a' && OpName[0] <= 'z')
170 OS << ' ';
171 OS << OpName;
172 return;
173 }
174
175 case DeclarationName::CXXLiteralOperatorName:
176 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
177 return;
178
179 case DeclarationName::CXXConversionFunctionName: {
180 OS << "operator ";
181 QualType Type = getCXXNameType();
182 if (const RecordType *Rec = Type->getAs<RecordType>()) {
183 OS << *Rec->getDecl();
184 return;
185 }
186 // We know we're printing C++ here, ensure we print 'bool' properly.
187 PrintingPolicy CXXPolicy = Policy;
188 CXXPolicy.adjustForCPlusPlus();
189 Type.print(OS, CXXPolicy);
190 return;
191 }
192 case DeclarationName::CXXUsingDirective:
193 OS << "<using-directive>";
194 return;
195 }
196
197 llvm_unreachable("Unexpected declaration name kind");
198 }
199
200 namespace clang {
201
operator <<(raw_ostream & OS,DeclarationName N)202 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
203 LangOptions LO;
204 N.print(OS, PrintingPolicy(LO));
205 return OS;
206 }
207
208 } // namespace clang
209
isDependentName() const210 bool DeclarationName::isDependentName() const {
211 QualType T = getCXXNameType();
212 if (!T.isNull() && T->isDependentType())
213 return true;
214
215 // A class-scope deduction guide in a dependent context has a dependent name.
216 auto *TD = getCXXDeductionGuideTemplate();
217 if (TD && TD->getDeclContext()->isDependentContext())
218 return true;
219
220 return false;
221 }
222
getAsString() const223 std::string DeclarationName::getAsString() const {
224 std::string Result;
225 llvm::raw_string_ostream OS(Result);
226 OS << *this;
227 return OS.str();
228 }
229
getFETokenInfoSlow() const230 void *DeclarationName::getFETokenInfoSlow() const {
231 switch (getNameKind()) {
232 case Identifier:
233 llvm_unreachable("case Identifier already handled by getFETokenInfo!");
234 case CXXConstructorName:
235 case CXXDestructorName:
236 case CXXConversionFunctionName:
237 return castAsCXXSpecialNameExtra()->FETokenInfo;
238 case CXXOperatorName:
239 return castAsCXXOperatorIdName()->FETokenInfo;
240 case CXXDeductionGuideName:
241 return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
242 case CXXLiteralOperatorName:
243 return castAsCXXLiteralOperatorIdName()->FETokenInfo;
244 default:
245 llvm_unreachable("DeclarationName has no FETokenInfo!");
246 }
247 }
248
setFETokenInfoSlow(void * T)249 void DeclarationName::setFETokenInfoSlow(void *T) {
250 switch (getNameKind()) {
251 case Identifier:
252 llvm_unreachable("case Identifier already handled by setFETokenInfo!");
253 case CXXConstructorName:
254 case CXXDestructorName:
255 case CXXConversionFunctionName:
256 castAsCXXSpecialNameExtra()->FETokenInfo = T;
257 break;
258 case CXXOperatorName:
259 castAsCXXOperatorIdName()->FETokenInfo = T;
260 break;
261 case CXXDeductionGuideName:
262 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
263 break;
264 case CXXLiteralOperatorName:
265 castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
266 break;
267 default:
268 llvm_unreachable("DeclarationName has no FETokenInfo!");
269 }
270 }
271
dump() const272 LLVM_DUMP_METHOD void DeclarationName::dump() const {
273 llvm::errs() << *this << '\n';
274 }
275
DeclarationNameTable(const ASTContext & C)276 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
277 // Initialize the overloaded operator names.
278 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
279 CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
280 }
281
282 DeclarationName
getCXXDeductionGuideName(TemplateDecl * Template)283 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
284 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
285
286 llvm::FoldingSetNodeID ID;
287 ID.AddPointer(Template);
288
289 void *InsertPos = nullptr;
290 if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
291 return DeclarationName(Name);
292
293 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
294 CXXDeductionGuideNames.InsertNode(Name, InsertPos);
295 return DeclarationName(Name);
296 }
297
getCXXConstructorName(CanQualType Ty)298 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
299 // The type of constructors is unqualified.
300 Ty = Ty.getUnqualifiedType();
301 // Do we already have this C++ constructor name ?
302 llvm::FoldingSetNodeID ID;
303 ID.AddPointer(Ty.getAsOpaquePtr());
304 void *InsertPos = nullptr;
305 if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
306 return {Name, DeclarationName::StoredCXXConstructorName};
307
308 // We have to create it.
309 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
310 CXXConstructorNames.InsertNode(SpecialName, InsertPos);
311 return {SpecialName, DeclarationName::StoredCXXConstructorName};
312 }
313
getCXXDestructorName(CanQualType Ty)314 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
315 // The type of destructors is unqualified.
316 Ty = Ty.getUnqualifiedType();
317 // Do we already have this C++ destructor name ?
318 llvm::FoldingSetNodeID ID;
319 ID.AddPointer(Ty.getAsOpaquePtr());
320 void *InsertPos = nullptr;
321 if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
322 return {Name, DeclarationName::StoredCXXDestructorName};
323
324 // We have to create it.
325 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
326 CXXDestructorNames.InsertNode(SpecialName, InsertPos);
327 return {SpecialName, DeclarationName::StoredCXXDestructorName};
328 }
329
330 DeclarationName
getCXXConversionFunctionName(CanQualType Ty)331 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
332 // Do we already have this C++ conversion function name ?
333 llvm::FoldingSetNodeID ID;
334 ID.AddPointer(Ty.getAsOpaquePtr());
335 void *InsertPos = nullptr;
336 if (auto *Name =
337 CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
338 return {Name, DeclarationName::StoredCXXConversionFunctionName};
339
340 // We have to create it.
341 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
342 CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
343 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
344 }
345
346 DeclarationName
getCXXSpecialName(DeclarationName::NameKind Kind,CanQualType Ty)347 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
348 CanQualType Ty) {
349 switch (Kind) {
350 case DeclarationName::CXXConstructorName:
351 return getCXXConstructorName(Ty);
352 case DeclarationName::CXXDestructorName:
353 return getCXXDestructorName(Ty);
354 case DeclarationName::CXXConversionFunctionName:
355 return getCXXConversionFunctionName(Ty);
356 default:
357 llvm_unreachable("Invalid kind in getCXXSpecialName!");
358 }
359 }
360
361 DeclarationName
getCXXLiteralOperatorName(IdentifierInfo * II)362 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
363 llvm::FoldingSetNodeID ID;
364 ID.AddPointer(II);
365
366 void *InsertPos = nullptr;
367 if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
368 return DeclarationName(Name);
369
370 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
371 CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
372 return DeclarationName(LiteralName);
373 }
374
DeclarationNameLoc(DeclarationName Name)375 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
376 switch (Name.getNameKind()) {
377 case DeclarationName::Identifier:
378 case DeclarationName::CXXDeductionGuideName:
379 break;
380 case DeclarationName::CXXConstructorName:
381 case DeclarationName::CXXDestructorName:
382 case DeclarationName::CXXConversionFunctionName:
383 NamedType.TInfo = nullptr;
384 break;
385 case DeclarationName::CXXOperatorName:
386 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
387 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
388 break;
389 case DeclarationName::CXXLiteralOperatorName:
390 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
391 break;
392 case DeclarationName::ObjCZeroArgSelector:
393 case DeclarationName::ObjCOneArgSelector:
394 case DeclarationName::ObjCMultiArgSelector:
395 // FIXME: ?
396 break;
397 case DeclarationName::CXXUsingDirective:
398 break;
399 }
400 }
401
containsUnexpandedParameterPack() const402 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
403 switch (Name.getNameKind()) {
404 case DeclarationName::Identifier:
405 case DeclarationName::ObjCZeroArgSelector:
406 case DeclarationName::ObjCOneArgSelector:
407 case DeclarationName::ObjCMultiArgSelector:
408 case DeclarationName::CXXOperatorName:
409 case DeclarationName::CXXLiteralOperatorName:
410 case DeclarationName::CXXUsingDirective:
411 case DeclarationName::CXXDeductionGuideName:
412 return false;
413
414 case DeclarationName::CXXConstructorName:
415 case DeclarationName::CXXDestructorName:
416 case DeclarationName::CXXConversionFunctionName:
417 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
418 return TInfo->getType()->containsUnexpandedParameterPack();
419
420 return Name.getCXXNameType()->containsUnexpandedParameterPack();
421 }
422 llvm_unreachable("All name kinds handled.");
423 }
424
isInstantiationDependent() const425 bool DeclarationNameInfo::isInstantiationDependent() const {
426 switch (Name.getNameKind()) {
427 case DeclarationName::Identifier:
428 case DeclarationName::ObjCZeroArgSelector:
429 case DeclarationName::ObjCOneArgSelector:
430 case DeclarationName::ObjCMultiArgSelector:
431 case DeclarationName::CXXOperatorName:
432 case DeclarationName::CXXLiteralOperatorName:
433 case DeclarationName::CXXUsingDirective:
434 case DeclarationName::CXXDeductionGuideName:
435 return false;
436
437 case DeclarationName::CXXConstructorName:
438 case DeclarationName::CXXDestructorName:
439 case DeclarationName::CXXConversionFunctionName:
440 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
441 return TInfo->getType()->isInstantiationDependentType();
442
443 return Name.getCXXNameType()->isInstantiationDependentType();
444 }
445 llvm_unreachable("All name kinds handled.");
446 }
447
getAsString() const448 std::string DeclarationNameInfo::getAsString() const {
449 std::string Result;
450 llvm::raw_string_ostream OS(Result);
451 OS << *this;
452 return OS.str();
453 }
454
operator <<(raw_ostream & OS,DeclarationNameInfo DNInfo)455 raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
456 LangOptions LO;
457 DNInfo.printName(OS, PrintingPolicy(LangOptions()));
458 return OS;
459 }
460
printName(raw_ostream & OS,PrintingPolicy Policy) const461 void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
462 switch (Name.getNameKind()) {
463 case DeclarationName::Identifier:
464 case DeclarationName::ObjCZeroArgSelector:
465 case DeclarationName::ObjCOneArgSelector:
466 case DeclarationName::ObjCMultiArgSelector:
467 case DeclarationName::CXXOperatorName:
468 case DeclarationName::CXXLiteralOperatorName:
469 case DeclarationName::CXXUsingDirective:
470 case DeclarationName::CXXDeductionGuideName:
471 Name.print(OS, Policy);
472 return;
473
474 case DeclarationName::CXXConstructorName:
475 case DeclarationName::CXXDestructorName:
476 case DeclarationName::CXXConversionFunctionName:
477 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
478 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
479 OS << '~';
480 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
481 OS << "operator ";
482 LangOptions LO;
483 Policy.adjustForCPlusPlus();
484 Policy.SuppressScope = true;
485 OS << TInfo->getType().getAsString(Policy);
486 } else
487 Name.print(OS, Policy);
488 return;
489 }
490 llvm_unreachable("Unexpected declaration name kind");
491 }
492
getEndLocPrivate() const493 SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
494 switch (Name.getNameKind()) {
495 case DeclarationName::Identifier:
496 case DeclarationName::CXXDeductionGuideName:
497 return NameLoc;
498
499 case DeclarationName::CXXOperatorName: {
500 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
501 return SourceLocation::getFromRawEncoding(raw);
502 }
503
504 case DeclarationName::CXXLiteralOperatorName: {
505 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
506 return SourceLocation::getFromRawEncoding(raw);
507 }
508
509 case DeclarationName::CXXConstructorName:
510 case DeclarationName::CXXDestructorName:
511 case DeclarationName::CXXConversionFunctionName:
512 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
513 return TInfo->getTypeLoc().getEndLoc();
514 else
515 return NameLoc;
516
517 // DNInfo work in progress: FIXME.
518 case DeclarationName::ObjCZeroArgSelector:
519 case DeclarationName::ObjCOneArgSelector:
520 case DeclarationName::ObjCMultiArgSelector:
521 case DeclarationName::CXXUsingDirective:
522 return NameLoc;
523 }
524 llvm_unreachable("Unexpected declaration name kind");
525 }
526