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 bool operator<(DeclarationName LHS, DeclarationName RHS) {
54 if (LHS.getNameKind() != RHS.getNameKind())
55 return LHS.getNameKind() < RHS.getNameKind();
57 switch (LHS.getNameKind()) {
58 case DeclarationName::Identifier:
59 return LHS.getAsIdentifierInfo()->getName() <
60 RHS.getAsIdentifierInfo()->getName();
62 case DeclarationName::ObjCZeroArgSelector:
63 case DeclarationName::ObjCOneArgSelector:
64 case DeclarationName::ObjCMultiArgSelector: {
65 Selector LHSSelector = LHS.getObjCSelector();
66 Selector RHSSelector = RHS.getObjCSelector();
68 N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
70 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
71 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
73 return LHSId && !RHSId;
75 switch (LHSId->getName().compare(RHSId->getName())) {
82 return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
85 case DeclarationName::CXXConstructorName:
86 case DeclarationName::CXXDestructorName:
87 case DeclarationName::CXXConversionFunctionName:
88 return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
90 case DeclarationName::CXXOperatorName:
91 return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
93 case DeclarationName::CXXUsingDirective:
100 } // end namespace clang
102 DeclarationName::DeclarationName(Selector Sel) {
103 if (!Sel.getAsOpaquePtr()) {
108 switch (Sel.getNumArgs()) {
110 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
111 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
112 Ptr |= StoredObjCZeroArgSelector;
116 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
117 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
118 Ptr |= StoredObjCOneArgSelector;
122 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
123 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
124 Ptr |= StoredDeclarationNameExtra;
129 DeclarationName::NameKind DeclarationName::getNameKind() const {
130 switch (getStoredNameKind()) {
131 case StoredIdentifier: return Identifier;
132 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
133 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
135 case StoredDeclarationNameExtra:
136 switch (getExtra()->ExtraKindOrNumArgs) {
137 case DeclarationNameExtra::CXXConstructor:
138 return CXXConstructorName;
140 case DeclarationNameExtra::CXXDestructor:
141 return CXXDestructorName;
143 case DeclarationNameExtra::CXXConversionFunction:
144 return CXXConversionFunctionName;
146 case DeclarationNameExtra::CXXUsingDirective:
147 return CXXUsingDirective;
150 // Check if we have one of the CXXOperator* enumeration values.
151 if (getExtra()->ExtraKindOrNumArgs <
152 DeclarationNameExtra::CXXUsingDirective)
153 return CXXOperatorName;
155 return ObjCMultiArgSelector;
160 // Can't actually get here.
161 assert(0 && "This should be unreachable!");
165 std::string DeclarationName::getAsString() const {
166 switch (getNameKind()) {
168 if (const IdentifierInfo *II = getAsIdentifierInfo())
169 return II->getName();
172 case ObjCZeroArgSelector:
173 case ObjCOneArgSelector:
174 case ObjCMultiArgSelector:
175 return getObjCSelector().getAsString();
177 case CXXConstructorName: {
178 QualType ClassType = getCXXNameType();
179 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
180 return ClassRec->getDecl()->getNameAsString();
181 return ClassType.getAsString();
184 case CXXDestructorName: {
185 std::string Result = "~";
186 QualType Type = getCXXNameType();
187 if (const RecordType *Rec = Type->getAs<RecordType>())
188 Result += Rec->getDecl()->getNameAsString();
190 Result += Type.getAsString();
194 case CXXOperatorName: {
195 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
197 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
199 #include "clang/Basic/OperatorKinds.def"
201 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
202 assert(OpName && "not an overloaded operator");
204 std::string Result = "operator";
205 if (OpName[0] >= 'a' && OpName[0] <= 'z')
211 case CXXConversionFunctionName: {
212 std::string Result = "operator ";
213 QualType Type = getCXXNameType();
214 if (const RecordType *Rec = Type->getAs<RecordType>())
215 Result += Rec->getDecl()->getNameAsString();
217 Result += Type.getAsString();
220 case CXXUsingDirective:
221 return "<using-directive>";
224 assert(false && "Unexpected declaration name kind");
228 QualType DeclarationName::getCXXNameType() const {
229 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
230 return CXXName->Type;
235 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
236 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
238 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
239 return static_cast<OverloadedOperatorKind>(value);
245 Selector DeclarationName::getObjCSelector() const {
246 switch (getNameKind()) {
247 case ObjCZeroArgSelector:
248 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
250 case ObjCOneArgSelector:
251 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
253 case ObjCMultiArgSelector:
254 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
263 void *DeclarationName::getFETokenInfoAsVoid() const {
264 switch (getNameKind()) {
266 return getAsIdentifierInfo()->getFETokenInfo<void>();
268 case CXXConstructorName:
269 case CXXDestructorName:
270 case CXXConversionFunctionName:
271 return getAsCXXSpecialName()->FETokenInfo;
273 case CXXOperatorName:
274 return getAsCXXOperatorIdName()->FETokenInfo;
277 assert(false && "Declaration name has no FETokenInfo");
282 void DeclarationName::setFETokenInfo(void *T) {
283 switch (getNameKind()) {
285 getAsIdentifierInfo()->setFETokenInfo(T);
288 case CXXConstructorName:
289 case CXXDestructorName:
290 case CXXConversionFunctionName:
291 getAsCXXSpecialName()->FETokenInfo = T;
294 case CXXOperatorName:
295 getAsCXXOperatorIdName()->FETokenInfo = T;
299 assert(false && "Declaration name has no FETokenInfo");
303 DeclarationName DeclarationName::getUsingDirectiveName() {
304 // Single instance of DeclarationNameExtra for using-directive
305 static DeclarationNameExtra UDirExtra =
306 { DeclarationNameExtra::CXXUsingDirective };
308 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
309 Ptr |= StoredDeclarationNameExtra;
311 return DeclarationName(Ptr);
314 void DeclarationName::dump() const {
315 fprintf(stderr, "%s\n", getAsString().c_str());
318 DeclarationNameTable::DeclarationNameTable() {
319 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
321 // Initialize the overloaded operator names.
322 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
323 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
324 CXXOperatorNames[Op].ExtraKindOrNumArgs
325 = Op + DeclarationNameExtra::CXXConversionFunction;
326 CXXOperatorNames[Op].FETokenInfo = 0;
330 DeclarationNameTable::~DeclarationNameTable() {
331 llvm::FoldingSet<CXXSpecialName> *set =
332 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
333 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
336 CXXSpecialName *n = &*I++;
341 delete [] CXXOperatorNames;
345 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
347 assert(Kind >= DeclarationName::CXXConstructorName &&
348 Kind <= DeclarationName::CXXConversionFunctionName &&
349 "Kind must be a C++ special name kind");
350 llvm::FoldingSet<CXXSpecialName> *SpecialNames
351 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
353 DeclarationNameExtra::ExtraKind EKind;
355 case DeclarationName::CXXConstructorName:
356 EKind = DeclarationNameExtra::CXXConstructor;
357 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
359 case DeclarationName::CXXDestructorName:
360 EKind = DeclarationNameExtra::CXXDestructor;
361 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
363 case DeclarationName::CXXConversionFunctionName:
364 EKind = DeclarationNameExtra::CXXConversionFunction;
367 return DeclarationName();
370 // Unique selector, to guarantee there is one per name.
371 llvm::FoldingSetNodeID ID;
372 ID.AddInteger(EKind);
373 ID.AddPointer(Ty.getAsOpaquePtr());
376 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
377 return DeclarationName(Name);
379 CXXSpecialName *SpecialName = new CXXSpecialName;
380 SpecialName->ExtraKindOrNumArgs = EKind;
381 SpecialName->Type = Ty;
382 SpecialName->FETokenInfo = 0;
384 SpecialNames->InsertNode(SpecialName, InsertPos);
385 return DeclarationName(SpecialName);
389 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
390 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
394 llvm::DenseMapInfo<clang::DeclarationName>::
395 getHashValue(clang::DeclarationName N) {
396 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());