blob: 5cc0aab5ee3f4e55cd4404044649c5cd9e47063c [file] [log] [blame]
Douglas Gregor24afd4a2008-11-17 14:58:09 +00001//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the DeclarationName and DeclarationNameTable
11// classes.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/AST/DeclarationName.h"
Douglas Gregor6704b312008-11-17 22:58:34 +000015#include "clang/AST/Type.h"
16#include "clang/AST/Decl.h"
Douglas Gregor24afd4a2008-11-17 14:58:09 +000017#include "clang/Basic/IdentifierTable.h"
Douglas Gregor608ff622009-04-22 21:45:53 +000018#include "llvm/ADT/DenseMap.h"
Douglas Gregor24afd4a2008-11-17 14:58:09 +000019#include "llvm/ADT/FoldingSet.h"
Douglas Gregor24afd4a2008-11-17 14:58:09 +000020using namespace clang;
21
22namespace 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.
26class CXXSpecialName
27 : public DeclarationNameExtra, public llvm::FoldingSetNode {
28public:
Douglas Gregorb0212bd2008-11-17 20:34:05 +000029 /// Type - The type associated with this declaration name.
Douglas Gregor24afd4a2008-11-17 14:58:09 +000030 QualType Type;
31
Douglas Gregorb0212bd2008-11-17 20:34:05 +000032 /// FETokenInfo - Extra information associated with this declaration
33 /// name that can be used by the front end.
34 void *FETokenInfo;
35
Douglas Gregor24afd4a2008-11-17 14:58:09 +000036 void Profile(llvm::FoldingSetNodeID &ID) {
37 ID.AddInteger(ExtraKindOrNumArgs);
38 ID.AddPointer(Type.getAsOpaquePtr());
39 }
40};
41
Douglas Gregor96a32dd2008-11-18 14:39:36 +000042/// CXXOperatorIdName - Contains extra information for the name of an
43/// overloaded operator in C++, such as "operator+.
44class CXXOperatorIdName : public DeclarationNameExtra {
45public:
46 /// FETokenInfo - Extra information associated with this operator
47 /// name that can be used by the front end.
48 void *FETokenInfo;
49};
50
Douglas Gregor24afd4a2008-11-17 14:58:09 +000051bool operator<(DeclarationName LHS, DeclarationName RHS) {
52 if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
53 if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
54 return strcmp(LhsId->getName(), RhsId->getName()) < 0;
55
56 return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
57}
58
59} // end namespace clang
60
61DeclarationName::DeclarationName(Selector Sel) {
62 switch (Sel.getNumArgs()) {
63 case 0:
64 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenekc5f6de02009-03-14 00:27:40 +000065 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor24afd4a2008-11-17 14:58:09 +000066 Ptr |= StoredObjCZeroArgSelector;
67 break;
68
69 case 1:
70 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenekc5f6de02009-03-14 00:27:40 +000071 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor24afd4a2008-11-17 14:58:09 +000072 Ptr |= StoredObjCOneArgSelector;
73 break;
74
75 default:
76 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Ted Kremenekc5f6de02009-03-14 00:27:40 +000077 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Douglas Gregor96a32dd2008-11-18 14:39:36 +000078 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor24afd4a2008-11-17 14:58:09 +000079 break;
80 }
81}
82
83DeclarationName::NameKind DeclarationName::getNameKind() const {
84 switch (getStoredNameKind()) {
85 case StoredIdentifier: return Identifier;
86 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
87 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
88
Douglas Gregor96a32dd2008-11-18 14:39:36 +000089 case StoredDeclarationNameExtra:
Douglas Gregor24afd4a2008-11-17 14:58:09 +000090 switch (getExtra()->ExtraKindOrNumArgs) {
91 case DeclarationNameExtra::CXXConstructor:
92 return CXXConstructorName;
93
94 case DeclarationNameExtra::CXXDestructor:
95 return CXXDestructorName;
96
97 case DeclarationNameExtra::CXXConversionFunction:
98 return CXXConversionFunctionName;
99
Douglas Gregor7a7be652009-02-03 19:21:40 +0000100 case DeclarationNameExtra::CXXUsingDirective:
101 return CXXUsingDirective;
102
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000103 default:
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000104 // Check if we have one of the CXXOperator* enumeration values.
105 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor7a7be652009-02-03 19:21:40 +0000106 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000107 return CXXOperatorName;
108
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000109 return ObjCMultiArgSelector;
110 }
111 break;
112 }
113
114 // Can't actually get here.
Chris Lattner86913d42009-03-21 06:40:50 +0000115 assert(0 && "This should be unreachable!");
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000116 return Identifier;
117}
118
Douglas Gregor6704b312008-11-17 22:58:34 +0000119std::string DeclarationName::getAsString() const {
120 switch (getNameKind()) {
121 case Identifier:
122 if (const IdentifierInfo *II = getAsIdentifierInfo())
123 return II->getName();
124 return "";
125
126 case ObjCZeroArgSelector:
127 case ObjCOneArgSelector:
128 case ObjCMultiArgSelector:
Chris Lattner3a8f2942008-11-24 03:33:13 +0000129 return getObjCSelector().getAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000130
131 case CXXConstructorName: {
132 QualType ClassType = getCXXNameType();
133 if (const RecordType *ClassRec = ClassType->getAsRecordType())
Chris Lattner6c5ec622008-11-24 04:00:27 +0000134 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000135 return ClassType.getAsString();
136 }
137
138 case CXXDestructorName: {
139 std::string Result = "~";
140 QualType Type = getCXXNameType();
141 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner6c5ec622008-11-24 04:00:27 +0000142 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000143 else
144 Result += Type.getAsString();
145 return Result;
146 }
147
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000148 case CXXOperatorName: {
149 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
150 0,
151#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
152 Spelling,
153#include "clang/Basic/OperatorKinds.def"
154 };
155 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
156 assert(OpName && "not an overloaded operator");
157
158 std::string Result = "operator";
159 if (OpName[0] >= 'a' && OpName[0] <= 'z')
160 Result += ' ';
161 Result += OpName;
162 return Result;
163 }
164
Douglas Gregor6704b312008-11-17 22:58:34 +0000165 case CXXConversionFunctionName: {
166 std::string Result = "operator ";
167 QualType Type = getCXXNameType();
168 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner6c5ec622008-11-24 04:00:27 +0000169 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000170 else
171 Result += Type.getAsString();
172 return Result;
173 }
Douglas Gregor7a7be652009-02-03 19:21:40 +0000174 case CXXUsingDirective:
175 return "<using-directive>";
Douglas Gregor6704b312008-11-17 22:58:34 +0000176 }
177
178 assert(false && "Unexpected declaration name kind");
179 return "";
180}
181
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000182QualType DeclarationName::getCXXNameType() const {
183 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
184 return CXXName->Type;
185 else
186 return QualType();
187}
188
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000189OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
190 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
191 unsigned value
192 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
193 return static_cast<OverloadedOperatorKind>(value);
194 } else {
195 return OO_None;
196 }
197}
198
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000199Selector DeclarationName::getObjCSelector() const {
200 switch (getNameKind()) {
201 case ObjCZeroArgSelector:
202 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
203
204 case ObjCOneArgSelector:
205 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
206
207 case ObjCMultiArgSelector:
208 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
209
210 default:
211 break;
212 }
213
214 return Selector();
215}
216
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000217void *DeclarationName::getFETokenInfoAsVoid() const {
218 switch (getNameKind()) {
219 case Identifier:
220 return getAsIdentifierInfo()->getFETokenInfo<void>();
221
222 case CXXConstructorName:
223 case CXXDestructorName:
224 case CXXConversionFunctionName:
225 return getAsCXXSpecialName()->FETokenInfo;
226
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000227 case CXXOperatorName:
228 return getAsCXXOperatorIdName()->FETokenInfo;
229
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000230 default:
231 assert(false && "Declaration name has no FETokenInfo");
232 }
233 return 0;
234}
235
236void DeclarationName::setFETokenInfo(void *T) {
237 switch (getNameKind()) {
238 case Identifier:
239 getAsIdentifierInfo()->setFETokenInfo(T);
240 break;
241
242 case CXXConstructorName:
243 case CXXDestructorName:
244 case CXXConversionFunctionName:
245 getAsCXXSpecialName()->FETokenInfo = T;
246 break;
247
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000248 case CXXOperatorName:
249 getAsCXXOperatorIdName()->FETokenInfo = T;
250 break;
251
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000252 default:
253 assert(false && "Declaration name has no FETokenInfo");
254 }
255}
256
Douglas Gregor7a7be652009-02-03 19:21:40 +0000257DeclarationName DeclarationName::getUsingDirectiveName() {
258 // Single instance of DeclarationNameExtra for using-directive
259 static DeclarationNameExtra UDirExtra =
260 { DeclarationNameExtra::CXXUsingDirective };
261
262 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
263 Ptr |= StoredDeclarationNameExtra;
264
265 return DeclarationName(Ptr);
266}
267
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000268DeclarationNameTable::DeclarationNameTable() {
269 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000270
271 // Initialize the overloaded operator names.
272 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
273 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
274 CXXOperatorNames[Op].ExtraKindOrNumArgs
275 = Op + DeclarationNameExtra::CXXConversionFunction;
276 CXXOperatorNames[Op].FETokenInfo = 0;
277 }
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000278}
279
280DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes8f3bb2a2008-12-14 17:27:25 +0000281 llvm::FoldingSet<CXXSpecialName> *set =
282 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopes1640bf22008-12-14 21:53:25 +0000283 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes8f3bb2a2008-12-14 17:27:25 +0000284
Nuno Lopes1640bf22008-12-14 21:53:25 +0000285 while (I != E) {
286 CXXSpecialName *n = &*I++;
287 delete n;
Nuno Lopes8f3bb2a2008-12-14 17:27:25 +0000288 }
289
290 delete set;
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000291 delete [] CXXOperatorNames;
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000292}
293
294DeclarationName
295DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
296 QualType Ty) {
297 assert(Kind >= DeclarationName::CXXConstructorName &&
298 Kind <= DeclarationName::CXXConversionFunctionName &&
299 "Kind must be a C++ special name kind");
300
301 llvm::FoldingSet<CXXSpecialName> *SpecialNames
302 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
303
304 DeclarationNameExtra::ExtraKind EKind;
305 switch (Kind) {
306 case DeclarationName::CXXConstructorName:
307 EKind = DeclarationNameExtra::CXXConstructor;
Chris Lattnerb6eccdc2009-02-16 22:33:34 +0000308 assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000309 break;
310 case DeclarationName::CXXDestructorName:
311 EKind = DeclarationNameExtra::CXXDestructor;
Douglas Gregor036b5a02009-01-13 00:11:19 +0000312 assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000313 break;
314 case DeclarationName::CXXConversionFunctionName:
315 EKind = DeclarationNameExtra::CXXConversionFunction;
316 break;
317 default:
318 return DeclarationName();
319 }
320
321 // Unique selector, to guarantee there is one per name.
322 llvm::FoldingSetNodeID ID;
323 ID.AddInteger(EKind);
324 ID.AddPointer(Ty.getAsOpaquePtr());
325
326 void *InsertPos = 0;
327 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
328 return DeclarationName(Name);
329
330 CXXSpecialName *SpecialName = new CXXSpecialName;
331 SpecialName->ExtraKindOrNumArgs = EKind;
332 SpecialName->Type = Ty;
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000333 SpecialName->FETokenInfo = 0;
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000334
335 SpecialNames->InsertNode(SpecialName, InsertPos);
336 return DeclarationName(SpecialName);
337}
338
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000339DeclarationName
340DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
341 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
342}
343
Douglas Gregor8acb7272008-12-11 16:49:14 +0000344unsigned
345llvm::DenseMapInfo<clang::DeclarationName>::
346getHashValue(clang::DeclarationName N) {
347 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
348}
349