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 return OS << N.getObjCSelector().getAsString();
148 case DeclarationName::CXXConstructorName: {
149 QualType ClassType = N.getCXXNameType();
150 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
151 return OS << *ClassRec->getDecl();
152 return OS << ClassType.getAsString();
155 case DeclarationName::CXXDestructorName: {
157 QualType Type = N.getCXXNameType();
158 if (const RecordType *Rec = Type->getAs<RecordType>())
159 return OS << *Rec->getDecl();
160 return OS << Type.getAsString();
163 case DeclarationName::CXXOperatorName: {
164 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
166 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
168 #include "clang/Basic/OperatorKinds.def"
170 const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
171 assert(OpName && "not an overloaded operator");
174 if (OpName[0] >= 'a' && OpName[0] <= 'z')
179 case DeclarationName::CXXLiteralOperatorName:
180 return OS << "operator \"\" " << N.getCXXLiteralIdentifier()->getName();
182 case DeclarationName::CXXConversionFunctionName: {
184 QualType Type = N.getCXXNameType();
185 if (const RecordType *Rec = Type->getAs<RecordType>())
186 return OS << *Rec->getDecl();
187 return OS << Type.getAsString();
189 case DeclarationName::CXXUsingDirective:
190 return OS << "<using-directive>";
193 llvm_unreachable("Unexpected declaration name kind");
196 } // end namespace clang
198 DeclarationName::NameKind DeclarationName::getNameKind() const {
199 switch (getStoredNameKind()) {
200 case StoredIdentifier: return Identifier;
201 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
202 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
204 case StoredDeclarationNameExtra:
205 switch (getExtra()->ExtraKindOrNumArgs) {
206 case DeclarationNameExtra::CXXConstructor:
207 return CXXConstructorName;
209 case DeclarationNameExtra::CXXDestructor:
210 return CXXDestructorName;
212 case DeclarationNameExtra::CXXConversionFunction:
213 return CXXConversionFunctionName;
215 case DeclarationNameExtra::CXXLiteralOperator:
216 return CXXLiteralOperatorName;
218 case DeclarationNameExtra::CXXUsingDirective:
219 return CXXUsingDirective;
222 // Check if we have one of the CXXOperator* enumeration values.
223 if (getExtra()->ExtraKindOrNumArgs <
224 DeclarationNameExtra::CXXUsingDirective)
225 return CXXOperatorName;
227 return ObjCMultiArgSelector;
231 // Can't actually get here.
232 llvm_unreachable("This should be unreachable!");
235 bool DeclarationName::isDependentName() const {
236 QualType T = getCXXNameType();
237 return !T.isNull() && T->isDependentType();
240 std::string DeclarationName::getAsString() const {
242 llvm::raw_string_ostream OS(Result);
247 QualType DeclarationName::getCXXNameType() const {
248 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
249 return CXXName->Type;
254 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
255 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
257 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
258 return static_cast<OverloadedOperatorKind>(value);
264 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
265 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
271 void *DeclarationName::getFETokenInfoAsVoidSlow() const {
272 switch (getNameKind()) {
274 llvm_unreachable("Handled by getFETokenInfo()");
276 case CXXConstructorName:
277 case CXXDestructorName:
278 case CXXConversionFunctionName:
279 return getAsCXXSpecialName()->FETokenInfo;
281 case CXXOperatorName:
282 return getAsCXXOperatorIdName()->FETokenInfo;
284 case CXXLiteralOperatorName:
285 return getAsCXXLiteralOperatorIdName()->FETokenInfo;
288 llvm_unreachable("Declaration name has no FETokenInfo");
292 void DeclarationName::setFETokenInfo(void *T) {
293 switch (getNameKind()) {
295 getAsIdentifierInfo()->setFETokenInfo(T);
298 case CXXConstructorName:
299 case CXXDestructorName:
300 case CXXConversionFunctionName:
301 getAsCXXSpecialName()->FETokenInfo = T;
304 case CXXOperatorName:
305 getAsCXXOperatorIdName()->FETokenInfo = T;
308 case CXXLiteralOperatorName:
309 getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
313 llvm_unreachable("Declaration name has no FETokenInfo");
317 DeclarationName DeclarationName::getUsingDirectiveName() {
318 // Single instance of DeclarationNameExtra for using-directive
319 static const DeclarationNameExtra UDirExtra =
320 { DeclarationNameExtra::CXXUsingDirective };
322 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
323 Ptr |= StoredDeclarationNameExtra;
325 return DeclarationName(Ptr);
328 void DeclarationName::dump() const {
329 llvm::errs() << *this << '\n';
332 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
333 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
334 CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
336 // Initialize the overloaded operator names.
337 CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
338 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
339 CXXOperatorNames[Op].ExtraKindOrNumArgs
340 = Op + DeclarationNameExtra::CXXConversionFunction;
341 CXXOperatorNames[Op].FETokenInfo = 0;
345 DeclarationNameTable::~DeclarationNameTable() {
346 llvm::FoldingSet<CXXSpecialName> *SpecialNames =
347 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
348 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
349 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
350 (CXXLiteralOperatorNames);
356 DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
357 return getCXXSpecialName(DeclarationName::CXXConstructorName,
358 Ty.getUnqualifiedType());
361 DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
362 return getCXXSpecialName(DeclarationName::CXXDestructorName,
363 Ty.getUnqualifiedType());
367 DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
368 return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
372 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
374 assert(Kind >= DeclarationName::CXXConstructorName &&
375 Kind <= DeclarationName::CXXConversionFunctionName &&
376 "Kind must be a C++ special name kind");
377 llvm::FoldingSet<CXXSpecialName> *SpecialNames
378 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
380 DeclarationNameExtra::ExtraKind EKind;
382 case DeclarationName::CXXConstructorName:
383 EKind = DeclarationNameExtra::CXXConstructor;
384 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
386 case DeclarationName::CXXDestructorName:
387 EKind = DeclarationNameExtra::CXXDestructor;
388 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
390 case DeclarationName::CXXConversionFunctionName:
391 EKind = DeclarationNameExtra::CXXConversionFunction;
394 return DeclarationName();
397 // Unique selector, to guarantee there is one per name.
398 llvm::FoldingSetNodeID ID;
399 ID.AddInteger(EKind);
400 ID.AddPointer(Ty.getAsOpaquePtr());
403 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
404 return DeclarationName(Name);
406 CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
407 SpecialName->ExtraKindOrNumArgs = EKind;
408 SpecialName->Type = Ty;
409 SpecialName->FETokenInfo = 0;
411 SpecialNames->InsertNode(SpecialName, InsertPos);
412 return DeclarationName(SpecialName);
416 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
417 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
421 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
422 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
423 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
424 (CXXLiteralOperatorNames);
426 llvm::FoldingSetNodeID ID;
430 if (CXXLiteralOperatorIdName *Name =
431 LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
432 return DeclarationName (Name);
434 CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
435 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
436 LiteralName->ID = II;
437 LiteralName->FETokenInfo = 0;
439 LiteralNames->InsertNode(LiteralName, InsertPos);
440 return DeclarationName(LiteralName);
443 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
444 switch (Name.getNameKind()) {
445 case DeclarationName::Identifier:
447 case DeclarationName::CXXConstructorName:
448 case DeclarationName::CXXDestructorName:
449 case DeclarationName::CXXConversionFunctionName:
452 case DeclarationName::CXXOperatorName:
453 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
454 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
456 case DeclarationName::CXXLiteralOperatorName:
457 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
459 case DeclarationName::ObjCZeroArgSelector:
460 case DeclarationName::ObjCOneArgSelector:
461 case DeclarationName::ObjCMultiArgSelector:
464 case DeclarationName::CXXUsingDirective:
469 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
470 switch (Name.getNameKind()) {
471 case DeclarationName::Identifier:
472 case DeclarationName::ObjCZeroArgSelector:
473 case DeclarationName::ObjCOneArgSelector:
474 case DeclarationName::ObjCMultiArgSelector:
475 case DeclarationName::CXXOperatorName:
476 case DeclarationName::CXXLiteralOperatorName:
477 case DeclarationName::CXXUsingDirective:
480 case DeclarationName::CXXConstructorName:
481 case DeclarationName::CXXDestructorName:
482 case DeclarationName::CXXConversionFunctionName:
483 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
484 return TInfo->getType()->containsUnexpandedParameterPack();
486 return Name.getCXXNameType()->containsUnexpandedParameterPack();
488 llvm_unreachable("All name kinds handled.");
491 bool DeclarationNameInfo::isInstantiationDependent() const {
492 switch (Name.getNameKind()) {
493 case DeclarationName::Identifier:
494 case DeclarationName::ObjCZeroArgSelector:
495 case DeclarationName::ObjCOneArgSelector:
496 case DeclarationName::ObjCMultiArgSelector:
497 case DeclarationName::CXXOperatorName:
498 case DeclarationName::CXXLiteralOperatorName:
499 case DeclarationName::CXXUsingDirective:
502 case DeclarationName::CXXConstructorName:
503 case DeclarationName::CXXDestructorName:
504 case DeclarationName::CXXConversionFunctionName:
505 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
506 return TInfo->getType()->isInstantiationDependentType();
508 return Name.getCXXNameType()->isInstantiationDependentType();
510 llvm_unreachable("All name kinds handled.");
513 std::string DeclarationNameInfo::getAsString() const {
515 llvm::raw_string_ostream OS(Result);
520 void DeclarationNameInfo::printName(raw_ostream &OS) const {
521 switch (Name.getNameKind()) {
522 case DeclarationName::Identifier:
523 case DeclarationName::ObjCZeroArgSelector:
524 case DeclarationName::ObjCOneArgSelector:
525 case DeclarationName::ObjCMultiArgSelector:
526 case DeclarationName::CXXOperatorName:
527 case DeclarationName::CXXLiteralOperatorName:
528 case DeclarationName::CXXUsingDirective:
532 case DeclarationName::CXXConstructorName:
533 case DeclarationName::CXXDestructorName:
534 case DeclarationName::CXXConversionFunctionName:
535 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
536 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
538 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
540 OS << TInfo->getType().getAsString();
545 llvm_unreachable("Unexpected declaration name kind");
548 SourceLocation DeclarationNameInfo::getEndLoc() const {
549 switch (Name.getNameKind()) {
550 case DeclarationName::Identifier:
553 case DeclarationName::CXXOperatorName: {
554 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
555 return SourceLocation::getFromRawEncoding(raw);
558 case DeclarationName::CXXLiteralOperatorName: {
559 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
560 return SourceLocation::getFromRawEncoding(raw);
563 case DeclarationName::CXXConstructorName:
564 case DeclarationName::CXXDestructorName:
565 case DeclarationName::CXXConversionFunctionName:
566 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
567 return TInfo->getTypeLoc().getEndLoc();
571 // DNInfo work in progress: FIXME.
572 case DeclarationName::ObjCZeroArgSelector:
573 case DeclarationName::ObjCOneArgSelector:
574 case DeclarationName::ObjCMultiArgSelector:
575 case DeclarationName::CXXUsingDirective:
578 llvm_unreachable("Unexpected declaration name kind");