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/DeclarationName.h"
15 #include "clang/AST/Type.h"
16 #include "clang/AST/TypeOrdering.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/Basic/IdentifierTable.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/FoldingSet.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace clang;
25 /// CXXSpecialName - Records the type associated with one of the
26 /// "special" kinds of declaration names in C++, e.g., constructors,
27 /// destructors, and conversion functions.
29 : public DeclarationNameExtra, public llvm::FoldingSetNode {
31 /// Type - The type associated with this declaration name.
34 /// FETokenInfo - Extra information associated with this declaration
35 /// name that can be used by the front end.
38 void Profile(llvm::FoldingSetNodeID &ID) {
39 ID.AddInteger(ExtraKindOrNumArgs);
40 ID.AddPointer(Type.getAsOpaquePtr());
44 /// CXXOperatorIdName - Contains extra information for the name of an
45 /// overloaded operator in C++, such as "operator+.
46 class CXXOperatorIdName : public DeclarationNameExtra {
48 /// FETokenInfo - Extra information associated with this operator
49 /// name that can be used by the front end.
53 /// CXXLiberalOperatorName - Contains the actual identifier that makes up the
56 /// This identifier is stored here rather than directly in DeclarationName so as
57 /// to allow Objective-C selectors, which are about a million times more common,
58 /// to consume minimal memory.
59 class CXXLiteralOperatorIdName
60 : public DeclarationNameExtra, public llvm::FoldingSetNode {
64 void Profile(llvm::FoldingSetNodeID &FSID) {
69 static int compareInt(unsigned A, unsigned B) {
70 return (A < B ? -1 : (A > B ? 1 : 0));
73 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
74 if (LHS.getNameKind() != RHS.getNameKind())
75 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
77 switch (LHS.getNameKind()) {
78 case DeclarationName::Identifier: {
79 IdentifierInfo *LII = LHS.getAsIdentifierInfo();
80 IdentifierInfo *RII = RHS.getAsIdentifierInfo();
81 if (!LII) return RII ? -1 : 0;
84 return LII->getName().compare(RII->getName());
87 case DeclarationName::ObjCZeroArgSelector:
88 case DeclarationName::ObjCOneArgSelector:
89 case DeclarationName::ObjCMultiArgSelector: {
90 Selector LHSSelector = LHS.getObjCSelector();
91 Selector RHSSelector = RHS.getObjCSelector();
92 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
93 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
94 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
95 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
97 switch (LHSId->getName().compare(RHSId->getName())) {
104 return compareInt(LN, RN);
107 case DeclarationName::CXXConstructorName:
108 case DeclarationName::CXXDestructorName:
109 case DeclarationName::CXXConversionFunctionName:
110 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
112 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
116 case DeclarationName::CXXOperatorName:
117 return compareInt(LHS.getCXXOverloadedOperator(),
118 RHS.getCXXOverloadedOperator());
120 case DeclarationName::CXXLiteralOperatorName:
121 return LHS.getCXXLiteralIdentifier()->getName().compare(
122 RHS.getCXXLiteralIdentifier()->getName());
124 case DeclarationName::CXXUsingDirective:
131 } // end namespace clang
133 DeclarationName::DeclarationName(Selector Sel) {
134 if (!Sel.getAsOpaquePtr()) {
139 switch (Sel.getNumArgs()) {
141 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
142 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
143 Ptr |= StoredObjCZeroArgSelector;
147 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
148 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
149 Ptr |= StoredObjCOneArgSelector;
153 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
154 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
155 Ptr |= StoredDeclarationNameExtra;
160 DeclarationName::NameKind DeclarationName::getNameKind() const {
161 switch (getStoredNameKind()) {
162 case StoredIdentifier: return Identifier;
163 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
164 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
166 case StoredDeclarationNameExtra:
167 switch (getExtra()->ExtraKindOrNumArgs) {
168 case DeclarationNameExtra::CXXConstructor:
169 return CXXConstructorName;
171 case DeclarationNameExtra::CXXDestructor:
172 return CXXDestructorName;
174 case DeclarationNameExtra::CXXConversionFunction:
175 return CXXConversionFunctionName;
177 case DeclarationNameExtra::CXXLiteralOperator:
178 return CXXLiteralOperatorName;
180 case DeclarationNameExtra::CXXUsingDirective:
181 return CXXUsingDirective;
184 // Check if we have one of the CXXOperator* enumeration values.
185 if (getExtra()->ExtraKindOrNumArgs <
186 DeclarationNameExtra::CXXUsingDirective)
187 return CXXOperatorName;
189 return ObjCMultiArgSelector;
194 // Can't actually get here.
195 assert(0 && "This should be unreachable!");
199 bool DeclarationName::isDependentName() const {
200 QualType T = getCXXNameType();
201 return !T.isNull() && T->isDependentType();
204 std::string DeclarationName::getAsString() const {
206 llvm::raw_string_ostream OS(Result);
211 void DeclarationName::printName(llvm::raw_ostream &OS) const {
212 switch (getNameKind()) {
214 if (const IdentifierInfo *II = getAsIdentifierInfo())
218 case ObjCZeroArgSelector:
219 case ObjCOneArgSelector:
220 case ObjCMultiArgSelector:
221 OS << getObjCSelector().getAsString();
224 case CXXConstructorName: {
225 QualType ClassType = getCXXNameType();
226 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
227 OS << ClassRec->getDecl();
229 OS << ClassType.getAsString();
233 case CXXDestructorName: {
235 QualType Type = getCXXNameType();
236 if (const RecordType *Rec = Type->getAs<RecordType>())
237 OS << Rec->getDecl();
239 OS << Type.getAsString();
243 case CXXOperatorName: {
244 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
246 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
248 #include "clang/Basic/OperatorKinds.def"
250 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
251 assert(OpName && "not an overloaded operator");
254 if (OpName[0] >= 'a' && OpName[0] <= 'z')
260 case CXXLiteralOperatorName:
261 OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
264 case CXXConversionFunctionName: {
266 QualType Type = getCXXNameType();
267 if (const RecordType *Rec = Type->getAs<RecordType>())
268 OS << Rec->getDecl();
270 OS << Type.getAsString();
273 case CXXUsingDirective:
274 OS << "<using-directive>";
278 assert(false && "Unexpected declaration name kind");
281 QualType DeclarationName::getCXXNameType() const {
282 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
283 return CXXName->Type;
288 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
289 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
291 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
292 return static_cast<OverloadedOperatorKind>(value);
298 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
299 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
305 Selector DeclarationName::getObjCSelector() const {
306 switch (getNameKind()) {
307 case ObjCZeroArgSelector:
308 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
310 case ObjCOneArgSelector:
311 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
313 case ObjCMultiArgSelector:
314 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
323 void *DeclarationName::getFETokenInfoAsVoid() const {
324 switch (getNameKind()) {
326 return getAsIdentifierInfo()->getFETokenInfo<void>();
328 case CXXConstructorName:
329 case CXXDestructorName:
330 case CXXConversionFunctionName:
331 return getAsCXXSpecialName()->FETokenInfo;
333 case CXXOperatorName:
334 return getAsCXXOperatorIdName()->FETokenInfo;
336 case CXXLiteralOperatorName:
337 return getCXXLiteralIdentifier()->getFETokenInfo<void>();
340 assert(false && "Declaration name has no FETokenInfo");
345 void DeclarationName::setFETokenInfo(void *T) {
346 switch (getNameKind()) {
348 getAsIdentifierInfo()->setFETokenInfo(T);
351 case CXXConstructorName:
352 case CXXDestructorName:
353 case CXXConversionFunctionName:
354 getAsCXXSpecialName()->FETokenInfo = T;
357 case CXXOperatorName:
358 getAsCXXOperatorIdName()->FETokenInfo = T;
361 case CXXLiteralOperatorName:
362 getCXXLiteralIdentifier()->setFETokenInfo(T);
366 assert(false && "Declaration name has no FETokenInfo");
370 DeclarationName DeclarationName::getUsingDirectiveName() {
371 // Single instance of DeclarationNameExtra for using-directive
372 static const DeclarationNameExtra UDirExtra =
373 { DeclarationNameExtra::CXXUsingDirective };
375 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
376 Ptr |= StoredDeclarationNameExtra;
378 return DeclarationName(Ptr);
381 void DeclarationName::dump() const {
382 printName(llvm::errs());
383 llvm::errs() << '\n';
386 DeclarationNameTable::DeclarationNameTable() {
387 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
388 CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
390 // Initialize the overloaded operator names.
391 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
392 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
393 CXXOperatorNames[Op].ExtraKindOrNumArgs
394 = Op + DeclarationNameExtra::CXXConversionFunction;
395 CXXOperatorNames[Op].FETokenInfo = 0;
399 DeclarationNameTable::~DeclarationNameTable() {
400 llvm::FoldingSet<CXXSpecialName> *SpecialNames =
401 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
402 llvm::FoldingSetIterator<CXXSpecialName>
403 SI = SpecialNames->begin(), SE = SpecialNames->end();
406 CXXSpecialName *n = &*SI++;
411 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
412 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
413 (CXXLiteralOperatorNames);
414 llvm::FoldingSetIterator<CXXLiteralOperatorIdName>
415 LI = LiteralNames->begin(), LE = LiteralNames->end();
418 CXXLiteralOperatorIdName *n = &*LI++;
424 delete [] CXXOperatorNames;
428 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
430 assert(Kind >= DeclarationName::CXXConstructorName &&
431 Kind <= DeclarationName::CXXConversionFunctionName &&
432 "Kind must be a C++ special name kind");
433 llvm::FoldingSet<CXXSpecialName> *SpecialNames
434 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
436 DeclarationNameExtra::ExtraKind EKind;
438 case DeclarationName::CXXConstructorName:
439 EKind = DeclarationNameExtra::CXXConstructor;
440 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
442 case DeclarationName::CXXDestructorName:
443 EKind = DeclarationNameExtra::CXXDestructor;
444 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
446 case DeclarationName::CXXConversionFunctionName:
447 EKind = DeclarationNameExtra::CXXConversionFunction;
450 return DeclarationName();
453 // Unique selector, to guarantee there is one per name.
454 llvm::FoldingSetNodeID ID;
455 ID.AddInteger(EKind);
456 ID.AddPointer(Ty.getAsOpaquePtr());
459 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
460 return DeclarationName(Name);
462 CXXSpecialName *SpecialName = new CXXSpecialName;
463 SpecialName->ExtraKindOrNumArgs = EKind;
464 SpecialName->Type = Ty;
465 SpecialName->FETokenInfo = 0;
467 SpecialNames->InsertNode(SpecialName, InsertPos);
468 return DeclarationName(SpecialName);
472 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
473 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
477 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
478 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
479 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
480 (CXXLiteralOperatorNames);
482 llvm::FoldingSetNodeID ID;
486 if (CXXLiteralOperatorIdName *Name =
487 LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
488 return DeclarationName (Name);
490 CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
491 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
492 LiteralName->ID = II;
494 LiteralNames->InsertNode(LiteralName, InsertPos);
495 return DeclarationName(LiteralName);
499 llvm::DenseMapInfo<clang::DeclarationName>::
500 getHashValue(clang::DeclarationName N) {
501 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());