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 llvm::FoldingSetInsertToken Token;
295 if (auto *Name = CXXDeductionGuideNames.lookup(ID, Token))
296 return DeclarationName(Name);
297
298 auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
299 CXXDeductionGuideNames.insert(N: Name, Token);
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 llvm::FoldingSetInsertToken Token;
310 if (auto *Name = CXXConstructorNames.lookup(ID, Token))
311 return {Name, DeclarationName::StoredCXXConstructorName};
312
313 // We have to create it.
314 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
315 CXXConstructorNames.insert(N: SpecialName, Token);
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 llvm::FoldingSetInsertToken Token;
326 if (auto *Name = CXXDestructorNames.lookup(ID, Token))
327 return {Name, DeclarationName::StoredCXXDestructorName};
328
329 // We have to create it.
330 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
331 CXXDestructorNames.insert(N: SpecialName, Token);
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 llvm::FoldingSetInsertToken Token;
341 if (auto *Name = CXXConversionFunctionNames.lookup(ID, Token))
342 return {Name, DeclarationName::StoredCXXConversionFunctionName};
343
344 // We have to create it.
345 auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
346 CXXConversionFunctionNames.insert(N: SpecialName, Token);
347 return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
348}
349
350DeclarationName
351DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
352 CanQualType Ty) {
353 switch (Kind) {
354 case DeclarationName::CXXConstructorName:
355 return getCXXConstructorName(Ty);
356 case DeclarationName::CXXDestructorName:
357 return getCXXDestructorName(Ty);
358 case DeclarationName::CXXConversionFunctionName:
359 return getCXXConversionFunctionName(Ty);
360 default:
361 llvm_unreachable("Invalid kind in getCXXSpecialName!");
362 }
363}
364
365DeclarationName
366DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo *II) {
367 llvm::FoldingSetNodeID ID;
368 ID.AddPointer(Ptr: II);
369
370 llvm::FoldingSetInsertToken Token;
371 if (auto *Name = CXXLiteralOperatorNames.lookup(ID, Token))
372 return DeclarationName(Name);
373
374 auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
375 CXXLiteralOperatorNames.insert(N: LiteralName, Token);
376 return DeclarationName(LiteralName);
377}
378
379DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
380 switch (Name.getNameKind()) {
381 case DeclarationName::Identifier:
382 case DeclarationName::CXXDeductionGuideName:
383 break;
384 case DeclarationName::CXXConstructorName:
385 case DeclarationName::CXXDestructorName:
386 case DeclarationName::CXXConversionFunctionName:
387 setNamedTypeLoc(nullptr);
388 break;
389 case DeclarationName::CXXOperatorName:
390 setCXXOperatorNameRange(SourceRange());
391 break;
392 case DeclarationName::CXXLiteralOperatorName:
393 setCXXLiteralOperatorNameLoc(SourceLocation());
394 break;
395 case DeclarationName::ObjCZeroArgSelector:
396 case DeclarationName::ObjCOneArgSelector:
397 case DeclarationName::ObjCMultiArgSelector:
398 // FIXME: ?
399 break;
400 case DeclarationName::CXXUsingDirective:
401 break;
402 }
403}
404
405bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
406 switch (Name.getNameKind()) {
407 case DeclarationName::Identifier:
408 case DeclarationName::ObjCZeroArgSelector:
409 case DeclarationName::ObjCOneArgSelector:
410 case DeclarationName::ObjCMultiArgSelector:
411 case DeclarationName::CXXOperatorName:
412 case DeclarationName::CXXLiteralOperatorName:
413 case DeclarationName::CXXUsingDirective:
414 case DeclarationName::CXXDeductionGuideName:
415 return false;
416
417 case DeclarationName::CXXConstructorName:
418 case DeclarationName::CXXDestructorName:
419 case DeclarationName::CXXConversionFunctionName:
420 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
421 return TInfo->getType()->containsUnexpandedParameterPack();
422
423 return Name.getCXXNameType()->containsUnexpandedParameterPack();
424 }
425 llvm_unreachable("All name kinds handled.");
426}
427
428bool DeclarationNameInfo::isInstantiationDependent() const {
429 switch (Name.getNameKind()) {
430 case DeclarationName::Identifier:
431 case DeclarationName::ObjCZeroArgSelector:
432 case DeclarationName::ObjCOneArgSelector:
433 case DeclarationName::ObjCMultiArgSelector:
434 case DeclarationName::CXXOperatorName:
435 case DeclarationName::CXXLiteralOperatorName:
436 case DeclarationName::CXXUsingDirective:
437 case DeclarationName::CXXDeductionGuideName:
438 return false;
439
440 case DeclarationName::CXXConstructorName:
441 case DeclarationName::CXXDestructorName:
442 case DeclarationName::CXXConversionFunctionName:
443 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
444 return TInfo->getType()->isInstantiationDependentType();
445
446 return Name.getCXXNameType()->isInstantiationDependentType();
447 }
448 llvm_unreachable("All name kinds handled.");
449}
450
451std::string DeclarationNameInfo::getAsString() const {
452 std::string Result;
453 llvm::raw_string_ostream OS(Result);
454 OS << *this;
455 return Result;
456}
457
458raw_ostream &clang::operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo) {
459 LangOptions LO;
460 DNInfo.printName(OS, Policy: PrintingPolicy(LangOptions()));
461 return OS;
462}
463
464void DeclarationNameInfo::printName(raw_ostream &OS, PrintingPolicy Policy) const {
465 switch (Name.getNameKind()) {
466 case DeclarationName::Identifier:
467 case DeclarationName::ObjCZeroArgSelector:
468 case DeclarationName::ObjCOneArgSelector:
469 case DeclarationName::ObjCMultiArgSelector:
470 case DeclarationName::CXXOperatorName:
471 case DeclarationName::CXXLiteralOperatorName:
472 case DeclarationName::CXXUsingDirective:
473 case DeclarationName::CXXDeductionGuideName:
474 Name.print(OS, Policy);
475 return;
476
477 case DeclarationName::CXXConstructorName:
478 case DeclarationName::CXXDestructorName:
479 case DeclarationName::CXXConversionFunctionName:
480 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
481 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
482 OS << '~';
483 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
484 OS << "operator ";
485 LangOptions LO;
486 Policy.adjustForCPlusPlus();
487 Policy.SuppressScope = true;
488 OS << TInfo->getType().getAsString(Policy);
489 } else
490 Name.print(OS, Policy);
491 return;
492 }
493 llvm_unreachable("Unexpected declaration name kind");
494}
495
496SourceLocation DeclarationNameInfo::getEndLocPrivate() const {
497 switch (Name.getNameKind()) {
498 case DeclarationName::Identifier:
499 case DeclarationName::CXXDeductionGuideName:
500 return NameLoc;
501
502 case DeclarationName::CXXOperatorName:
503 return LocInfo.getCXXOperatorNameEndLoc();
504
505 case DeclarationName::CXXLiteralOperatorName:
506 return LocInfo.getCXXLiteralOperatorNameLoc();
507
508 case DeclarationName::CXXConstructorName:
509 case DeclarationName::CXXDestructorName:
510 case DeclarationName::CXXConversionFunctionName:
511 if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
512 return TInfo->getTypeLoc().getEndLoc();
513 else
514 return NameLoc;
515
516 // DNInfo work in progress: FIXME.
517 case DeclarationName::ObjCZeroArgSelector:
518 case DeclarationName::ObjCOneArgSelector:
519 case DeclarationName::ObjCMultiArgSelector:
520 case DeclarationName::CXXUsingDirective:
521 return NameLoc;
522 }
523 llvm_unreachable("Unexpected declaration name kind");
524}
525