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
40using namespace clang;
41
42static int compareInt(unsigned A, unsigned B) {
43 return (A < B ? -1 : (A > B ? 1 : 0));
44}
45
46int 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(RHS: 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 RHS: RHSSelector.getAsIdentifierInfo()->getName());
72 }
73 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
74 for (unsigned I = 0, N = std::min(a: LN, b: RN); I != N; ++I) {
75 if (int Compare = LHSSelector.getNameForSlot(argIndex: I).compare(
76 RHS: RHSSelector.getNameForSlot(argIndex: I)))
77 return Compare;
78 }
79
80 return compareInt(A: LN, B: RN);
81 }
82
83 case DeclarationName::CXXConstructorName:
84 case DeclarationName::CXXDestructorName:
85 case DeclarationName::CXXConversionFunctionName:
86 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
87 return -1;
88 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
89 return 1;
90 return 0;
91
92 case DeclarationName::CXXDeductionGuideName:
93 // We never want to compare deduction guide names for templates from
94 // different scopes, so just compare the template-name.
95 return compare(LHS: LHS.getCXXDeductionGuideTemplate()->getDeclName(),
96 RHS: RHS.getCXXDeductionGuideTemplate()->getDeclName());
97
98 case DeclarationName::CXXOperatorName:
99 return compareInt(A: LHS.getCXXOverloadedOperator(),
100 B: RHS.getCXXOverloadedOperator());
101
102 case DeclarationName::CXXLiteralOperatorName:
103 return LHS.getCXXLiteralIdentifier()->getName().compare(
104 RHS: RHS.getCXXLiteralIdentifier()->getName());
105
106 case DeclarationName::CXXUsingDirective:
107 return 0;
108 }
109
110 llvm_unreachable("Invalid DeclarationName Kind!");
111}
112
113static void printCXXConstructorDestructorName(QualType ClassType,
114 raw_ostream &OS,
115 PrintingPolicy Policy) {
116 // We know we're printing C++ here. Ensure we print types properly.
117 Policy.adjustForCPlusPlus();
118
119 if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
120 ClassRec->getDecl()->printName(OS, Policy);
121 return;
122 }
123 if (Policy.SuppressTemplateArgsInCXXConstructors) {
124 if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
125 InjTy->getDecl()->printName(OS, Policy);
126 return;
127 }
128 }
129 ClassType.print(OS, Policy);
130}
131
132void DeclarationName::print(raw_ostream &OS,
133 const PrintingPolicy &Policy) const {
134 switch (getNameKind()) {
135 case DeclarationName::Identifier:
136 if (const IdentifierInfo *II = getAsIdentifierInfo()) {
137 StringRef Name = II->getName();
138 // If this is a mangled OpenMP variant name we strip off the mangling for
139 // printing. It should not be visible to the user at all.
140 if (II->isMangledOpenMPVariantName()) {
141 std::pair<StringRef, StringRef> NameContextPair =
142 Name.split(Separator: getOpenMPVariantManglingSeparatorStr());
143 OS << NameContextPair.first << "["
144 << OMPTraitInfo(NameContextPair.second) << "]";
145 } else {
146 OS << Name;
147 }
148 }
149 return;
150
151 case DeclarationName::ObjCZeroArgSelector:
152 case DeclarationName::ObjCOneArgSelector:
153 case DeclarationName::ObjCMultiArgSelector:
154 getObjCSelector().print(OS);
155 return;
156
157 case DeclarationName::CXXConstructorName:
158 return printCXXConstructorDestructorName(ClassType: getCXXNameType(), OS, Policy);
159
160 case DeclarationName::CXXDestructorName:
161 OS << '~';
162 return printCXXConstructorDestructorName(ClassType: getCXXNameType(), OS, Policy);
163
164 case DeclarationName::CXXDeductionGuideName:
165 OS << "<deduction guide for ";
166 getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
167 OS << '>';
168 return;
169
170 case DeclarationName::CXXOperatorName: {
171 const char *OpName = getOperatorSpelling(Operator: 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, Policy: 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
206namespace clang {
207
208raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
209 LangOptions LO;
210 N.print(OS, Policy: PrintingPolicy(LO));
211 return OS;
212}
213
214} // namespace clang
215
216bool 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
229std::string DeclarationName::getAsString() const {
230 std::string Result;
231 llvm::raw_string_ostream OS(Result);
232 OS << *this;
233 return Result;
234}
235
236void *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
255void 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
278LLVM_DUMP_METHOD void DeclarationName::dump() const {
279 llvm::errs() << *this << '\n';
280}
281
282DeclarationNameTable::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
288DeclarationName
289DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
290 Template = cast<TemplateDecl>(Val: Template->getCanonicalDecl());
291
292 llvm::FoldingSetNodeID ID;
293 ID.AddPointer(Ptr: 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(N: Name, InsertPos);
301 return DeclarationName(Name);
302}
303
304DeclarationName 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(Ptr: 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(N: SpecialName, InsertPos);
317 return {SpecialName, DeclarationName::StoredCXXConstructorName};
318}
319
320DeclarationName 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(Ptr: 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(N: SpecialName, InsertPos);
333 return {SpecialName, DeclarationName::StoredCXXDestructorName};
334}
335
336DeclarationName
337DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
338 // Do we already have this C++ conversion function name ?
339 llvm::FoldingSetNodeID ID;
340 ID.AddPointer(Ptr: 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(N: SpecialName, InsertPos);
349 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
350}
351
352DeclarationName
353DeclarationNameTable::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
367DeclarationName
368DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo *II) {
369 llvm::FoldingSetNodeID ID;
370 ID.AddPointer(Ptr: 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(N: LiteralName, InsertPos);
378 return DeclarationName(LiteralName);
379}
380
381DeclarationNameLoc::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 setNamedTypeLoc(nullptr);
390 break;
391 case DeclarationName::CXXOperatorName:
392 setCXXOperatorNameRange(SourceRange());
393 break;
394 case DeclarationName::CXXLiteralOperatorName:
395 setCXXLiteralOperatorNameLoc(SourceLocation());
396 break;
397 case DeclarationName::ObjCZeroArgSelector:
398 case DeclarationName::ObjCOneArgSelector:
399 case DeclarationName::ObjCMultiArgSelector:
400 // FIXME: ?
401 break;
402 case DeclarationName::CXXUsingDirective:
403 break;
404 }
405}
406
407bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
408 switch (Name.getNameKind()) {
409 case DeclarationName::Identifier:
410 case DeclarationName::ObjCZeroArgSelector:
411 case DeclarationName::ObjCOneArgSelector:
412 case DeclarationName::ObjCMultiArgSelector:
413 case DeclarationName::CXXOperatorName:
414 case DeclarationName::CXXLiteralOperatorName:
415 case DeclarationName::CXXUsingDirective:
416 case DeclarationName::CXXDeductionGuideName:
417 return false;
418
419 case DeclarationName::CXXConstructorName:
420 case DeclarationName::CXXDestructorName:
421 case DeclarationName::CXXConversionFunctionName:
422 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
423 return TInfo->getType()->containsUnexpandedParameterPack();
424
425 return Name.getCXXNameType()->containsUnexpandedParameterPack();
426 }
427 llvm_unreachable("All name kinds handled.");
428}
429
430bool DeclarationNameInfo::isInstantiationDependent() const {
431 switch (Name.getNameKind()) {
432 case DeclarationName::Identifier:
433 case DeclarationName::ObjCZeroArgSelector:
434 case DeclarationName::ObjCOneArgSelector:
435 case DeclarationName::ObjCMultiArgSelector:
436 case DeclarationName::CXXOperatorName:
437 case DeclarationName::CXXLiteralOperatorName:
438 case DeclarationName::CXXUsingDirective:
439 case DeclarationName::CXXDeductionGuideName:
440 return false;
441
442 case DeclarationName::CXXConstructorName:
443 case DeclarationName::CXXDestructorName:
444 case DeclarationName::CXXConversionFunctionName:
445 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
446 return TInfo->getType()->isInstantiationDependentType();
447
448 return Name.getCXXNameType()->isInstantiationDependentType();
449 }
450 llvm_unreachable("All name kinds handled.");
451}
452
453std::string DeclarationNameInfo::getAsString() const {
454 std::string Result;
455 llvm::raw_string_ostream OS(Result);
456 OS << *this;
457 return Result;
458}
459
460raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
461 LangOptions LO;
462 DNInfo.printName(OS, Policy: PrintingPolicy(LangOptions()));
463 return OS;
464}
465
466void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
467 switch (Name.getNameKind()) {
468 case DeclarationName::Identifier:
469 case DeclarationName::ObjCZeroArgSelector:
470 case DeclarationName::ObjCOneArgSelector:
471 case DeclarationName::ObjCMultiArgSelector:
472 case DeclarationName::CXXOperatorName:
473 case DeclarationName::CXXLiteralOperatorName:
474 case DeclarationName::CXXUsingDirective:
475 case DeclarationName::CXXDeductionGuideName:
476 Name.print(OS, Policy);
477 return;
478
479 case DeclarationName::CXXConstructorName:
480 case DeclarationName::CXXDestructorName:
481 case DeclarationName::CXXConversionFunctionName:
482 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
483 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
484 OS << '~';
485 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
486 OS << "operator ";
487 LangOptions LO;
488 Policy.adjustForCPlusPlus();
489 Policy.SuppressScope = true;
490 OS << TInfo->getType().getAsString(Policy);
491 } else
492 Name.print(OS, Policy);
493 return;
494 }
495 llvm_unreachable("Unexpected declaration name kind");
496}
497
498SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
499 switch (Name.getNameKind()) {
500 case DeclarationName::Identifier:
501 case DeclarationName::CXXDeductionGuideName:
502 return NameLoc;
503
504 case DeclarationName::CXXOperatorName:
505 return LocInfo.getCXXOperatorNameEndLoc();
506
507 case DeclarationName::CXXLiteralOperatorName:
508 return LocInfo.getCXXLiteralOperatorNameLoc();
509
510 case DeclarationName::CXXConstructorName:
511 case DeclarationName::CXXDestructorName:
512 case DeclarationName::CXXConversionFunctionName:
513 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
514 return TInfo->getTypeLoc().getEndLoc();
515 else
516 return NameLoc;
517
518 // DNInfo work in progress: FIXME.
519 case DeclarationName::ObjCZeroArgSelector:
520 case DeclarationName::ObjCOneArgSelector:
521 case DeclarationName::ObjCMultiArgSelector:
522 case DeclarationName::CXXUsingDirective:
523 return NameLoc;
524 }
525 llvm_unreachable("Unexpected declaration name kind");
526}
527