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 if (int Compare
= LHSSelector
.getNameForSlot(I
).compare(
76 RHSSelector
.getNameForSlot(I
)))
80 return compareInt(LN
, RN
);
83 case DeclarationName::CXXConstructorName
:
84 case DeclarationName::CXXDestructorName
:
85 case DeclarationName::CXXConversionFunctionName
:
86 if (QualTypeOrdering()(LHS
.getCXXNameType(), RHS
.getCXXNameType()))
88 if (QualTypeOrdering()(RHS
.getCXXNameType(), LHS
.getCXXNameType()))
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
.getCXXDeductionGuideTemplate()->getDeclName(),
96 RHS
.getCXXDeductionGuideTemplate()->getDeclName());
98 case DeclarationName::CXXOperatorName
:
99 return compareInt(LHS
.getCXXOverloadedOperator(),
100 RHS
.getCXXOverloadedOperator());
102 case DeclarationName::CXXLiteralOperatorName
:
103 return LHS
.getCXXLiteralIdentifier()->getName().compare(
104 RHS
.getCXXLiteralIdentifier()->getName());
106 case DeclarationName::CXXUsingDirective
:
110 llvm_unreachable("Invalid DeclarationName Kind!");
113 static void printCXXConstructorDestructorName(QualType ClassType
,
115 PrintingPolicy Policy
) {
116 // We know we're printing C++ here. Ensure we print types properly.
117 Policy
.adjustForCPlusPlus();
119 if (const RecordType
*ClassRec
= ClassType
->getAs
<RecordType
>()) {
120 ClassRec
->getDecl()->printName(OS
, Policy
);
123 if (Policy
.SuppressTemplateArgsInCXXConstructors
) {
124 if (auto *InjTy
= ClassType
->getAs
<InjectedClassNameType
>()) {
125 InjTy
->getDecl()->printName(OS
, Policy
);
129 ClassType
.print(OS
, Policy
);
132 void 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(getOpenMPVariantManglingSeparatorStr());
143 OS
<< NameContextPair
.first
<< "["
144 << OMPTraitInfo(NameContextPair
.second
) << "]";
151 case DeclarationName::ObjCZeroArgSelector
:
152 case DeclarationName::ObjCOneArgSelector
:
153 case DeclarationName::ObjCMultiArgSelector
:
154 getObjCSelector().print(OS
);
157 case DeclarationName::CXXConstructorName
:
158 return printCXXConstructorDestructorName(getCXXNameType(), OS
, Policy
);
160 case DeclarationName::CXXDestructorName
:
162 return printCXXConstructorDestructorName(getCXXNameType(), OS
, Policy
);
164 case DeclarationName::CXXDeductionGuideName
:
165 OS
<< "<deduction guide for ";
166 getCXXDeductionGuideTemplate()->getDeclName().print(OS
, Policy
);
170 case DeclarationName::CXXOperatorName
: {
171 const char *OpName
= getOperatorSpelling(getCXXOverloadedOperator());
172 assert(OpName
&& "not an overloaded operator");
175 if (OpName
[0] >= 'a' && OpName
[0] <= 'z')
181 case DeclarationName::CXXLiteralOperatorName
:
182 OS
<< "operator\"\"" << getCXXLiteralIdentifier()->getName();
185 case DeclarationName::CXXConversionFunctionName
: {
187 QualType Type
= getCXXNameType();
188 if (const RecordType
*Rec
= Type
->getAs
<RecordType
>()) {
189 OS
<< *Rec
->getDecl();
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
);
198 case DeclarationName::CXXUsingDirective
:
199 OS
<< "<using-directive>";
203 llvm_unreachable("Unexpected declaration name kind");
208 raw_ostream
&operator<<(raw_ostream
&OS
, DeclarationName N
) {
210 N
.print(OS
, PrintingPolicy(LO
));
216 bool DeclarationName::isDependentName() const {
217 QualType T
= getCXXNameType();
218 if (!T
.isNull() && T
->isDependentType())
221 // A class-scope deduction guide in a dependent context has a dependent name.
222 auto *TD
= getCXXDeductionGuideTemplate();
223 if (TD
&& TD
->getDeclContext()->isDependentContext())
229 std::string
DeclarationName::getAsString() const {
231 llvm::raw_string_ostream
OS(Result
);
236 void *DeclarationName::getFETokenInfoSlow() const {
237 switch (getNameKind()) {
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
;
251 llvm_unreachable("DeclarationName has no FETokenInfo!");
255 void DeclarationName::setFETokenInfoSlow(void *T
) {
256 switch (getNameKind()) {
258 llvm_unreachable("case Identifier already handled by setFETokenInfo!");
259 case CXXConstructorName
:
260 case CXXDestructorName
:
261 case CXXConversionFunctionName
:
262 castAsCXXSpecialNameExtra()->FETokenInfo
= T
;
264 case CXXOperatorName
:
265 castAsCXXOperatorIdName()->FETokenInfo
= T
;
267 case CXXDeductionGuideName
:
268 castAsCXXDeductionGuideNameExtra()->FETokenInfo
= T
;
270 case CXXLiteralOperatorName
:
271 castAsCXXLiteralOperatorIdName()->FETokenInfo
= T
;
274 llvm_unreachable("DeclarationName has no FETokenInfo!");
278 LLVM_DUMP_METHOD
void DeclarationName::dump() const {
279 llvm::errs() << *this << '\n';
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
);
289 DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl
*Template
) {
290 Template
= cast
<TemplateDecl
>(Template
->getCanonicalDecl());
292 llvm::FoldingSetNodeID ID
;
293 ID
.AddPointer(Template
);
295 void *InsertPos
= nullptr;
296 if (auto *Name
= CXXDeductionGuideNames
.FindNodeOrInsertPos(ID
, InsertPos
))
297 return DeclarationName(Name
);
299 auto *Name
= new (Ctx
) detail::CXXDeductionGuideNameExtra(Template
);
300 CXXDeductionGuideNames
.InsertNode(Name
, InsertPos
);
301 return DeclarationName(Name
);
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
};
314 // We have to create it.
315 auto *SpecialName
= new (Ctx
) detail::CXXSpecialNameExtra(Ty
);
316 CXXConstructorNames
.InsertNode(SpecialName
, InsertPos
);
317 return {SpecialName
, DeclarationName::StoredCXXConstructorName
};
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
};
330 // We have to create it.
331 auto *SpecialName
= new (Ctx
) detail::CXXSpecialNameExtra(Ty
);
332 CXXDestructorNames
.InsertNode(SpecialName
, InsertPos
);
333 return {SpecialName
, DeclarationName::StoredCXXDestructorName
};
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;
343 CXXConversionFunctionNames
.FindNodeOrInsertPos(ID
, InsertPos
))
344 return {Name
, DeclarationName::StoredCXXConversionFunctionName
};
346 // We have to create it.
347 auto *SpecialName
= new (Ctx
) detail::CXXSpecialNameExtra(Ty
);
348 CXXConversionFunctionNames
.InsertNode(SpecialName
, InsertPos
);
349 return {SpecialName
, DeclarationName::StoredCXXConversionFunctionName
};
353 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind 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
);
363 llvm_unreachable("Invalid kind in getCXXSpecialName!");
368 DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo
*II
) {
369 llvm::FoldingSetNodeID ID
;
372 void *InsertPos
= nullptr;
373 if (auto *Name
= CXXLiteralOperatorNames
.FindNodeOrInsertPos(ID
, InsertPos
))
374 return DeclarationName(Name
);
376 auto *LiteralName
= new (Ctx
) detail::CXXLiteralOperatorIdName(II
);
377 CXXLiteralOperatorNames
.InsertNode(LiteralName
, InsertPos
);
378 return DeclarationName(LiteralName
);
381 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name
) {
382 switch (Name
.getNameKind()) {
383 case DeclarationName::Identifier
:
384 case DeclarationName::CXXDeductionGuideName
:
386 case DeclarationName::CXXConstructorName
:
387 case DeclarationName::CXXDestructorName
:
388 case DeclarationName::CXXConversionFunctionName
:
389 setNamedTypeLoc(nullptr);
391 case DeclarationName::CXXOperatorName
:
392 setCXXOperatorNameRange(SourceRange());
394 case DeclarationName::CXXLiteralOperatorName
:
395 setCXXLiteralOperatorNameLoc(SourceLocation());
397 case DeclarationName::ObjCZeroArgSelector
:
398 case DeclarationName::ObjCOneArgSelector
:
399 case DeclarationName::ObjCMultiArgSelector
:
402 case DeclarationName::CXXUsingDirective
:
407 bool 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
:
419 case DeclarationName::CXXConstructorName
:
420 case DeclarationName::CXXDestructorName
:
421 case DeclarationName::CXXConversionFunctionName
:
422 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo())
423 return TInfo
->getType()->containsUnexpandedParameterPack();
425 return Name
.getCXXNameType()->containsUnexpandedParameterPack();
427 llvm_unreachable("All name kinds handled.");
430 bool 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
:
442 case DeclarationName::CXXConstructorName
:
443 case DeclarationName::CXXDestructorName
:
444 case DeclarationName::CXXConversionFunctionName
:
445 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo())
446 return TInfo
->getType()->isInstantiationDependentType();
448 return Name
.getCXXNameType()->isInstantiationDependentType();
450 llvm_unreachable("All name kinds handled.");
453 std::string
DeclarationNameInfo::getAsString() const {
455 llvm::raw_string_ostream
OS(Result
);
460 raw_ostream
&clang::operator<<(raw_ostream
&OS
, DeclarationNameInfo DNInfo
) {
462 DNInfo
.printName(OS
, PrintingPolicy(LangOptions()));
466 void 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
);
479 case DeclarationName::CXXConstructorName
:
480 case DeclarationName::CXXDestructorName
:
481 case DeclarationName::CXXConversionFunctionName
:
482 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo()) {
483 if (Name
.getNameKind() == DeclarationName::CXXDestructorName
)
485 else if (Name
.getNameKind() == DeclarationName::CXXConversionFunctionName
)
488 Policy
.adjustForCPlusPlus();
489 Policy
.SuppressScope
= true;
490 OS
<< TInfo
->getType().getAsString(Policy
);
492 Name
.print(OS
, Policy
);
495 llvm_unreachable("Unexpected declaration name kind");
498 SourceLocation
DeclarationNameInfo::getEndLocPrivate() const {
499 switch (Name
.getNameKind()) {
500 case DeclarationName::Identifier
:
501 case DeclarationName::CXXDeductionGuideName
:
504 case DeclarationName::CXXOperatorName
:
505 return LocInfo
.getCXXOperatorNameEndLoc();
507 case DeclarationName::CXXLiteralOperatorName
:
508 return LocInfo
.getCXXLiteralOperatorNameLoc();
510 case DeclarationName::CXXConstructorName
:
511 case DeclarationName::CXXDestructorName
:
512 case DeclarationName::CXXConversionFunctionName
:
513 if (TypeSourceInfo
*TInfo
= LocInfo
.getNamedTypeInfo())
514 return TInfo
->getTypeLoc().getEndLoc();
518 // DNInfo work in progress: FIXME.
519 case DeclarationName::ObjCZeroArgSelector
:
520 case DeclarationName::ObjCOneArgSelector
:
521 case DeclarationName::ObjCMultiArgSelector
:
522 case DeclarationName::CXXUsingDirective
:
525 llvm_unreachable("Unexpected declaration name kind");