1 //===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the DeclarationName and DeclarationNameTable
13 //===----------------------------------------------------------------------===//
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclarationName.h"
17 #include "clang/AST/Type.h"
18 #include "clang/AST/TypeLoc.h"
19 #include "clang/AST/TypeOrdering.h"
20 #include "clang/Basic/IdentifierTable.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/raw_ostream.h"
25 using namespace clang
;
28 /// CXXSpecialName - Records the type associated with one of the
29 /// "special" kinds of declaration names in C++, e.g., constructors,
30 /// destructors, and conversion functions.
32 : public DeclarationNameExtra
, public llvm::FoldingSetNode
{
34 /// Type - The type associated with this declaration name.
37 /// FETokenInfo - Extra information associated with this declaration
38 /// name that can be used by the front end.
41 void Profile(llvm::FoldingSetNodeID
&ID
) {
42 ID
.AddInteger(ExtraKindOrNumArgs
);
43 ID
.AddPointer(Type
.getAsOpaquePtr());
47 /// CXXOperatorIdName - Contains extra information for the name of an
48 /// overloaded operator in C++, such as "operator+.
49 class CXXOperatorIdName
: public DeclarationNameExtra
{
51 /// FETokenInfo - Extra information associated with this operator
52 /// name that can be used by the front end.
56 /// CXXLiteralOperatorName - Contains the actual identifier that makes up the
59 /// This identifier is stored here rather than directly in DeclarationName so as
60 /// to allow Objective-C selectors, which are about a million times more common,
61 /// to consume minimal memory.
62 class CXXLiteralOperatorIdName
63 : public DeclarationNameExtra
, public llvm::FoldingSetNode
{
67 /// FETokenInfo - Extra information associated with this operator
68 /// name that can be used by the front end.
71 void Profile(llvm::FoldingSetNodeID
&FSID
) {
76 static int compareInt(unsigned A
, unsigned B
) {
77 return (A
< B
? -1 : (A
> B
? 1 : 0));
80 int DeclarationName::compare(DeclarationName LHS
, DeclarationName RHS
) {
81 if (LHS
.getNameKind() != RHS
.getNameKind())
82 return (LHS
.getNameKind() < RHS
.getNameKind() ? -1 : 1);
84 switch (LHS
.getNameKind()) {
85 case DeclarationName::Identifier
: {
86 IdentifierInfo
*LII
= LHS
.getAsIdentifierInfo();
87 IdentifierInfo
*RII
= RHS
.getAsIdentifierInfo();
88 if (!LII
) return RII
? -1 : 0;
91 return LII
->getName().compare(RII
->getName());
94 case DeclarationName::ObjCZeroArgSelector
:
95 case DeclarationName::ObjCOneArgSelector
:
96 case DeclarationName::ObjCMultiArgSelector
: {
97 Selector LHSSelector
= LHS
.getObjCSelector();
98 Selector RHSSelector
= RHS
.getObjCSelector();
99 unsigned LN
= LHSSelector
.getNumArgs(), RN
= RHSSelector
.getNumArgs();
100 for (unsigned I
= 0, N
= std::min(LN
, RN
); I
!= N
; ++I
) {
101 switch (LHSSelector
.getNameForSlot(I
).compare(
102 RHSSelector
.getNameForSlot(I
))) {
103 case -1: return true;
104 case 1: return false;
109 return compareInt(LN
, RN
);
112 case DeclarationName::CXXConstructorName
:
113 case DeclarationName::CXXDestructorName
:
114 case DeclarationName::CXXConversionFunctionName
:
115 if (QualTypeOrdering()(LHS
.getCXXNameType(), RHS
.getCXXNameType()))
117 if (QualTypeOrdering()(RHS
.getCXXNameType(), LHS
.getCXXNameType()))
121 case DeclarationName::CXXOperatorName
:
122 return compareInt(LHS
.getCXXOverloadedOperator(),
123 RHS
.getCXXOverloadedOperator());
125 case DeclarationName::CXXLiteralOperatorName
:
126 return LHS
.getCXXLiteralIdentifier()->getName().compare(
127 RHS
.getCXXLiteralIdentifier()->getName());
129 case DeclarationName::CXXUsingDirective
:
133 llvm_unreachable("Invalid DeclarationName Kind!");
136 raw_ostream
&operator<<(raw_ostream
&OS
, DeclarationName N
) {
137 switch (N
.getNameKind()) {
138 case DeclarationName::Identifier
:
139 if (const IdentifierInfo
*II
= N
.getAsIdentifierInfo())
143 case DeclarationName::ObjCZeroArgSelector
:
144 case DeclarationName::ObjCOneArgSelector
:
145 case DeclarationName::ObjCMultiArgSelector
:
146 N
.getObjCSelector().print(OS
);
149 case DeclarationName::CXXConstructorName
: {
150 QualType ClassType
= N
.getCXXNameType();
151 if (const RecordType
*ClassRec
= ClassType
->getAs
<RecordType
>())
152 return OS
<< *ClassRec
->getDecl();
155 return OS
<< ClassType
.getAsString(PrintingPolicy(LO
));
158 case DeclarationName::CXXDestructorName
: {
160 QualType Type
= N
.getCXXNameType();
161 if (const RecordType
*Rec
= Type
->getAs
<RecordType
>())
162 return OS
<< *Rec
->getDecl();
165 return OS
<< Type
.getAsString(PrintingPolicy(LO
));
168 case DeclarationName::CXXOperatorName
: {
169 static const char* const OperatorNames
[NUM_OVERLOADED_OPERATORS
] = {
171 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
173 #include "clang/Basic/OperatorKinds.def"
175 const char *OpName
= OperatorNames
[N
.getCXXOverloadedOperator()];
176 assert(OpName
&& "not an overloaded operator");
179 if (OpName
[0] >= 'a' && OpName
[0] <= 'z')
184 case DeclarationName::CXXLiteralOperatorName
:
185 return OS
<< "operator \"\" " << N
.getCXXLiteralIdentifier()->getName();
187 case DeclarationName::CXXConversionFunctionName
: {
189 QualType Type
= N
.getCXXNameType();
190 if (const RecordType
*Rec
= Type
->getAs
<RecordType
>())
191 return OS
<< *Rec
->getDecl();
195 return OS
<< Type
.getAsString(PrintingPolicy(LO
));
197 case DeclarationName::CXXUsingDirective
:
198 return OS
<< "<using-directive>";
201 llvm_unreachable("Unexpected declaration name kind");
204 } // end namespace clang
206 DeclarationName::NameKind
DeclarationName::getNameKind() const {
207 switch (getStoredNameKind()) {
208 case StoredIdentifier
: return Identifier
;
209 case StoredObjCZeroArgSelector
: return ObjCZeroArgSelector
;
210 case StoredObjCOneArgSelector
: return ObjCOneArgSelector
;
212 case StoredDeclarationNameExtra
:
213 switch (getExtra()->ExtraKindOrNumArgs
) {
214 case DeclarationNameExtra::CXXConstructor
:
215 return CXXConstructorName
;
217 case DeclarationNameExtra::CXXDestructor
:
218 return CXXDestructorName
;
220 case DeclarationNameExtra::CXXConversionFunction
:
221 return CXXConversionFunctionName
;
223 case DeclarationNameExtra::CXXLiteralOperator
:
224 return CXXLiteralOperatorName
;
226 case DeclarationNameExtra::CXXUsingDirective
:
227 return CXXUsingDirective
;
230 // Check if we have one of the CXXOperator* enumeration values.
231 if (getExtra()->ExtraKindOrNumArgs
<
232 DeclarationNameExtra::CXXUsingDirective
)
233 return CXXOperatorName
;
235 return ObjCMultiArgSelector
;
239 // Can't actually get here.
240 llvm_unreachable("This should be unreachable!");
243 bool DeclarationName::isDependentName() const {
244 QualType T
= getCXXNameType();
245 return !T
.isNull() && T
->isDependentType();
248 std::string
DeclarationName::getAsString() const {
250 llvm::raw_string_ostream
OS(Result
);
255 QualType
DeclarationName::getCXXNameType() const {
256 if (CXXSpecialName
*CXXName
= getAsCXXSpecialName())
257 return CXXName
->Type
;
262 OverloadedOperatorKind
DeclarationName::getCXXOverloadedOperator() const {
263 if (CXXOperatorIdName
*CXXOp
= getAsCXXOperatorIdName()) {
265 = CXXOp
->ExtraKindOrNumArgs
- DeclarationNameExtra::CXXConversionFunction
;
266 return static_cast<OverloadedOperatorKind
>(value
);
272 IdentifierInfo
*DeclarationName::getCXXLiteralIdentifier() const {
273 if (CXXLiteralOperatorIdName
*CXXLit
= getAsCXXLiteralOperatorIdName())
279 void *DeclarationName::getFETokenInfoAsVoidSlow() const {
280 switch (getNameKind()) {
282 llvm_unreachable("Handled by getFETokenInfo()");
284 case CXXConstructorName
:
285 case CXXDestructorName
:
286 case CXXConversionFunctionName
:
287 return getAsCXXSpecialName()->FETokenInfo
;
289 case CXXOperatorName
:
290 return getAsCXXOperatorIdName()->FETokenInfo
;
292 case CXXLiteralOperatorName
:
293 return getAsCXXLiteralOperatorIdName()->FETokenInfo
;
296 llvm_unreachable("Declaration name has no FETokenInfo");
300 void DeclarationName::setFETokenInfo(void *T
) {
301 switch (getNameKind()) {
303 getAsIdentifierInfo()->setFETokenInfo(T
);
306 case CXXConstructorName
:
307 case CXXDestructorName
:
308 case CXXConversionFunctionName
:
309 getAsCXXSpecialName()->FETokenInfo
= T
;
312 case CXXOperatorName
:
313 getAsCXXOperatorIdName()->FETokenInfo
= T
;
316 case CXXLiteralOperatorName
:
317 getAsCXXLiteralOperatorIdName()->FETokenInfo
= T
;
321 llvm_unreachable("Declaration name has no FETokenInfo");
325 DeclarationName
DeclarationName::getUsingDirectiveName() {
326 // Single instance of DeclarationNameExtra for using-directive
327 static const DeclarationNameExtra UDirExtra
=
328 { DeclarationNameExtra::CXXUsingDirective
};
330 uintptr_t Ptr
= reinterpret_cast<uintptr_t>(&UDirExtra
);
331 Ptr
|= StoredDeclarationNameExtra
;
333 return DeclarationName(Ptr
);
336 void DeclarationName::dump() const {
337 llvm::errs() << *this << '\n';
340 DeclarationNameTable::DeclarationNameTable(const ASTContext
&C
) : Ctx(C
) {
341 CXXSpecialNamesImpl
= new llvm::FoldingSet
<CXXSpecialName
>;
342 CXXLiteralOperatorNames
= new llvm::FoldingSet
<CXXLiteralOperatorIdName
>;
344 // Initialize the overloaded operator names.
345 CXXOperatorNames
= new (Ctx
) CXXOperatorIdName
[NUM_OVERLOADED_OPERATORS
];
346 for (unsigned Op
= 0; Op
< NUM_OVERLOADED_OPERATORS
; ++Op
) {
347 CXXOperatorNames
[Op
].ExtraKindOrNumArgs
348 = Op
+ DeclarationNameExtra::CXXConversionFunction
;
349 CXXOperatorNames
[Op
].FETokenInfo
= nullptr;
353 DeclarationNameTable::~DeclarationNameTable() {
354 llvm::FoldingSet
<CXXSpecialName
> *SpecialNames
=
355 static_cast<llvm::FoldingSet
<CXXSpecialName
>*>(CXXSpecialNamesImpl
);
356 llvm::FoldingSet
<CXXLiteralOperatorIdName
> *LiteralNames
357 = static_cast<llvm::FoldingSet
<CXXLiteralOperatorIdName
>*>
358 (CXXLiteralOperatorNames
);
364 DeclarationName
DeclarationNameTable::getCXXConstructorName(CanQualType Ty
) {
365 return getCXXSpecialName(DeclarationName::CXXConstructorName
,
366 Ty
.getUnqualifiedType());
369 DeclarationName
DeclarationNameTable::getCXXDestructorName(CanQualType Ty
) {
370 return getCXXSpecialName(DeclarationName::CXXDestructorName
,
371 Ty
.getUnqualifiedType());
375 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty
) {
376 return getCXXSpecialName(DeclarationName::CXXConversionFunctionName
, Ty
);
380 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind
,
382 assert(Kind
>= DeclarationName::CXXConstructorName
&&
383 Kind
<= DeclarationName::CXXConversionFunctionName
&&
384 "Kind must be a C++ special name kind");
385 llvm::FoldingSet
<CXXSpecialName
> *SpecialNames
386 = static_cast<llvm::FoldingSet
<CXXSpecialName
>*>(CXXSpecialNamesImpl
);
388 DeclarationNameExtra::ExtraKind EKind
;
390 case DeclarationName::CXXConstructorName
:
391 EKind
= DeclarationNameExtra::CXXConstructor
;
392 assert(!Ty
.hasQualifiers() &&"Constructor type must be unqualified");
394 case DeclarationName::CXXDestructorName
:
395 EKind
= DeclarationNameExtra::CXXDestructor
;
396 assert(!Ty
.hasQualifiers() && "Destructor type must be unqualified");
398 case DeclarationName::CXXConversionFunctionName
:
399 EKind
= DeclarationNameExtra::CXXConversionFunction
;
402 return DeclarationName();
405 // Unique selector, to guarantee there is one per name.
406 llvm::FoldingSetNodeID ID
;
407 ID
.AddInteger(EKind
);
408 ID
.AddPointer(Ty
.getAsOpaquePtr());
410 void *InsertPos
= nullptr;
411 if (CXXSpecialName
*Name
= SpecialNames
->FindNodeOrInsertPos(ID
, InsertPos
))
412 return DeclarationName(Name
);
414 CXXSpecialName
*SpecialName
= new (Ctx
) CXXSpecialName
;
415 SpecialName
->ExtraKindOrNumArgs
= EKind
;
416 SpecialName
->Type
= Ty
;
417 SpecialName
->FETokenInfo
= nullptr;
419 SpecialNames
->InsertNode(SpecialName
, InsertPos
);
420 return DeclarationName(SpecialName
);
424 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op
) {
425 return DeclarationName(&CXXOperatorNames
[(unsigned)Op
]);
429 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo
*II
) {
430 llvm::FoldingSet
<CXXLiteralOperatorIdName
> *LiteralNames
431 = static_cast<llvm::FoldingSet
<CXXLiteralOperatorIdName
>*>
432 (CXXLiteralOperatorNames
);
434 llvm::FoldingSetNodeID ID
;
437 void *InsertPos
= nullptr;
438 if (CXXLiteralOperatorIdName
*Name
=
439 LiteralNames
->FindNodeOrInsertPos(ID
, InsertPos
))
440 return DeclarationName (Name
);
442 CXXLiteralOperatorIdName
*LiteralName
= new (Ctx
) CXXLiteralOperatorIdName
;
443 LiteralName
->ExtraKindOrNumArgs
= DeclarationNameExtra::CXXLiteralOperator
;
444 LiteralName
->ID
= II
;
445 LiteralName
->FETokenInfo
= nullptr;
447 LiteralNames
->InsertNode(LiteralName
, InsertPos
);
448 return DeclarationName(LiteralName
);
451 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name
) {
452 switch (Name
.getNameKind()) {
453 case DeclarationName::Identifier
:
455 case DeclarationName::CXXConstructorName
:
456 case DeclarationName::CXXDestructorName
:
457 case DeclarationName::CXXConversionFunctionName
:
458 NamedType
.TInfo
= nullptr;
460 case DeclarationName::CXXOperatorName
:
461 CXXOperatorName
.BeginOpNameLoc
= SourceLocation().getRawEncoding();
462 CXXOperatorName
.EndOpNameLoc
= SourceLocation().getRawEncoding();
464 case DeclarationName::CXXLiteralOperatorName
:
465 CXXLiteralOperatorName
.OpNameLoc
= SourceLocation().getRawEncoding();
467 case DeclarationName::ObjCZeroArgSelector
:
468 case DeclarationName::ObjCOneArgSelector
:
469 case DeclarationName::ObjCMultiArgSelector
:
472 case DeclarationName::CXXUsingDirective
:
477 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
478 switch (Name
.getNameKind()) {
479 case DeclarationName::Identifier
:
480 case DeclarationName::ObjCZeroArgSelector
:
481 case DeclarationName::ObjCOneArgSelector
:
482 case DeclarationName::ObjCMultiArgSelector
:
483 case DeclarationName::CXXOperatorName
:
484 case DeclarationName::CXXLiteralOperatorName
:
485 case DeclarationName::CXXUsingDirective
:
488 case DeclarationName::CXXConstructorName
:
489 case DeclarationName::CXXDestructorName
:
490 case DeclarationName::CXXConversionFunctionName
:
491 if (TypeSourceInfo
*TInfo
= LocInfo
.NamedType
.TInfo
)
492 return TInfo
->getType()->containsUnexpandedParameterPack();
494 return Name
.getCXXNameType()->containsUnexpandedParameterPack();
496 llvm_unreachable("All name kinds handled.");
499 bool DeclarationNameInfo::isInstantiationDependent() const {
500 switch (Name
.getNameKind()) {
501 case DeclarationName::Identifier
:
502 case DeclarationName::ObjCZeroArgSelector
:
503 case DeclarationName::ObjCOneArgSelector
:
504 case DeclarationName::ObjCMultiArgSelector
:
505 case DeclarationName::CXXOperatorName
:
506 case DeclarationName::CXXLiteralOperatorName
:
507 case DeclarationName::CXXUsingDirective
:
510 case DeclarationName::CXXConstructorName
:
511 case DeclarationName::CXXDestructorName
:
512 case DeclarationName::CXXConversionFunctionName
:
513 if (TypeSourceInfo
*TInfo
= LocInfo
.NamedType
.TInfo
)
514 return TInfo
->getType()->isInstantiationDependentType();
516 return Name
.getCXXNameType()->isInstantiationDependentType();
518 llvm_unreachable("All name kinds handled.");
521 std::string
DeclarationNameInfo::getAsString() const {
523 llvm::raw_string_ostream
OS(Result
);
528 void DeclarationNameInfo::printName(raw_ostream
&OS
) const {
529 switch (Name
.getNameKind()) {
530 case DeclarationName::Identifier
:
531 case DeclarationName::ObjCZeroArgSelector
:
532 case DeclarationName::ObjCOneArgSelector
:
533 case DeclarationName::ObjCMultiArgSelector
:
534 case DeclarationName::CXXOperatorName
:
535 case DeclarationName::CXXLiteralOperatorName
:
536 case DeclarationName::CXXUsingDirective
:
540 case DeclarationName::CXXConstructorName
:
541 case DeclarationName::CXXDestructorName
:
542 case DeclarationName::CXXConversionFunctionName
:
543 if (TypeSourceInfo
*TInfo
= LocInfo
.NamedType
.TInfo
) {
544 if (Name
.getNameKind() == DeclarationName::CXXDestructorName
)
546 else if (Name
.getNameKind() == DeclarationName::CXXConversionFunctionName
)
551 OS
<< TInfo
->getType().getAsString(PrintingPolicy(LO
));
556 llvm_unreachable("Unexpected declaration name kind");
559 SourceLocation
DeclarationNameInfo::getEndLoc() const {
560 switch (Name
.getNameKind()) {
561 case DeclarationName::Identifier
:
564 case DeclarationName::CXXOperatorName
: {
565 unsigned raw
= LocInfo
.CXXOperatorName
.EndOpNameLoc
;
566 return SourceLocation::getFromRawEncoding(raw
);
569 case DeclarationName::CXXLiteralOperatorName
: {
570 unsigned raw
= LocInfo
.CXXLiteralOperatorName
.OpNameLoc
;
571 return SourceLocation::getFromRawEncoding(raw
);
574 case DeclarationName::CXXConstructorName
:
575 case DeclarationName::CXXDestructorName
:
576 case DeclarationName::CXXConversionFunctionName
:
577 if (TypeSourceInfo
*TInfo
= LocInfo
.NamedType
.TInfo
)
578 return TInfo
->getTypeLoc().getEndLoc();
582 // DNInfo work in progress: FIXME.
583 case DeclarationName::ObjCZeroArgSelector
:
584 case DeclarationName::ObjCOneArgSelector
:
585 case DeclarationName::ObjCMultiArgSelector
:
586 case DeclarationName::CXXUsingDirective
:
589 llvm_unreachable("Unexpected declaration name kind");