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/Decl.h"
17 #include "clang/Basic/IdentifierTable.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/FoldingSet.h"
20 using namespace clang;
23 /// CXXSpecialName - Records the type associated with one of the
24 /// "special" kinds of declaration names in C++, e.g., constructors,
25 /// destructors, and conversion functions.
27 : public DeclarationNameExtra, public llvm::FoldingSetNode {
29 /// Type - The type associated with this declaration name.
32 /// FETokenInfo - Extra information associated with this declaration
33 /// name that can be used by the front end.
36 void Profile(llvm::FoldingSetNodeID &ID) {
37 ID.AddInteger(ExtraKindOrNumArgs);
38 ID.AddPointer(Type.getAsOpaquePtr());
42 /// CXXOperatorIdName - Contains extra information for the name of an
43 /// overloaded operator in C++, such as "operator+.
44 class CXXOperatorIdName : public DeclarationNameExtra {
46 /// FETokenInfo - Extra information associated with this operator
47 /// name that can be used by the front end.
51 bool operator<(DeclarationName LHS, DeclarationName RHS) {
52 if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
53 if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
54 return LhsId->getName() < RhsId->getName();
56 return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
59 } // end namespace clang
61 DeclarationName::DeclarationName(Selector Sel) {
62 if (!Sel.getAsOpaquePtr()) {
67 switch (Sel.getNumArgs()) {
69 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
70 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
71 Ptr |= StoredObjCZeroArgSelector;
75 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
76 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
77 Ptr |= StoredObjCOneArgSelector;
81 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
82 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
83 Ptr |= StoredDeclarationNameExtra;
88 DeclarationName::NameKind DeclarationName::getNameKind() const {
89 switch (getStoredNameKind()) {
90 case StoredIdentifier: return Identifier;
91 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
92 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
94 case StoredDeclarationNameExtra:
95 switch (getExtra()->ExtraKindOrNumArgs) {
96 case DeclarationNameExtra::CXXConstructor:
97 return CXXConstructorName;
99 case DeclarationNameExtra::CXXDestructor:
100 return CXXDestructorName;
102 case DeclarationNameExtra::CXXConversionFunction:
103 return CXXConversionFunctionName;
105 case DeclarationNameExtra::CXXUsingDirective:
106 return CXXUsingDirective;
109 // Check if we have one of the CXXOperator* enumeration values.
110 if (getExtra()->ExtraKindOrNumArgs <
111 DeclarationNameExtra::CXXUsingDirective)
112 return CXXOperatorName;
114 return ObjCMultiArgSelector;
119 // Can't actually get here.
120 assert(0 && "This should be unreachable!");
124 std::string DeclarationName::getAsString() const {
125 switch (getNameKind()) {
127 if (const IdentifierInfo *II = getAsIdentifierInfo())
128 return II->getName();
131 case ObjCZeroArgSelector:
132 case ObjCOneArgSelector:
133 case ObjCMultiArgSelector:
134 return getObjCSelector().getAsString();
136 case CXXConstructorName: {
137 QualType ClassType = getCXXNameType();
138 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
139 return ClassRec->getDecl()->getNameAsString();
140 return ClassType.getAsString();
143 case CXXDestructorName: {
144 std::string Result = "~";
145 QualType Type = getCXXNameType();
146 if (const RecordType *Rec = Type->getAs<RecordType>())
147 Result += Rec->getDecl()->getNameAsString();
149 Result += Type.getAsString();
153 case CXXOperatorName: {
154 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
156 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
158 #include "clang/Basic/OperatorKinds.def"
160 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
161 assert(OpName && "not an overloaded operator");
163 std::string Result = "operator";
164 if (OpName[0] >= 'a' && OpName[0] <= 'z')
170 case CXXConversionFunctionName: {
171 std::string Result = "operator ";
172 QualType Type = getCXXNameType();
173 if (const RecordType *Rec = Type->getAs<RecordType>())
174 Result += Rec->getDecl()->getNameAsString();
176 Result += Type.getAsString();
179 case CXXUsingDirective:
180 return "<using-directive>";
183 assert(false && "Unexpected declaration name kind");
187 QualType DeclarationName::getCXXNameType() const {
188 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
189 return CXXName->Type;
194 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
195 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
197 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
198 return static_cast<OverloadedOperatorKind>(value);
204 Selector DeclarationName::getObjCSelector() const {
205 switch (getNameKind()) {
206 case ObjCZeroArgSelector:
207 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
209 case ObjCOneArgSelector:
210 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
212 case ObjCMultiArgSelector:
213 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
222 void *DeclarationName::getFETokenInfoAsVoid() const {
223 switch (getNameKind()) {
225 return getAsIdentifierInfo()->getFETokenInfo<void>();
227 case CXXConstructorName:
228 case CXXDestructorName:
229 case CXXConversionFunctionName:
230 return getAsCXXSpecialName()->FETokenInfo;
232 case CXXOperatorName:
233 return getAsCXXOperatorIdName()->FETokenInfo;
236 assert(false && "Declaration name has no FETokenInfo");
241 void DeclarationName::setFETokenInfo(void *T) {
242 switch (getNameKind()) {
244 getAsIdentifierInfo()->setFETokenInfo(T);
247 case CXXConstructorName:
248 case CXXDestructorName:
249 case CXXConversionFunctionName:
250 getAsCXXSpecialName()->FETokenInfo = T;
253 case CXXOperatorName:
254 getAsCXXOperatorIdName()->FETokenInfo = T;
258 assert(false && "Declaration name has no FETokenInfo");
262 DeclarationName DeclarationName::getUsingDirectiveName() {
263 // Single instance of DeclarationNameExtra for using-directive
264 static DeclarationNameExtra UDirExtra =
265 { DeclarationNameExtra::CXXUsingDirective };
267 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
268 Ptr |= StoredDeclarationNameExtra;
270 return DeclarationName(Ptr);
273 DeclarationNameTable::DeclarationNameTable() {
274 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
276 // Initialize the overloaded operator names.
277 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
278 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
279 CXXOperatorNames[Op].ExtraKindOrNumArgs
280 = Op + DeclarationNameExtra::CXXConversionFunction;
281 CXXOperatorNames[Op].FETokenInfo = 0;
285 DeclarationNameTable::~DeclarationNameTable() {
286 llvm::FoldingSet<CXXSpecialName> *set =
287 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
288 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
291 CXXSpecialName *n = &*I++;
296 delete [] CXXOperatorNames;
300 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
302 assert(Kind >= DeclarationName::CXXConstructorName &&
303 Kind <= DeclarationName::CXXConversionFunctionName &&
304 "Kind must be a C++ special name kind");
305 llvm::FoldingSet<CXXSpecialName> *SpecialNames
306 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
308 DeclarationNameExtra::ExtraKind EKind;
310 case DeclarationName::CXXConstructorName:
311 EKind = DeclarationNameExtra::CXXConstructor;
312 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
314 case DeclarationName::CXXDestructorName:
315 EKind = DeclarationNameExtra::CXXDestructor;
316 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
318 case DeclarationName::CXXConversionFunctionName:
319 EKind = DeclarationNameExtra::CXXConversionFunction;
322 return DeclarationName();
325 // Unique selector, to guarantee there is one per name.
326 llvm::FoldingSetNodeID ID;
327 ID.AddInteger(EKind);
328 ID.AddPointer(Ty.getAsOpaquePtr());
331 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
332 return DeclarationName(Name);
334 CXXSpecialName *SpecialName = new CXXSpecialName;
335 SpecialName->ExtraKindOrNumArgs = EKind;
336 SpecialName->Type = Ty;
337 SpecialName->FETokenInfo = 0;
339 SpecialNames->InsertNode(SpecialName, InsertPos);
340 return DeclarationName(SpecialName);
344 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
345 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
349 llvm::DenseMapInfo<clang::DeclarationName>::
350 getHashValue(clang::DeclarationName N) {
351 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());