blob: 1ff068c9862c12a60e3acfc0ed1485f5c50c72a3 [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
Douglas Gregor2e1cd422008-11-17 14:58:09 +000053bool operator<(DeclarationName LHS, DeclarationName RHS) {
Douglas Gregord6b5f132009-11-04 22:24:30 +000054 if (LHS.getNameKind() != RHS.getNameKind())
55 return LHS.getNameKind() < RHS.getNameKind();
56
57 switch (LHS.getNameKind()) {
58 case DeclarationName::Identifier:
59 return LHS.getAsIdentifierInfo()->getName() <
60 RHS.getAsIdentifierInfo()->getName();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000061
Douglas Gregord6b5f132009-11-04 22:24:30 +000062 case DeclarationName::ObjCZeroArgSelector:
63 case DeclarationName::ObjCOneArgSelector:
64 case DeclarationName::ObjCMultiArgSelector: {
65 Selector LHSSelector = LHS.getObjCSelector();
66 Selector RHSSelector = RHS.getObjCSelector();
67 for (unsigned I = 0,
68 N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
69 I != N; ++I) {
70 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
71 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
72 if (!LHSId || !RHSId)
73 return LHSId && !RHSId;
74
75 switch (LHSId->getName().compare(RHSId->getName())) {
76 case -1: return true;
77 case 1: return false;
78 default: break;
79 }
80 }
81
82 return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
83 }
84
85 case DeclarationName::CXXConstructorName:
86 case DeclarationName::CXXDestructorName:
87 case DeclarationName::CXXConversionFunctionName:
88 return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
89
90 case DeclarationName::CXXOperatorName:
91 return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
92
93 case DeclarationName::CXXUsingDirective:
94 return false;
95 }
96
97 return false;
Douglas Gregor2e1cd422008-11-17 14:58:09 +000098}
99
100} // end namespace clang
101
102DeclarationName::DeclarationName(Selector Sel) {
Douglas Gregor319ac892009-04-23 22:29:11 +0000103 if (!Sel.getAsOpaquePtr()) {
Douglas Gregor813a97b2009-10-17 17:25:45 +0000104 Ptr = 0;
Douglas Gregor319ac892009-04-23 22:29:11 +0000105 return;
106 }
107
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000108 switch (Sel.getNumArgs()) {
109 case 0:
110 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000111 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000112 Ptr |= StoredObjCZeroArgSelector;
113 break;
114
115 case 1:
116 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000117 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000118 Ptr |= StoredObjCOneArgSelector;
119 break;
120
121 default:
122 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000123 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000124 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000125 break;
126 }
127}
128
129DeclarationName::NameKind DeclarationName::getNameKind() const {
130 switch (getStoredNameKind()) {
131 case StoredIdentifier: return Identifier;
132 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
133 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
134
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000135 case StoredDeclarationNameExtra:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000136 switch (getExtra()->ExtraKindOrNumArgs) {
Mike Stump1eb44332009-09-09 15:08:12 +0000137 case DeclarationNameExtra::CXXConstructor:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000138 return CXXConstructorName;
139
Mike Stump1eb44332009-09-09 15:08:12 +0000140 case DeclarationNameExtra::CXXDestructor:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000141 return CXXDestructorName;
142
Mike Stump1eb44332009-09-09 15:08:12 +0000143 case DeclarationNameExtra::CXXConversionFunction:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000144 return CXXConversionFunctionName;
145
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000146 case DeclarationNameExtra::CXXUsingDirective:
147 return CXXUsingDirective;
148
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000149 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000150 // Check if we have one of the CXXOperator* enumeration values.
Mike Stump1eb44332009-09-09 15:08:12 +0000151 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000152 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000153 return CXXOperatorName;
154
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000155 return ObjCMultiArgSelector;
156 }
157 break;
158 }
159
160 // Can't actually get here.
Chris Lattnerac8d75f2009-03-21 06:40:50 +0000161 assert(0 && "This should be unreachable!");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000162 return Identifier;
163}
164
Douglas Gregor10bd3682008-11-17 22:58:34 +0000165std::string DeclarationName::getAsString() const {
166 switch (getNameKind()) {
167 case Identifier:
168 if (const IdentifierInfo *II = getAsIdentifierInfo())
169 return II->getName();
170 return "";
171
172 case ObjCZeroArgSelector:
173 case ObjCOneArgSelector:
174 case ObjCMultiArgSelector:
Chris Lattner077bf5e2008-11-24 03:33:13 +0000175 return getObjCSelector().getAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000176
177 case CXXConstructorName: {
178 QualType ClassType = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000179 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000180 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000181 return ClassType.getAsString();
182 }
183
184 case CXXDestructorName: {
185 std::string Result = "~";
186 QualType Type = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000187 if (const RecordType *Rec = Type->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000188 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000189 else
190 Result += Type.getAsString();
191 return Result;
192 }
193
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000194 case CXXOperatorName: {
195 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
196 0,
197#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
198 Spelling,
199#include "clang/Basic/OperatorKinds.def"
200 };
201 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
202 assert(OpName && "not an overloaded operator");
Mike Stump1eb44332009-09-09 15:08:12 +0000203
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000204 std::string Result = "operator";
205 if (OpName[0] >= 'a' && OpName[0] <= 'z')
206 Result += ' ';
207 Result += OpName;
208 return Result;
209 }
210
Douglas Gregor10bd3682008-11-17 22:58:34 +0000211 case CXXConversionFunctionName: {
212 std::string Result = "operator ";
213 QualType Type = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000214 if (const RecordType *Rec = Type->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000215 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000216 else
217 Result += Type.getAsString();
218 return Result;
219 }
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000220 case CXXUsingDirective:
221 return "<using-directive>";
Douglas Gregor10bd3682008-11-17 22:58:34 +0000222 }
223
224 assert(false && "Unexpected declaration name kind");
225 return "";
226}
227
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000228QualType DeclarationName::getCXXNameType() const {
229 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
230 return CXXName->Type;
231 else
232 return QualType();
233}
234
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000235OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
236 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
Mike Stump1eb44332009-09-09 15:08:12 +0000237 unsigned value
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000238 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
239 return static_cast<OverloadedOperatorKind>(value);
240 } else {
241 return OO_None;
242 }
243}
244
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000245Selector DeclarationName::getObjCSelector() const {
246 switch (getNameKind()) {
247 case ObjCZeroArgSelector:
248 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
249
250 case ObjCOneArgSelector:
251 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
252
253 case ObjCMultiArgSelector:
254 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
255
256 default:
257 break;
258 }
259
260 return Selector();
261}
262
Douglas Gregor2def4832008-11-17 20:34:05 +0000263void *DeclarationName::getFETokenInfoAsVoid() const {
264 switch (getNameKind()) {
265 case Identifier:
266 return getAsIdentifierInfo()->getFETokenInfo<void>();
267
268 case CXXConstructorName:
269 case CXXDestructorName:
270 case CXXConversionFunctionName:
271 return getAsCXXSpecialName()->FETokenInfo;
272
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000273 case CXXOperatorName:
274 return getAsCXXOperatorIdName()->FETokenInfo;
275
Douglas Gregor2def4832008-11-17 20:34:05 +0000276 default:
277 assert(false && "Declaration name has no FETokenInfo");
278 }
279 return 0;
280}
281
282void DeclarationName::setFETokenInfo(void *T) {
283 switch (getNameKind()) {
284 case Identifier:
285 getAsIdentifierInfo()->setFETokenInfo(T);
286 break;
287
288 case CXXConstructorName:
289 case CXXDestructorName:
290 case CXXConversionFunctionName:
291 getAsCXXSpecialName()->FETokenInfo = T;
292 break;
293
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000294 case CXXOperatorName:
295 getAsCXXOperatorIdName()->FETokenInfo = T;
296 break;
297
Douglas Gregor2def4832008-11-17 20:34:05 +0000298 default:
299 assert(false && "Declaration name has no FETokenInfo");
300 }
301}
302
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000303DeclarationName DeclarationName::getUsingDirectiveName() {
304 // Single instance of DeclarationNameExtra for using-directive
305 static DeclarationNameExtra UDirExtra =
306 { DeclarationNameExtra::CXXUsingDirective };
307
308 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
309 Ptr |= StoredDeclarationNameExtra;
310
311 return DeclarationName(Ptr);
312}
313
Anders Carlsson70f5bc72009-11-15 22:30:43 +0000314void DeclarationName::dump() const {
315 fprintf(stderr, "%s\n", getAsString().c_str());
316}
317
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000318DeclarationNameTable::DeclarationNameTable() {
319 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000320
321 // Initialize the overloaded operator names.
322 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
323 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
Mike Stump1eb44332009-09-09 15:08:12 +0000324 CXXOperatorNames[Op].ExtraKindOrNumArgs
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000325 = Op + DeclarationNameExtra::CXXConversionFunction;
326 CXXOperatorNames[Op].FETokenInfo = 0;
327 }
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000328}
329
330DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000331 llvm::FoldingSet<CXXSpecialName> *set =
332 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000333 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000334
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000335 while (I != E) {
336 CXXSpecialName *n = &*I++;
337 delete n;
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000338 }
339
340 delete set;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000341 delete [] CXXOperatorNames;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000342}
343
Mike Stump1eb44332009-09-09 15:08:12 +0000344DeclarationName
345DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
Douglas Gregor50d62d12009-08-05 05:36:45 +0000346 CanQualType Ty) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000347 assert(Kind >= DeclarationName::CXXConstructorName &&
348 Kind <= DeclarationName::CXXConversionFunctionName &&
349 "Kind must be a C++ special name kind");
Mike Stump1eb44332009-09-09 15:08:12 +0000350 llvm::FoldingSet<CXXSpecialName> *SpecialNames
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000351 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
352
353 DeclarationNameExtra::ExtraKind EKind;
354 switch (Kind) {
Mike Stump1eb44332009-09-09 15:08:12 +0000355 case DeclarationName::CXXConstructorName:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000356 EKind = DeclarationNameExtra::CXXConstructor;
John McCall0953e762009-09-24 19:53:00 +0000357 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000358 break;
359 case DeclarationName::CXXDestructorName:
360 EKind = DeclarationNameExtra::CXXDestructor;
John McCall0953e762009-09-24 19:53:00 +0000361 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000362 break;
363 case DeclarationName::CXXConversionFunctionName:
364 EKind = DeclarationNameExtra::CXXConversionFunction;
365 break;
366 default:
367 return DeclarationName();
368 }
369
370 // Unique selector, to guarantee there is one per name.
371 llvm::FoldingSetNodeID ID;
372 ID.AddInteger(EKind);
373 ID.AddPointer(Ty.getAsOpaquePtr());
374
375 void *InsertPos = 0;
376 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
377 return DeclarationName(Name);
378
379 CXXSpecialName *SpecialName = new CXXSpecialName;
380 SpecialName->ExtraKindOrNumArgs = EKind;
381 SpecialName->Type = Ty;
Douglas Gregor2def4832008-11-17 20:34:05 +0000382 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000383
384 SpecialNames->InsertNode(SpecialName, InsertPos);
385 return DeclarationName(SpecialName);
386}
387
Mike Stump1eb44332009-09-09 15:08:12 +0000388DeclarationName
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000389DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
390 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
391}
392
Mike Stump1eb44332009-09-09 15:08:12 +0000393unsigned
Douglas Gregor44b43212008-12-11 16:49:14 +0000394llvm::DenseMapInfo<clang::DeclarationName>::
395getHashValue(clang::DeclarationName N) {
396 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
397}
398