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/TypeOrdering.h"
19 #include "clang/Basic/IdentifierTable.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/FoldingSet.h"
22 #include "llvm/Support/raw_ostream.h"
23 using namespace clang;
26 /// CXXSpecialName - Records the type associated with one of the
27 /// "special" kinds of declaration names in C++, e.g., constructors,
28 /// destructors, and conversion functions.
30 : public DeclarationNameExtra, public llvm::FoldingSetNode {
32 /// Type - The type associated with this declaration name.
35 /// FETokenInfo - Extra information associated with this declaration
36 /// name that can be used by the front end.
39 void Profile(llvm::FoldingSetNodeID &ID) {
40 ID.AddInteger(ExtraKindOrNumArgs);
41 ID.AddPointer(Type.getAsOpaquePtr());
45 /// CXXOperatorIdName - Contains extra information for the name of an
46 /// overloaded operator in C++, such as "operator+.
47 class CXXOperatorIdName : public DeclarationNameExtra {
49 /// FETokenInfo - Extra information associated with this operator
50 /// name that can be used by the front end.
54 /// CXXLiberalOperatorName - Contains the actual identifier that makes up the
57 /// This identifier is stored here rather than directly in DeclarationName so as
58 /// to allow Objective-C selectors, which are about a million times more common,
59 /// to consume minimal memory.
60 class CXXLiteralOperatorIdName
61 : public DeclarationNameExtra, public llvm::FoldingSetNode {
65 void Profile(llvm::FoldingSetNodeID &FSID) {
70 static int compareInt(unsigned A, unsigned B) {
71 return (A < B ? -1 : (A > B ? 1 : 0));
74 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
75 if (LHS.getNameKind() != RHS.getNameKind())
76 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
78 switch (LHS.getNameKind()) {
79 case DeclarationName::Identifier: {
80 IdentifierInfo *LII = LHS.getAsIdentifierInfo();
81 IdentifierInfo *RII = RHS.getAsIdentifierInfo();
82 if (!LII) return RII ? -1 : 0;
85 return LII->getName().compare(RII->getName());
88 case DeclarationName::ObjCZeroArgSelector:
89 case DeclarationName::ObjCOneArgSelector:
90 case DeclarationName::ObjCMultiArgSelector: {
91 Selector LHSSelector = LHS.getObjCSelector();
92 Selector RHSSelector = RHS.getObjCSelector();
93 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
94 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
95 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
96 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
98 switch (LHSId->getName().compare(RHSId->getName())) {
100 case 1: return false;
105 return compareInt(LN, RN);
108 case DeclarationName::CXXConstructorName:
109 case DeclarationName::CXXDestructorName:
110 case DeclarationName::CXXConversionFunctionName:
111 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
113 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
117 case DeclarationName::CXXOperatorName:
118 return compareInt(LHS.getCXXOverloadedOperator(),
119 RHS.getCXXOverloadedOperator());
121 case DeclarationName::CXXLiteralOperatorName:
122 return LHS.getCXXLiteralIdentifier()->getName().compare(
123 RHS.getCXXLiteralIdentifier()->getName());
125 case DeclarationName::CXXUsingDirective:
132 } // end namespace clang
134 DeclarationName::DeclarationName(Selector Sel) {
135 if (!Sel.getAsOpaquePtr()) {
140 switch (Sel.getNumArgs()) {
142 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
143 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
144 Ptr |= StoredObjCZeroArgSelector;
148 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
149 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
150 Ptr |= StoredObjCOneArgSelector;
154 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
155 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
156 Ptr |= StoredDeclarationNameExtra;
161 DeclarationName::NameKind DeclarationName::getNameKind() const {
162 switch (getStoredNameKind()) {
163 case StoredIdentifier: return Identifier;
164 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
165 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
167 case StoredDeclarationNameExtra:
168 switch (getExtra()->ExtraKindOrNumArgs) {
169 case DeclarationNameExtra::CXXConstructor:
170 return CXXConstructorName;
172 case DeclarationNameExtra::CXXDestructor:
173 return CXXDestructorName;
175 case DeclarationNameExtra::CXXConversionFunction:
176 return CXXConversionFunctionName;
178 case DeclarationNameExtra::CXXLiteralOperator:
179 return CXXLiteralOperatorName;
181 case DeclarationNameExtra::CXXUsingDirective:
182 return CXXUsingDirective;
185 // Check if we have one of the CXXOperator* enumeration values.
186 if (getExtra()->ExtraKindOrNumArgs <
187 DeclarationNameExtra::CXXUsingDirective)
188 return CXXOperatorName;
190 return ObjCMultiArgSelector;
195 // Can't actually get here.
196 assert(0 && "This should be unreachable!");
200 bool DeclarationName::isDependentName() const {
201 QualType T = getCXXNameType();
202 return !T.isNull() && T->isDependentType();
205 std::string DeclarationName::getAsString() const {
207 llvm::raw_string_ostream OS(Result);
212 void DeclarationName::printName(llvm::raw_ostream &OS) const {
213 switch (getNameKind()) {
215 if (const IdentifierInfo *II = getAsIdentifierInfo())
219 case ObjCZeroArgSelector:
220 case ObjCOneArgSelector:
221 case ObjCMultiArgSelector:
222 OS << getObjCSelector().getAsString();
225 case CXXConstructorName: {
226 QualType ClassType = getCXXNameType();
227 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
228 OS << ClassRec->getDecl();
230 OS << ClassType.getAsString();
234 case CXXDestructorName: {
236 QualType Type = getCXXNameType();
237 if (const RecordType *Rec = Type->getAs<RecordType>())
238 OS << Rec->getDecl();
240 OS << Type.getAsString();
244 case CXXOperatorName: {
245 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
247 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
249 #include "clang/Basic/OperatorKinds.def"
251 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
252 assert(OpName && "not an overloaded operator");
255 if (OpName[0] >= 'a' && OpName[0] <= 'z')
261 case CXXLiteralOperatorName:
262 OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
265 case CXXConversionFunctionName: {
267 QualType Type = getCXXNameType();
268 if (const RecordType *Rec = Type->getAs<RecordType>())
269 OS << Rec->getDecl();
271 OS << Type.getAsString();
274 case CXXUsingDirective:
275 OS << "<using-directive>";
279 assert(false && "Unexpected declaration name kind");
282 QualType DeclarationName::getCXXNameType() const {
283 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
284 return CXXName->Type;
289 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
290 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
292 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
293 return static_cast<OverloadedOperatorKind>(value);
299 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
300 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
306 Selector DeclarationName::getObjCSelector() const {
307 switch (getNameKind()) {
308 case ObjCZeroArgSelector:
309 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
311 case ObjCOneArgSelector:
312 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
314 case ObjCMultiArgSelector:
315 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
324 void *DeclarationName::getFETokenInfoAsVoid() const {
325 switch (getNameKind()) {
327 return getAsIdentifierInfo()->getFETokenInfo<void>();
329 case CXXConstructorName:
330 case CXXDestructorName:
331 case CXXConversionFunctionName:
332 return getAsCXXSpecialName()->FETokenInfo;
334 case CXXOperatorName:
335 return getAsCXXOperatorIdName()->FETokenInfo;
337 case CXXLiteralOperatorName:
338 return getCXXLiteralIdentifier()->getFETokenInfo<void>();
341 assert(false && "Declaration name has no FETokenInfo");
346 void DeclarationName::setFETokenInfo(void *T) {
347 switch (getNameKind()) {
349 getAsIdentifierInfo()->setFETokenInfo(T);
352 case CXXConstructorName:
353 case CXXDestructorName:
354 case CXXConversionFunctionName:
355 getAsCXXSpecialName()->FETokenInfo = T;
358 case CXXOperatorName:
359 getAsCXXOperatorIdName()->FETokenInfo = T;
362 case CXXLiteralOperatorName:
363 getCXXLiteralIdentifier()->setFETokenInfo(T);
367 assert(false && "Declaration name has no FETokenInfo");
371 DeclarationName DeclarationName::getUsingDirectiveName() {
372 // Single instance of DeclarationNameExtra for using-directive
373 static const DeclarationNameExtra UDirExtra =
374 { DeclarationNameExtra::CXXUsingDirective };
376 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
377 Ptr |= StoredDeclarationNameExtra;
379 return DeclarationName(Ptr);
382 void DeclarationName::dump() const {
383 printName(llvm::errs());
384 llvm::errs() << '\n';
387 DeclarationNameTable::DeclarationNameTable(ASTContext &C) : Ctx(C) {
388 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
389 CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
391 // Initialize the overloaded operator names.
392 CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
393 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
394 CXXOperatorNames[Op].ExtraKindOrNumArgs
395 = Op + DeclarationNameExtra::CXXConversionFunction;
396 CXXOperatorNames[Op].FETokenInfo = 0;
400 DeclarationNameTable::~DeclarationNameTable() {
401 llvm::FoldingSet<CXXSpecialName> *SpecialNames =
402 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
403 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
404 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
405 (CXXLiteralOperatorNames);
407 if (Ctx.FreeMemory) {
408 llvm::FoldingSetIterator<CXXSpecialName>
409 SI = SpecialNames->begin(), SE = SpecialNames->end();
412 CXXSpecialName *n = &*SI++;
416 llvm::FoldingSetIterator<CXXLiteralOperatorIdName>
417 LI = LiteralNames->begin(), LE = LiteralNames->end();
420 CXXLiteralOperatorIdName *n = &*LI++;
424 Ctx.Deallocate(CXXOperatorNames);
432 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
434 assert(Kind >= DeclarationName::CXXConstructorName &&
435 Kind <= DeclarationName::CXXConversionFunctionName &&
436 "Kind must be a C++ special name kind");
437 llvm::FoldingSet<CXXSpecialName> *SpecialNames
438 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
440 DeclarationNameExtra::ExtraKind EKind;
442 case DeclarationName::CXXConstructorName:
443 EKind = DeclarationNameExtra::CXXConstructor;
444 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
446 case DeclarationName::CXXDestructorName:
447 EKind = DeclarationNameExtra::CXXDestructor;
448 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
450 case DeclarationName::CXXConversionFunctionName:
451 EKind = DeclarationNameExtra::CXXConversionFunction;
454 return DeclarationName();
457 // Unique selector, to guarantee there is one per name.
458 llvm::FoldingSetNodeID ID;
459 ID.AddInteger(EKind);
460 ID.AddPointer(Ty.getAsOpaquePtr());
463 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
464 return DeclarationName(Name);
466 CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
467 SpecialName->ExtraKindOrNumArgs = EKind;
468 SpecialName->Type = Ty;
469 SpecialName->FETokenInfo = 0;
471 SpecialNames->InsertNode(SpecialName, InsertPos);
472 return DeclarationName(SpecialName);
476 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
477 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
481 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
482 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
483 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
484 (CXXLiteralOperatorNames);
486 llvm::FoldingSetNodeID ID;
490 if (CXXLiteralOperatorIdName *Name =
491 LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
492 return DeclarationName (Name);
494 CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
495 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
496 LiteralName->ID = II;
498 LiteralNames->InsertNode(LiteralName, InsertPos);
499 return DeclarationName(LiteralName);
503 llvm::DenseMapInfo<clang::DeclarationName>::
504 getHashValue(clang::DeclarationName N) {
505 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());