1 //===- DeclarationName.cpp - Declaration names implementation -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the DeclarationName and DeclarationNameTable
12 //===----------------------------------------------------------------------===//
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"
40 using namespace clang
;
42 static int compareInt(unsigned A
, unsigned B
) {
43 return (A
< B
? -1 : (A
> B
? 1 : 0));
46 int DeclarationName::compare(DeclarationName LHS
, DeclarationName RHS
) {
47 if (LHS
.getNameKind() != RHS
.getNameKind())
48 return (LHS
.getNameKind() < RHS
.getNameKind() ? -1 : 1);
50 switch (LHS
.getNameKind()) {
51 case DeclarationName::Identifier
: {
52 IdentifierInfo
*LII
= LHS
.castAsIdentifierInfo();
53 IdentifierInfo
*RII
= RHS
.castAsIdentifierInfo();
59 return LII
->getName().compare(RII
->getName());
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());
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
))) {
86 return compareInt(LN
, RN
);
89 case DeclarationName::CXXConstructorName
:
90 case DeclarationName::CXXDestructorName
:
91 case DeclarationName::CXXConversionFunctionName
:
92 if (QualTypeOrdering()(LHS
.getCXXNameType(), RHS
.getCXXNameType()))
94 if (QualTypeOrdering()(RHS
.getCXXNameType(), LHS
.getCXXNameType()))
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());
104 case DeclarationName::CXXOperatorName
:
105 return compareInt(LHS
.getCXXOverloadedOperator(),
106 RHS
.getCXXOverloadedOperator());
108 case DeclarationName::CXXLiteralOperatorName
:
109 return LHS
.getCXXLiteralIdentifier()->getName().compare(
110 RHS
.getCXXLiteralIdentifier()->getName());
112 case DeclarationName::CXXUsingDirective
:
116 llvm_unreachable("Invalid DeclarationName Kind!");
119 static void printCXXConstructorDestructorName(QualType ClassType
,
121 PrintingPolicy Policy
) {
122 // We know we're printing C++ here. Ensure we print types properly.
123 Policy
.adjustForCPlusPlus();
125 if (const RecordType
*ClassRec
= ClassType
->getAs
<RecordType
>()) {
126 OS
<< *ClassRec
->getDecl();
129 if (Policy
.SuppressTemplateArgsInCXXConstructors
) {
130 if (auto *InjTy
= ClassType
->getAs
<InjectedClassNameType
>()) {
131 OS
<< *InjTy
->getDecl();
135 ClassType
.print(OS
, Policy
);
138 void DeclarationName::print(raw_ostream
&OS
,
139 const PrintingPolicy
&Policy
) const {
140 switch (getNameKind()) {
141 case DeclarationName::Identifier
:
142 if (const IdentifierInfo
*II
= getAsIdentifierInfo()) {
143 StringRef Name
= II
->getName();
144 // If this is a mangled OpenMP variant name we strip off the mangling for
145 // printing. It should not be visible to the user at all.
146 if (II
->isMangledOpenMPVariantName()) {
147 std::pair
<StringRef
, StringRef
> NameContextPair
=
148 Name
.split(getOpenMPVariantManglingSeparatorStr());
149 OS
<< NameContextPair
.first
<< "["
150 << OMPTraitInfo(NameContextPair
.second
) << "]";
157 case DeclarationName::ObjCZeroArgSelector
:
158 case DeclarationName::ObjCOneArgSelector
:
159 case DeclarationName::ObjCMultiArgSelector
:
160 getObjCSelector().print(OS
);
163 case DeclarationName::CXXConstructorName
:
164 return printCXXConstructorDestructorName(getCXXNameType(), OS
, Policy
);
166 case DeclarationName::CXXDestructorName
:
168 return printCXXConstructorDestructorName(getCXXNameType(), OS
, Policy
);
170 case DeclarationName::CXXDeductionGuideName
:
171 OS
<< "<deduction guide for ";
172 getCXXDeductionGuideTemplate()->getDeclName().print(OS
, Policy
);
176 case DeclarationName::CXXOperatorName
: {
177 const char *OpName
= getOperatorSpelling(getCXXOverloadedOperator());
178 assert(OpName
&& "not an overloaded operator");
181 if (OpName
[0] >= 'a' && OpName
[0] <= 'z')
187 case DeclarationName::CXXLiteralOperatorName
:
188 OS
<< "operator\"\"" << getCXXLiteralIdentifier()->getName();
191 case DeclarationName::CXXConversionFunctionName
: {
193 QualType Type
= getCXXNameType();
194 if (const RecordType
*Rec
= Type
->getAs
<RecordType
>()) {
195 OS
<< *Rec
->getDecl();
198 // We know we're printing C++ here, ensure we print 'bool' properly.
199 PrintingPolicy CXXPolicy
= Policy
;
200 CXXPolicy
.adjustForCPlusPlus();
201 Type
.print(OS
, CXXPolicy
);
204 case DeclarationName::CXXUsingDirective
:
205 OS
<< "<using-directive>";
209 llvm_unreachable("Unexpected declaration name kind");
214 raw_ostream
&operator<<(raw_ostream
&OS
, DeclarationName N
) {
216 N
.print(OS
, PrintingPolicy(LO
));
222 bool DeclarationName::isDependentName() const {
223 QualType T
= getCXXNameType();
224 if (!T
.isNull() && T
->isDependentType())
227 // A class-scope deduction guide in a dependent context has a dependent name.
228 auto *TD
= getCXXDeductionGuideTemplate();
229 if (TD
&& TD
->getDeclContext()->isDependentContext())
235 std::string
DeclarationName::getAsString() const {
237 llvm::raw_string_ostream
OS(Result
);
242 void *DeclarationName::getFETokenInfoSlow() const {
243 switch (getNameKind()) {
245 llvm_unreachable("case Identifier already handled by getFETokenInfo!");
246 case CXXConstructorName
:
247 case CXXDestructorName
:
248 case CXXConversionFunctionName
:
249 return castAsCXXSpecialNameExtra()->FETokenInfo
;
250 case CXXOperatorName
:
251 return castAsCXXOperatorIdName()->FETokenInfo
;
252 case CXXDeductionGuideName
:
253 return castAsCXXDeductionGuideNameExtra()->FETokenInfo
;
254 case CXXLiteralOperatorName
:
255 return castAsCXXLiteralOperatorIdName()->FETokenInfo
;
257 llvm_unreachable("DeclarationName has no FETokenInfo!");
261 void DeclarationName::setFETokenInfoSlow(void *T
) {
262 switch (getNameKind()) {
264 llvm_unreachable("case Identifier already handled by setFETokenInfo!");
265 case CXXConstructorName
:
266 case CXXDestructorName
:
267 case CXXConversionFunctionName
:
268 castAsCXXSpecialNameExtra()->FETokenInfo
= T
;
270 case CXXOperatorName
:
271 castAsCXXOperatorIdName()->FETokenInfo
= T
;
273 case CXXDeductionGuideName
:
274 castAsCXXDeductionGuideNameExtra()->FETokenInfo
= T
;
276 case CXXLiteralOperatorName
:
277 castAsCXXLiteralOperatorIdName()->FETokenInfo
= T
;
280 llvm_unreachable("DeclarationName has no FETokenInfo!");
284 LLVM_DUMP_METHOD
void DeclarationName::dump() const {
285 llvm::errs() << *this << '\n';
288 DeclarationNameTable::DeclarationNameTable(const ASTContext
&C
) : Ctx(C
) {
289 // Initialize the overloaded operator names.
290 for (unsigned Op
= 0; Op
< NUM_OVERLOADED_OPERATORS
; ++Op
)
291 CXXOperatorNames
[Op
].Kind
= static_cast<OverloadedOperatorKind
>(Op
);
295 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl
*Template
) {
296 Template
= cast
<TemplateDecl
>(Template
->getCanonicalDecl());
298 llvm::FoldingSetNodeID ID
;
299 ID
.AddPointer(Template
);
301 void *InsertPos
= nullptr;
302 if (auto *Name
= CXXDeductionGuideNames
.FindNodeOrInsertPos(ID
, InsertPos
))
303 return DeclarationName(Name
);
305 auto *Name
= new (Ctx
) detail::CXXDeductionGuideNameExtra(Template
);
306 CXXDeductionGuideNames
.InsertNode(Name
, InsertPos
);
307 return DeclarationName(Name
);
310 DeclarationName
DeclarationNameTable::getCXXConstructorName(CanQualType Ty
) {
311 // The type of constructors is unqualified.
312 Ty
= Ty
.getUnqualifiedType();
313 // Do we already have this C++ constructor name ?
314 llvm::FoldingSetNodeID ID
;
315 ID
.AddPointer(Ty
.getAsOpaquePtr());
316 void *InsertPos
= nullptr;
317 if (auto *Name
= CXXConstructorNames
.FindNodeOrInsertPos(ID
, InsertPos
))
318 return {Name
, DeclarationName::StoredCXXConstructorName
};
320 // We have to create it.
321 auto *SpecialName
= new (Ctx
) detail::CXXSpecialNameExtra(Ty
);
322 CXXConstructorNames
.InsertNode(SpecialName
, InsertPos
);
323 return {SpecialName
, DeclarationName::StoredCXXConstructorName
};
326 DeclarationName
DeclarationNameTable::getCXXDestructorName(CanQualType Ty
) {
327 // The type of destructors is unqualified.
328 Ty
= Ty
.getUnqualifiedType();
329 // Do we already have this C++ destructor name ?
330 llvm::FoldingSetNodeID ID
;
331 ID
.AddPointer(Ty
.getAsOpaquePtr());
332 void *InsertPos
= nullptr;
333 if (auto *Name
= CXXDestructorNames
.FindNodeOrInsertPos(ID
, InsertPos
))
334 return {Name
, DeclarationName::StoredCXXDestructorName
};
336 // We have to create it.
337 auto *SpecialName
= new (Ctx
) detail::CXXSpecialNameExtra(Ty
);
338 CXXDestructorNames
.InsertNode(SpecialName
, InsertPos
);
339 return {SpecialName
, DeclarationName::StoredCXXDestructorName
};
343 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty
) {
344 // Do we already have this C++ conversion function name ?
345 llvm::FoldingSetNodeID ID
;
346 ID
.AddPointer(Ty
.getAsOpaquePtr());
347 void *InsertPos
= nullptr;
349 CXXConversionFunctionNames
.FindNodeOrInsertPos(ID
, InsertPos
))
350 return {Name
, DeclarationName::StoredCXXConversionFunctionName
};
352 // We have to create it.
353 auto *SpecialName
= new (Ctx
) detail::CXXSpecialNameExtra(Ty
);
354 CXXConversionFunctionNames
.InsertNode(SpecialName
, InsertPos
);
355 return {SpecialName
, DeclarationName::StoredCXXConversionFunctionName
};
359 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind
,
362 case DeclarationName::CXXConstructorName
:
363 return getCXXConstructorName(Ty
);
364 case DeclarationName::CXXDestructorName
:
365 return getCXXDestructorName(Ty
);
366 case DeclarationName::CXXConversionFunctionName
:
367 return getCXXConversionFunctionName(Ty
);
369 llvm_unreachable("Invalid kind in getCXXSpecialName!");
374 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo
*II
) {
375 llvm::FoldingSetNodeID ID
;
378 void *InsertPos
= nullptr;
379 if (auto *Name
= CXXLiteralOperatorNames
.FindNodeOrInsertPos(ID
, InsertPos
))
380 return DeclarationName(Name
);
382 auto *LiteralName
= new (Ctx
) detail::CXXLiteralOperatorIdName(II
);
383 CXXLiteralOperatorNames
.InsertNode(LiteralName
, InsertPos
);
384 return DeclarationName(LiteralName
);
387 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name
) {
388 switch (Name
.getNameKind()) {
389 case DeclarationName::Identifier
:
390 case DeclarationName::CXXDeductionGuideName
:
392 case DeclarationName::CXXConstructorName
:
393 case DeclarationName::CXXDestructorName
:
394 case DeclarationName::CXXConversionFunctionName
:
395 setNamedTypeLoc(nullptr);
397 case DeclarationName::CXXOperatorName
:
398 setCXXOperatorNameRange(SourceRange());
400 case DeclarationName::CXXLiteralOperatorName
:
401 setCXXLiteralOperatorNameLoc(SourceLocation());
403 case DeclarationName::ObjCZeroArgSelector
:
404 case DeclarationName::ObjCOneArgSelector
:
405 case DeclarationName::ObjCMultiArgSelector
:
408 case DeclarationName::CXXUsingDirective
:
413 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
414 switch (Name
.getNameKind()) {
415 case DeclarationName::Identifier
:
416 case DeclarationName::ObjCZeroArgSelector
:
417 case DeclarationName::ObjCOneArgSelector
:
418 case DeclarationName::ObjCMultiArgSelector
:
419 case DeclarationName::CXXOperatorName
:
420 case DeclarationName::CXXLiteralOperatorName
:
421 case DeclarationName::CXXUsingDirective
:
422 case DeclarationName::CXXDeductionGuideName
:
425 case DeclarationName::CXXConstructorName
:
426 case DeclarationName::CXXDestructorName
:
427 case DeclarationName::CXXConversionFunctionName
:
428 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo())
429 return TInfo
->getType()->containsUnexpandedParameterPack();
431 return Name
.getCXXNameType()->containsUnexpandedParameterPack();
433 llvm_unreachable("All name kinds handled.");
436 bool DeclarationNameInfo::isInstantiationDependent() const {
437 switch (Name
.getNameKind()) {
438 case DeclarationName::Identifier
:
439 case DeclarationName::ObjCZeroArgSelector
:
440 case DeclarationName::ObjCOneArgSelector
:
441 case DeclarationName::ObjCMultiArgSelector
:
442 case DeclarationName::CXXOperatorName
:
443 case DeclarationName::CXXLiteralOperatorName
:
444 case DeclarationName::CXXUsingDirective
:
445 case DeclarationName::CXXDeductionGuideName
:
448 case DeclarationName::CXXConstructorName
:
449 case DeclarationName::CXXDestructorName
:
450 case DeclarationName::CXXConversionFunctionName
:
451 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo())
452 return TInfo
->getType()->isInstantiationDependentType();
454 return Name
.getCXXNameType()->isInstantiationDependentType();
456 llvm_unreachable("All name kinds handled.");
459 std::string
DeclarationNameInfo::getAsString() const {
461 llvm::raw_string_ostream
OS(Result
);
466 raw_ostream
&clang::operator<<(raw_ostream
&OS
, DeclarationNameInfo DNInfo
) {
468 DNInfo
.printName(OS
, PrintingPolicy(LangOptions()));
472 void DeclarationNameInfo::printName(raw_ostream
&OS
, PrintingPolicy Policy
) const {
473 switch (Name
.getNameKind()) {
474 case DeclarationName::Identifier
:
475 case DeclarationName::ObjCZeroArgSelector
:
476 case DeclarationName::ObjCOneArgSelector
:
477 case DeclarationName::ObjCMultiArgSelector
:
478 case DeclarationName::CXXOperatorName
:
479 case DeclarationName::CXXLiteralOperatorName
:
480 case DeclarationName::CXXUsingDirective
:
481 case DeclarationName::CXXDeductionGuideName
:
482 Name
.print(OS
, Policy
);
485 case DeclarationName::CXXConstructorName
:
486 case DeclarationName::CXXDestructorName
:
487 case DeclarationName::CXXConversionFunctionName
:
488 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo()) {
489 if (Name
.getNameKind() == DeclarationName::CXXDestructorName
)
491 else if (Name
.getNameKind() == DeclarationName::CXXConversionFunctionName
)
494 Policy
.adjustForCPlusPlus();
495 Policy
.SuppressScope
= true;
496 OS
<< TInfo
->getType().getAsString(Policy
);
498 Name
.print(OS
, Policy
);
501 llvm_unreachable("Unexpected declaration name kind");
504 SourceLocation
DeclarationNameInfo::getEndLocPrivate() const {
505 switch (Name
.getNameKind()) {
506 case DeclarationName::Identifier
:
507 case DeclarationName::CXXDeductionGuideName
:
510 case DeclarationName::CXXOperatorName
:
511 return LocInfo
.getCXXOperatorNameEndLoc();
513 case DeclarationName::CXXLiteralOperatorName
:
514 return LocInfo
.getCXXLiteralOperatorNameLoc();
516 case DeclarationName::CXXConstructorName
:
517 case DeclarationName::CXXDestructorName
:
518 case DeclarationName::CXXConversionFunctionName
:
519 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo())
520 return TInfo
->getTypeLoc().getEndLoc();
524 // DNInfo work in progress: FIXME.
525 case DeclarationName::ObjCZeroArgSelector
:
526 case DeclarationName::ObjCOneArgSelector
:
527 case DeclarationName::ObjCMultiArgSelector
:
528 case DeclarationName::CXXUsingDirective
:
531 llvm_unreachable("Unexpected declaration name kind");