blob: 3471657b652374d5ff581f9279171feffcb0bfc0 [file] [log] [blame]
Douglas Gregor2e1cd422008-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 Gregor10bd3682008-11-17 22:58:34 +000015#include "clang/AST/Type.h"
Douglas Gregord6b5f132009-11-04 22:24:30 +000016#include "clang/AST/TypeOrdering.h"
Douglas Gregor10bd3682008-11-17 22:58:34 +000017#include "clang/AST/Decl.h"
Douglas Gregor2e1cd422008-11-17 14:58:09 +000018#include "clang/Basic/IdentifierTable.h"
Douglas Gregor370187c2009-04-22 21:45:53 +000019#include "llvm/ADT/DenseMap.h"
Douglas Gregor2e1cd422008-11-17 14:58:09 +000020#include "llvm/ADT/FoldingSet.h"
Chandler Carruth894993f2009-11-15 23:10:57 +000021#include <cstdio>
Douglas Gregor2e1cd422008-11-17 14:58:09 +000022using namespace clang;
23
24namespace 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.
Mike Stump1eb44332009-09-09 15:08:12 +000028class CXXSpecialName
Douglas Gregor2e1cd422008-11-17 14:58:09 +000029 : public DeclarationNameExtra, public llvm::FoldingSetNode {
30public:
Douglas Gregor2def4832008-11-17 20:34:05 +000031 /// Type - The type associated with this declaration name.
Douglas Gregor2e1cd422008-11-17 14:58:09 +000032 QualType Type;
33
Douglas Gregor2def4832008-11-17 20:34:05 +000034 /// FETokenInfo - Extra information associated with this declaration
35 /// name that can be used by the front end.
36 void *FETokenInfo;
37
Douglas Gregor2e1cd422008-11-17 14:58:09 +000038 void Profile(llvm::FoldingSetNodeID &ID) {
39 ID.AddInteger(ExtraKindOrNumArgs);
40 ID.AddPointer(Type.getAsOpaquePtr());
41 }
42};
43
Douglas Gregore94ca9e42008-11-18 14:39:36 +000044/// CXXOperatorIdName - Contains extra information for the name of an
Mike Stump1eb44332009-09-09 15:08:12 +000045/// overloaded operator in C++, such as "operator+.
Douglas Gregore94ca9e42008-11-18 14:39:36 +000046class CXXOperatorIdName : public DeclarationNameExtra {
47public:
48 /// FETokenInfo - Extra information associated with this operator
49 /// name that can be used by the front end.
50 void *FETokenInfo;
51};
52
Sean Hunt3e518bd2009-11-29 07:34:05 +000053/// CXXLiberalOperatorName - Contains the actual identifier that makes up the
54/// name.
55///
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.
59class CXXLiteralOperatorIdName : public DeclarationNameExtra {
60public:
61 IdentifierInfo *ID;
62};
63
Douglas Gregor2e1cd422008-11-17 14:58:09 +000064bool operator<(DeclarationName LHS, DeclarationName RHS) {
Douglas Gregord6b5f132009-11-04 22:24:30 +000065 if (LHS.getNameKind() != RHS.getNameKind())
66 return LHS.getNameKind() < RHS.getNameKind();
67
68 switch (LHS.getNameKind()) {
69 case DeclarationName::Identifier:
70 return LHS.getAsIdentifierInfo()->getName() <
71 RHS.getAsIdentifierInfo()->getName();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000072
Douglas Gregord6b5f132009-11-04 22:24:30 +000073 case DeclarationName::ObjCZeroArgSelector:
74 case DeclarationName::ObjCOneArgSelector:
75 case DeclarationName::ObjCMultiArgSelector: {
76 Selector LHSSelector = LHS.getObjCSelector();
77 Selector RHSSelector = RHS.getObjCSelector();
78 for (unsigned I = 0,
79 N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
80 I != N; ++I) {
81 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
82 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
83 if (!LHSId || !RHSId)
84 return LHSId && !RHSId;
85
86 switch (LHSId->getName().compare(RHSId->getName())) {
87 case -1: return true;
88 case 1: return false;
89 default: break;
90 }
91 }
92
93 return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
94 }
95
96 case DeclarationName::CXXConstructorName:
97 case DeclarationName::CXXDestructorName:
98 case DeclarationName::CXXConversionFunctionName:
99 return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
100
101 case DeclarationName::CXXOperatorName:
102 return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
Sean Hunt3e518bd2009-11-29 07:34:05 +0000103
104 case DeclarationName::CXXLiteralOperatorName:
105 return LHS.getCXXLiteralIdentifier()->getName() <
106 RHS.getCXXLiteralIdentifier()->getName();
Douglas Gregord6b5f132009-11-04 22:24:30 +0000107
108 case DeclarationName::CXXUsingDirective:
109 return false;
110 }
111
112 return false;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000113}
114
115} // end namespace clang
116
117DeclarationName::DeclarationName(Selector Sel) {
Douglas Gregor319ac892009-04-23 22:29:11 +0000118 if (!Sel.getAsOpaquePtr()) {
Douglas Gregor813a97b2009-10-17 17:25:45 +0000119 Ptr = 0;
Douglas Gregor319ac892009-04-23 22:29:11 +0000120 return;
121 }
122
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000123 switch (Sel.getNumArgs()) {
124 case 0:
125 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000126 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000127 Ptr |= StoredObjCZeroArgSelector;
128 break;
129
130 case 1:
131 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000132 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000133 Ptr |= StoredObjCOneArgSelector;
134 break;
135
136 default:
137 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000138 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000139 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000140 break;
141 }
142}
143
144DeclarationName::NameKind DeclarationName::getNameKind() const {
145 switch (getStoredNameKind()) {
146 case StoredIdentifier: return Identifier;
147 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
148 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
149
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000150 case StoredDeclarationNameExtra:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000151 switch (getExtra()->ExtraKindOrNumArgs) {
Mike Stump1eb44332009-09-09 15:08:12 +0000152 case DeclarationNameExtra::CXXConstructor:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000153 return CXXConstructorName;
154
Mike Stump1eb44332009-09-09 15:08:12 +0000155 case DeclarationNameExtra::CXXDestructor:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000156 return CXXDestructorName;
157
Mike Stump1eb44332009-09-09 15:08:12 +0000158 case DeclarationNameExtra::CXXConversionFunction:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000159 return CXXConversionFunctionName;
160
Sean Hunt3e518bd2009-11-29 07:34:05 +0000161 case DeclarationNameExtra::CXXLiteralOperator:
162 return CXXLiteralOperatorName;
163
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000164 case DeclarationNameExtra::CXXUsingDirective:
165 return CXXUsingDirective;
166
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000167 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000168 // Check if we have one of the CXXOperator* enumeration values.
Mike Stump1eb44332009-09-09 15:08:12 +0000169 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000170 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000171 return CXXOperatorName;
172
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000173 return ObjCMultiArgSelector;
174 }
175 break;
176 }
177
178 // Can't actually get here.
Chris Lattnerac8d75f2009-03-21 06:40:50 +0000179 assert(0 && "This should be unreachable!");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000180 return Identifier;
181}
182
Douglas Gregor10bd3682008-11-17 22:58:34 +0000183std::string DeclarationName::getAsString() const {
184 switch (getNameKind()) {
185 case Identifier:
186 if (const IdentifierInfo *II = getAsIdentifierInfo())
187 return II->getName();
188 return "";
189
190 case ObjCZeroArgSelector:
191 case ObjCOneArgSelector:
192 case ObjCMultiArgSelector:
Chris Lattner077bf5e2008-11-24 03:33:13 +0000193 return getObjCSelector().getAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000194
195 case CXXConstructorName: {
196 QualType ClassType = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000197 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000198 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000199 return ClassType.getAsString();
200 }
201
202 case CXXDestructorName: {
203 std::string Result = "~";
204 QualType Type = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000205 if (const RecordType *Rec = Type->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000206 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000207 else
208 Result += Type.getAsString();
209 return Result;
210 }
211
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000212 case CXXOperatorName: {
213 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
214 0,
215#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
216 Spelling,
217#include "clang/Basic/OperatorKinds.def"
218 };
219 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
220 assert(OpName && "not an overloaded operator");
Mike Stump1eb44332009-09-09 15:08:12 +0000221
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000222 std::string Result = "operator";
223 if (OpName[0] >= 'a' && OpName[0] <= 'z')
224 Result += ' ';
225 Result += OpName;
226 return Result;
227 }
228
Sean Hunt3e518bd2009-11-29 07:34:05 +0000229 case CXXLiteralOperatorName: {
230 return "operator \"\" " + std::string(getCXXLiteralIdentifier()->getName());
231 }
232
Douglas Gregor10bd3682008-11-17 22:58:34 +0000233 case CXXConversionFunctionName: {
234 std::string Result = "operator ";
235 QualType Type = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000236 if (const RecordType *Rec = Type->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000237 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000238 else
239 Result += Type.getAsString();
240 return Result;
241 }
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000242 case CXXUsingDirective:
243 return "<using-directive>";
Douglas Gregor10bd3682008-11-17 22:58:34 +0000244 }
245
246 assert(false && "Unexpected declaration name kind");
247 return "";
248}
249
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000250QualType DeclarationName::getCXXNameType() const {
251 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
252 return CXXName->Type;
253 else
254 return QualType();
255}
256
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000257OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
258 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
Mike Stump1eb44332009-09-09 15:08:12 +0000259 unsigned value
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000260 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
261 return static_cast<OverloadedOperatorKind>(value);
262 } else {
263 return OO_None;
264 }
265}
266
Sean Hunt3e518bd2009-11-29 07:34:05 +0000267IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
268 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
269 return CXXLit->ID;
270 else
271 return 0;
272}
273
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000274Selector DeclarationName::getObjCSelector() const {
275 switch (getNameKind()) {
276 case ObjCZeroArgSelector:
277 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
278
279 case ObjCOneArgSelector:
280 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
281
282 case ObjCMultiArgSelector:
283 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
284
285 default:
286 break;
287 }
288
289 return Selector();
290}
291
Douglas Gregor2def4832008-11-17 20:34:05 +0000292void *DeclarationName::getFETokenInfoAsVoid() const {
293 switch (getNameKind()) {
294 case Identifier:
295 return getAsIdentifierInfo()->getFETokenInfo<void>();
296
297 case CXXConstructorName:
298 case CXXDestructorName:
299 case CXXConversionFunctionName:
300 return getAsCXXSpecialName()->FETokenInfo;
301
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000302 case CXXOperatorName:
303 return getAsCXXOperatorIdName()->FETokenInfo;
304
Sean Hunt3e518bd2009-11-29 07:34:05 +0000305 case CXXLiteralOperatorName:
306 return getCXXLiteralIdentifier()->getFETokenInfo<void>();
307
Douglas Gregor2def4832008-11-17 20:34:05 +0000308 default:
309 assert(false && "Declaration name has no FETokenInfo");
310 }
311 return 0;
312}
313
314void DeclarationName::setFETokenInfo(void *T) {
315 switch (getNameKind()) {
316 case Identifier:
317 getAsIdentifierInfo()->setFETokenInfo(T);
318 break;
319
320 case CXXConstructorName:
321 case CXXDestructorName:
322 case CXXConversionFunctionName:
323 getAsCXXSpecialName()->FETokenInfo = T;
324 break;
325
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000326 case CXXOperatorName:
327 getAsCXXOperatorIdName()->FETokenInfo = T;
328 break;
329
Sean Hunt3e518bd2009-11-29 07:34:05 +0000330 case CXXLiteralOperatorName:
331 getCXXLiteralIdentifier()->setFETokenInfo(T);
332 break;
333
Douglas Gregor2def4832008-11-17 20:34:05 +0000334 default:
335 assert(false && "Declaration name has no FETokenInfo");
336 }
337}
338
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000339DeclarationName DeclarationName::getUsingDirectiveName() {
340 // Single instance of DeclarationNameExtra for using-directive
341 static DeclarationNameExtra UDirExtra =
342 { DeclarationNameExtra::CXXUsingDirective };
343
344 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
345 Ptr |= StoredDeclarationNameExtra;
346
347 return DeclarationName(Ptr);
348}
349
Anders Carlsson70f5bc72009-11-15 22:30:43 +0000350void DeclarationName::dump() const {
351 fprintf(stderr, "%s\n", getAsString().c_str());
352}
353
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000354DeclarationNameTable::DeclarationNameTable() {
355 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000356
357 // Initialize the overloaded operator names.
358 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
359 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
Mike Stump1eb44332009-09-09 15:08:12 +0000360 CXXOperatorNames[Op].ExtraKindOrNumArgs
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000361 = Op + DeclarationNameExtra::CXXConversionFunction;
362 CXXOperatorNames[Op].FETokenInfo = 0;
363 }
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000364}
365
366DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000367 llvm::FoldingSet<CXXSpecialName> *set =
368 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000369 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000370
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000371 while (I != E) {
372 CXXSpecialName *n = &*I++;
373 delete n;
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000374 }
375
376 delete set;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000377 delete [] CXXOperatorNames;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000378}
379
Mike Stump1eb44332009-09-09 15:08:12 +0000380DeclarationName
381DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
Douglas Gregor50d62d12009-08-05 05:36:45 +0000382 CanQualType Ty) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000383 assert(Kind >= DeclarationName::CXXConstructorName &&
384 Kind <= DeclarationName::CXXConversionFunctionName &&
385 "Kind must be a C++ special name kind");
Mike Stump1eb44332009-09-09 15:08:12 +0000386 llvm::FoldingSet<CXXSpecialName> *SpecialNames
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000387 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
388
389 DeclarationNameExtra::ExtraKind EKind;
390 switch (Kind) {
Mike Stump1eb44332009-09-09 15:08:12 +0000391 case DeclarationName::CXXConstructorName:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000392 EKind = DeclarationNameExtra::CXXConstructor;
John McCall0953e762009-09-24 19:53:00 +0000393 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000394 break;
395 case DeclarationName::CXXDestructorName:
396 EKind = DeclarationNameExtra::CXXDestructor;
John McCall0953e762009-09-24 19:53:00 +0000397 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000398 break;
399 case DeclarationName::CXXConversionFunctionName:
400 EKind = DeclarationNameExtra::CXXConversionFunction;
401 break;
402 default:
403 return DeclarationName();
404 }
405
406 // Unique selector, to guarantee there is one per name.
407 llvm::FoldingSetNodeID ID;
408 ID.AddInteger(EKind);
409 ID.AddPointer(Ty.getAsOpaquePtr());
410
411 void *InsertPos = 0;
412 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
413 return DeclarationName(Name);
414
415 CXXSpecialName *SpecialName = new CXXSpecialName;
416 SpecialName->ExtraKindOrNumArgs = EKind;
417 SpecialName->Type = Ty;
Douglas Gregor2def4832008-11-17 20:34:05 +0000418 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000419
420 SpecialNames->InsertNode(SpecialName, InsertPos);
421 return DeclarationName(SpecialName);
422}
423
Mike Stump1eb44332009-09-09 15:08:12 +0000424DeclarationName
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000425DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
426 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
427}
428
Sean Hunt3e518bd2009-11-29 07:34:05 +0000429DeclarationName
430DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
431 CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
432 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
433 LiteralName->ID = II;
434 return DeclarationName(LiteralName);
435}
436
Mike Stump1eb44332009-09-09 15:08:12 +0000437unsigned
Douglas Gregor44b43212008-12-11 16:49:14 +0000438llvm::DenseMapInfo<clang::DeclarationName>::
439getHashValue(clang::DeclarationName N) {
440 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
441}
442