1 //===- DeclarationName.cpp - Declaration names implementation -------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the DeclarationName and DeclarationNameTable
11 // classes.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "clang/AST/DeclarationName.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclBase.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclTemplate.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)138 void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
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 static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
166 nullptr,
167 #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
168 Spelling,
169 #include "clang/Basic/OperatorKinds.def"
170 };
171 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
172 assert(OpName && "not an overloaded operator");
173
174 OS << "operator";
175 if (OpName[0] >= 'a' && OpName[0] <= 'z')
176 OS << ' ';
177 OS << OpName;
178 return;
179 }
180
181 case DeclarationName::CXXLiteralOperatorName:
182 OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
183 return;
184
185 case DeclarationName::CXXConversionFunctionName: {
186 OS << "operator ";
187 QualType Type = getCXXNameType();
188 if (const RecordType *Rec = Type->getAs<RecordType>()) {
189 OS << *Rec->getDecl();
190 return;
191 }
192 // We know we're printing C++ here, ensure we print 'bool' properly.
193 PrintingPolicy CXXPolicy = Policy;
194 CXXPolicy.adjustForCPlusPlus();
195 Type.print(OS, CXXPolicy);
196 return;
197 }
198 case DeclarationName::CXXUsingDirective:
199 OS << "<using-directive>";
200 return;
201 }
202
203 llvm_unreachable("Unexpected declaration name kind");
204 }
205
206 namespace clang {
207
operator <<(raw_ostream & OS,DeclarationName N)208 raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
209 LangOptions LO;
210 N.print(OS, PrintingPolicy(LO));
211 return OS;
212 }
213
214 } // namespace clang
215
isDependentName() const216 bool DeclarationName::isDependentName() const {
217 QualType T = getCXXNameType();
218 if (!T.isNull() && T->isDependentType())
219 return true;
220
221 // A class-scope deduction guide in a dependent context has a dependent name.
222 auto *TD = getCXXDeductionGuideTemplate();
223 if (TD && TD->getDeclContext()->isDependentContext())
224 return true;
225
226 return false;
227 }
228
getAsString() const229 std::string DeclarationName::getAsString() const {
230 std::string Result;
231 llvm::raw_string_ostream OS(Result);
232 OS << *this;
233 return OS.str();
234 }
235
getFETokenInfoSlow() const236 void *DeclarationName::getFETokenInfoSlow() const {
237 switch (getNameKind()) {
238 case Identifier:
239 llvm_unreachable("case Identifier already handled by getFETokenInfo!");
240 case CXXConstructorName:
241 case CXXDestructorName:
242 case CXXConversionFunctionName:
243 return castAsCXXSpecialNameExtra()->FETokenInfo;
244 case CXXOperatorName:
245 return castAsCXXOperatorIdName()->FETokenInfo;
246 case CXXDeductionGuideName:
247 return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
248 case CXXLiteralOperatorName:
249 return castAsCXXLiteralOperatorIdName()->FETokenInfo;
250 default:
251 llvm_unreachable("DeclarationName has no FETokenInfo!");
252 }
253 }
254
setFETokenInfoSlow(void * T)255 void DeclarationName::setFETokenInfoSlow(void *T) {
256 switch (getNameKind()) {
257 case Identifier:
258 llvm_unreachable("case Identifier already handled by setFETokenInfo!");
259 case CXXConstructorName:
260 case CXXDestructorName:
261 case CXXConversionFunctionName:
262 castAsCXXSpecialNameExtra()->FETokenInfo = T;
263 break;
264 case CXXOperatorName:
265 castAsCXXOperatorIdName()->FETokenInfo = T;
266 break;
267 case CXXDeductionGuideName:
268 castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
269 break;
270 case CXXLiteralOperatorName:
271 castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
272 break;
273 default:
274 llvm_unreachable("DeclarationName has no FETokenInfo!");
275 }
276 }
277
dump() const278 LLVM_DUMP_METHOD void DeclarationName::dump() const {
279 llvm::errs() << *this << '\n';
280 }
281
DeclarationNameTable(const ASTContext & C)282 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
283 // Initialize the overloaded operator names.
284 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
285 CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
286 }
287
288 DeclarationName
getCXXDeductionGuideName(TemplateDecl * Template)289 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
290 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
291
292 llvm::FoldingSetNodeID ID;
293 ID.AddPointer(Template);
294
295 void *InsertPos = nullptr;
296 if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
297 return DeclarationName(Name);
298
299 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
300 CXXDeductionGuideNames.InsertNode(Name, InsertPos);
301 return DeclarationName(Name);
302 }
303
getCXXConstructorName(CanQualType Ty)304 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
305 // The type of constructors is unqualified.
306 Ty = Ty.getUnqualifiedType();
307 // Do we already have this C++ constructor name ?
308 llvm::FoldingSetNodeID ID;
309 ID.AddPointer(Ty.getAsOpaquePtr());
310 void *InsertPos = nullptr;
311 if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
312 return {Name, DeclarationName::StoredCXXConstructorName};
313
314 // We have to create it.
315 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
316 CXXConstructorNames.InsertNode(SpecialName, InsertPos);
317 return {SpecialName, DeclarationName::StoredCXXConstructorName};
318 }
319
getCXXDestructorName(CanQualType Ty)320 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
321 // The type of destructors is unqualified.
322 Ty = Ty.getUnqualifiedType();
323 // Do we already have this C++ destructor name ?
324 llvm::FoldingSetNodeID ID;
325 ID.AddPointer(Ty.getAsOpaquePtr());
326 void *InsertPos = nullptr;
327 if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
328 return {Name, DeclarationName::StoredCXXDestructorName};
329
330 // We have to create it.
331 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
332 CXXDestructorNames.InsertNode(SpecialName, InsertPos);
333 return {SpecialName, DeclarationName::StoredCXXDestructorName};
334 }
335
336 DeclarationName
getCXXConversionFunctionName(CanQualType Ty)337 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
338 // Do we already have this C++ conversion function name ?
339 llvm::FoldingSetNodeID ID;
340 ID.AddPointer(Ty.getAsOpaquePtr());
341 void *InsertPos = nullptr;
342 if (auto *Name =
343 CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
344 return {Name, DeclarationName::StoredCXXConversionFunctionName};
345
346 // We have to create it.
347 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
348 CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
349 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
350 }
351
352 DeclarationName
getCXXSpecialName(DeclarationName::NameKind Kind,CanQualType Ty)353 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
354 CanQualType Ty) {
355 switch (Kind) {
356 case DeclarationName::CXXConstructorName:
357 return getCXXConstructorName(Ty);
358 case DeclarationName::CXXDestructorName:
359 return getCXXDestructorName(Ty);
360 case DeclarationName::CXXConversionFunctionName:
361 return getCXXConversionFunctionName(Ty);
362 default:
363 llvm_unreachable("Invalid kind in getCXXSpecialName!");
364 }
365 }
366
367 DeclarationName
getCXXLiteralOperatorName(IdentifierInfo * II)368 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
369 llvm::FoldingSetNodeID ID;
370 ID.AddPointer(II);
371
372 void *InsertPos = nullptr;
373 if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
374 return DeclarationName(Name);
375
376 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
377 CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
378 return DeclarationName(LiteralName);
379 }
380
DeclarationNameLoc(DeclarationName Name)381 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
382 switch (Name.getNameKind()) {
383 case DeclarationName::Identifier:
384 case DeclarationName::CXXDeductionGuideName:
385 break;
386 case DeclarationName::CXXConstructorName:
387 case DeclarationName::CXXDestructorName:
388 case DeclarationName::CXXConversionFunctionName:
389 NamedType.TInfo = nullptr;
390 break;
391 case DeclarationName::CXXOperatorName:
392 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
393 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
394 break;
395 case DeclarationName::CXXLiteralOperatorName:
396 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
397 break;
398 case DeclarationName::ObjCZeroArgSelector:
399 case DeclarationName::ObjCOneArgSelector:
400 case DeclarationName::ObjCMultiArgSelector:
401 // FIXME: ?
402 break;
403 case DeclarationName::CXXUsingDirective:
404 break;
405 }
406 }
407
containsUnexpandedParameterPack() const408 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
409 switch (Name.getNameKind()) {
410 case DeclarationName::Identifier:
411 case DeclarationName::ObjCZeroArgSelector:
412 case DeclarationName::ObjCOneArgSelector:
413 case DeclarationName::ObjCMultiArgSelector:
414 case DeclarationName::CXXOperatorName:
415 case DeclarationName::CXXLiteralOperatorName:
416 case DeclarationName::CXXUsingDirective:
417 case DeclarationName::CXXDeductionGuideName:
418 return false;
419
420 case DeclarationName::CXXConstructorName:
421 case DeclarationName::CXXDestructorName:
422 case DeclarationName::CXXConversionFunctionName:
423 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
424 return TInfo->getType()->containsUnexpandedParameterPack();
425
426 return Name.getCXXNameType()->containsUnexpandedParameterPack();
427 }
428 llvm_unreachable("All name kinds handled.");
429 }
430
isInstantiationDependent() const431 bool DeclarationNameInfo::isInstantiationDependent() const {
432 switch (Name.getNameKind()) {
433 case DeclarationName::Identifier:
434 case DeclarationName::ObjCZeroArgSelector:
435 case DeclarationName::ObjCOneArgSelector:
436 case DeclarationName::ObjCMultiArgSelector:
437 case DeclarationName::CXXOperatorName:
438 case DeclarationName::CXXLiteralOperatorName:
439 case DeclarationName::CXXUsingDirective:
440 case DeclarationName::CXXDeductionGuideName:
441 return false;
442
443 case DeclarationName::CXXConstructorName:
444 case DeclarationName::CXXDestructorName:
445 case DeclarationName::CXXConversionFunctionName:
446 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
447 return TInfo->getType()->isInstantiationDependentType();
448
449 return Name.getCXXNameType()->isInstantiationDependentType();
450 }
451 llvm_unreachable("All name kinds handled.");
452 }
453
getAsString() const454 std::string DeclarationNameInfo::getAsString() const {
455 std::string Result;
456 llvm::raw_string_ostream OS(Result);
457 printName(OS);
458 return OS.str();
459 }
460
printName(raw_ostream & OS) const461 void DeclarationNameInfo::printName(raw_ostream &OS) 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 OS << Name;
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 LO.CPlusPlus = true;
484 LO.Bool = true;
485 PrintingPolicy PP(LO);
486 PP.SuppressScope = true;
487 OS << TInfo->getType().getAsString(PP);
488 } else
489 OS << Name;
490 return;
491 }
492 llvm_unreachable("Unexpected declaration name kind");
493 }
494
getEndLocPrivate() const495 SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
496 switch (Name.getNameKind()) {
497 case DeclarationName::Identifier:
498 case DeclarationName::CXXDeductionGuideName:
499 return NameLoc;
500
501 case DeclarationName::CXXOperatorName: {
502 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
503 return SourceLocation::getFromRawEncoding(raw);
504 }
505
506 case DeclarationName::CXXLiteralOperatorName: {
507 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
508 return SourceLocation::getFromRawEncoding(raw);
509 }
510
511 case DeclarationName::CXXConstructorName:
512 case DeclarationName::CXXDestructorName:
513 case DeclarationName::CXXConversionFunctionName:
514 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
515 return TInfo->getTypeLoc().getEndLoc();
516 else
517 return NameLoc;
518
519 // DNInfo work in progress: FIXME.
520 case DeclarationName::ObjCZeroArgSelector:
521 case DeclarationName::ObjCOneArgSelector:
522 case DeclarationName::ObjCMultiArgSelector:
523 case DeclarationName::CXXUsingDirective:
524 return NameLoc;
525 }
526 llvm_unreachable("Unexpected declaration name kind");
527 }
528