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