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"
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 : public DeclarationNameExtra {
64 bool operator<(DeclarationName LHS, DeclarationName RHS) {
65 if (LHS.getNameKind() != RHS.getNameKind())
66 return LHS.getNameKind() < RHS.getNameKind();
68 switch (LHS.getNameKind()) {
69 case DeclarationName::Identifier:
70 return LHS.getAsIdentifierInfo()->getName() <
71 RHS.getAsIdentifierInfo()->getName();
73 case DeclarationName::ObjCZeroArgSelector:
74 case DeclarationName::ObjCOneArgSelector:
75 case DeclarationName::ObjCMultiArgSelector: {
76 Selector LHSSelector = LHS.getObjCSelector();
77 Selector RHSSelector = RHS.getObjCSelector();
79 N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
81 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
82 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
84 return LHSId && !RHSId;
86 switch (LHSId->getName().compare(RHSId->getName())) {
93 return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
96 case DeclarationName::CXXConstructorName:
97 case DeclarationName::CXXDestructorName:
98 case DeclarationName::CXXConversionFunctionName:
99 return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
101 case DeclarationName::CXXOperatorName:
102 return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
104 case DeclarationName::CXXLiteralOperatorName:
105 return LHS.getCXXLiteralIdentifier()->getName() <
106 RHS.getCXXLiteralIdentifier()->getName();
108 case DeclarationName::CXXUsingDirective:
115 } // end namespace clang
117 DeclarationName::DeclarationName(Selector Sel) {
118 if (!Sel.getAsOpaquePtr()) {
123 switch (Sel.getNumArgs()) {
125 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
126 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
127 Ptr |= StoredObjCZeroArgSelector;
131 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
132 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
133 Ptr |= StoredObjCOneArgSelector;
137 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
138 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
139 Ptr |= StoredDeclarationNameExtra;
144 DeclarationName::NameKind DeclarationName::getNameKind() const {
145 switch (getStoredNameKind()) {
146 case StoredIdentifier: return Identifier;
147 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
148 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
150 case StoredDeclarationNameExtra:
151 switch (getExtra()->ExtraKindOrNumArgs) {
152 case DeclarationNameExtra::CXXConstructor:
153 return CXXConstructorName;
155 case DeclarationNameExtra::CXXDestructor:
156 return CXXDestructorName;
158 case DeclarationNameExtra::CXXConversionFunction:
159 return CXXConversionFunctionName;
161 case DeclarationNameExtra::CXXLiteralOperator:
162 return CXXLiteralOperatorName;
164 case DeclarationNameExtra::CXXUsingDirective:
165 return CXXUsingDirective;
168 // Check if we have one of the CXXOperator* enumeration values.
169 if (getExtra()->ExtraKindOrNumArgs <
170 DeclarationNameExtra::CXXUsingDirective)
171 return CXXOperatorName;
173 return ObjCMultiArgSelector;
178 // Can't actually get here.
179 assert(0 && "This should be unreachable!");
183 std::string DeclarationName::getAsString() const {
184 switch (getNameKind()) {
186 if (const IdentifierInfo *II = getAsIdentifierInfo())
187 return II->getName();
190 case ObjCZeroArgSelector:
191 case ObjCOneArgSelector:
192 case ObjCMultiArgSelector:
193 return getObjCSelector().getAsString();
195 case CXXConstructorName: {
196 QualType ClassType = getCXXNameType();
197 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
198 return ClassRec->getDecl()->getNameAsString();
199 return ClassType.getAsString();
202 case CXXDestructorName: {
203 std::string Result = "~";
204 QualType Type = getCXXNameType();
205 if (const RecordType *Rec = Type->getAs<RecordType>())
206 Result += Rec->getDecl()->getNameAsString();
208 Result += Type.getAsString();
212 case CXXOperatorName: {
213 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
215 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
217 #include "clang/Basic/OperatorKinds.def"
219 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
220 assert(OpName && "not an overloaded operator");
222 std::string Result = "operator";
223 if (OpName[0] >= 'a' && OpName[0] <= 'z')
229 case CXXLiteralOperatorName: {
230 return "operator \"\" " + std::string(getCXXLiteralIdentifier()->getName());
233 case CXXConversionFunctionName: {
234 std::string Result = "operator ";
235 QualType Type = getCXXNameType();
236 if (const RecordType *Rec = Type->getAs<RecordType>())
237 Result += Rec->getDecl()->getNameAsString();
239 Result += Type.getAsString();
242 case CXXUsingDirective:
243 return "<using-directive>";
246 assert(false && "Unexpected declaration name kind");
250 QualType DeclarationName::getCXXNameType() const {
251 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
252 return CXXName->Type;
257 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
258 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
260 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
261 return static_cast<OverloadedOperatorKind>(value);
267 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
268 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
274 Selector DeclarationName::getObjCSelector() const {
275 switch (getNameKind()) {
276 case ObjCZeroArgSelector:
277 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
279 case ObjCOneArgSelector:
280 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
282 case ObjCMultiArgSelector:
283 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
292 void *DeclarationName::getFETokenInfoAsVoid() const {
293 switch (getNameKind()) {
295 return getAsIdentifierInfo()->getFETokenInfo<void>();
297 case CXXConstructorName:
298 case CXXDestructorName:
299 case CXXConversionFunctionName:
300 return getAsCXXSpecialName()->FETokenInfo;
302 case CXXOperatorName:
303 return getAsCXXOperatorIdName()->FETokenInfo;
305 case CXXLiteralOperatorName:
306 return getCXXLiteralIdentifier()->getFETokenInfo<void>();
309 assert(false && "Declaration name has no FETokenInfo");
314 void DeclarationName::setFETokenInfo(void *T) {
315 switch (getNameKind()) {
317 getAsIdentifierInfo()->setFETokenInfo(T);
320 case CXXConstructorName:
321 case CXXDestructorName:
322 case CXXConversionFunctionName:
323 getAsCXXSpecialName()->FETokenInfo = T;
326 case CXXOperatorName:
327 getAsCXXOperatorIdName()->FETokenInfo = T;
330 case CXXLiteralOperatorName:
331 getCXXLiteralIdentifier()->setFETokenInfo(T);
335 assert(false && "Declaration name has no FETokenInfo");
339 DeclarationName DeclarationName::getUsingDirectiveName() {
340 // Single instance of DeclarationNameExtra for using-directive
341 static const DeclarationNameExtra UDirExtra =
342 { DeclarationNameExtra::CXXUsingDirective };
344 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
345 Ptr |= StoredDeclarationNameExtra;
347 return DeclarationName(Ptr);
350 void DeclarationName::dump() const {
351 fprintf(stderr, "%s\n", getAsString().c_str());
354 DeclarationNameTable::DeclarationNameTable() {
355 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
357 // Initialize the overloaded operator names.
358 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
359 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
360 CXXOperatorNames[Op].ExtraKindOrNumArgs
361 = Op + DeclarationNameExtra::CXXConversionFunction;
362 CXXOperatorNames[Op].FETokenInfo = 0;
366 DeclarationNameTable::~DeclarationNameTable() {
367 llvm::FoldingSet<CXXSpecialName> *set =
368 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
369 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
372 CXXSpecialName *n = &*I++;
377 delete [] CXXOperatorNames;
381 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
383 assert(Kind >= DeclarationName::CXXConstructorName &&
384 Kind <= DeclarationName::CXXConversionFunctionName &&
385 "Kind must be a C++ special name kind");
386 llvm::FoldingSet<CXXSpecialName> *SpecialNames
387 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
389 DeclarationNameExtra::ExtraKind EKind;
391 case DeclarationName::CXXConstructorName:
392 EKind = DeclarationNameExtra::CXXConstructor;
393 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
395 case DeclarationName::CXXDestructorName:
396 EKind = DeclarationNameExtra::CXXDestructor;
397 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
399 case DeclarationName::CXXConversionFunctionName:
400 EKind = DeclarationNameExtra::CXXConversionFunction;
403 return DeclarationName();
406 // Unique selector, to guarantee there is one per name.
407 llvm::FoldingSetNodeID ID;
408 ID.AddInteger(EKind);
409 ID.AddPointer(Ty.getAsOpaquePtr());
412 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
413 return DeclarationName(Name);
415 CXXSpecialName *SpecialName = new CXXSpecialName;
416 SpecialName->ExtraKindOrNumArgs = EKind;
417 SpecialName->Type = Ty;
418 SpecialName->FETokenInfo = 0;
420 SpecialNames->InsertNode(SpecialName, InsertPos);
421 return DeclarationName(SpecialName);
425 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
426 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
430 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
431 CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
432 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
433 LiteralName->ID = II;
434 return DeclarationName(LiteralName);
438 llvm::DenseMapInfo<clang::DeclarationName>::
439 getHashValue(clang::DeclarationName N) {
440 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());