blob: 8664c508615feba19c41bb331e4b01dd84adce91 [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"
Douglas Gregor2e1cd422008-11-17 14:58:09 +000021using namespace clang;
22
23namespace clang {
24/// CXXSpecialName - Records the type associated with one of the
25/// "special" kinds of declaration names in C++, e.g., constructors,
26/// destructors, and conversion functions.
Mike Stump1eb44332009-09-09 15:08:12 +000027class CXXSpecialName
Douglas Gregor2e1cd422008-11-17 14:58:09 +000028 : public DeclarationNameExtra, public llvm::FoldingSetNode {
29public:
Douglas Gregor2def4832008-11-17 20:34:05 +000030 /// Type - The type associated with this declaration name.
Douglas Gregor2e1cd422008-11-17 14:58:09 +000031 QualType Type;
32
Douglas Gregor2def4832008-11-17 20:34:05 +000033 /// FETokenInfo - Extra information associated with this declaration
34 /// name that can be used by the front end.
35 void *FETokenInfo;
36
Douglas Gregor2e1cd422008-11-17 14:58:09 +000037 void Profile(llvm::FoldingSetNodeID &ID) {
38 ID.AddInteger(ExtraKindOrNumArgs);
39 ID.AddPointer(Type.getAsOpaquePtr());
40 }
41};
42
Douglas Gregore94ca9e42008-11-18 14:39:36 +000043/// CXXOperatorIdName - Contains extra information for the name of an
Mike Stump1eb44332009-09-09 15:08:12 +000044/// overloaded operator in C++, such as "operator+.
Douglas Gregore94ca9e42008-11-18 14:39:36 +000045class CXXOperatorIdName : public DeclarationNameExtra {
46public:
47 /// FETokenInfo - Extra information associated with this operator
48 /// name that can be used by the front end.
49 void *FETokenInfo;
50};
51
Douglas Gregor2e1cd422008-11-17 14:58:09 +000052bool operator<(DeclarationName LHS, DeclarationName RHS) {
Douglas Gregord6b5f132009-11-04 22:24:30 +000053 if (LHS.getNameKind() != RHS.getNameKind())
54 return LHS.getNameKind() < RHS.getNameKind();
55
56 switch (LHS.getNameKind()) {
57 case DeclarationName::Identifier:
58 return LHS.getAsIdentifierInfo()->getName() <
59 RHS.getAsIdentifierInfo()->getName();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000060
Douglas Gregord6b5f132009-11-04 22:24:30 +000061 case DeclarationName::ObjCZeroArgSelector:
62 case DeclarationName::ObjCOneArgSelector:
63 case DeclarationName::ObjCMultiArgSelector: {
64 Selector LHSSelector = LHS.getObjCSelector();
65 Selector RHSSelector = RHS.getObjCSelector();
66 for (unsigned I = 0,
67 N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
68 I != N; ++I) {
69 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
70 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
71 if (!LHSId || !RHSId)
72 return LHSId && !RHSId;
73
74 switch (LHSId->getName().compare(RHSId->getName())) {
75 case -1: return true;
76 case 1: return false;
77 default: break;
78 }
79 }
80
81 return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
82 }
83
84 case DeclarationName::CXXConstructorName:
85 case DeclarationName::CXXDestructorName:
86 case DeclarationName::CXXConversionFunctionName:
87 return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
88
89 case DeclarationName::CXXOperatorName:
90 return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
91
92 case DeclarationName::CXXUsingDirective:
93 return false;
94 }
95
96 return false;
Douglas Gregor2e1cd422008-11-17 14:58:09 +000097}
98
99} // end namespace clang
100
101DeclarationName::DeclarationName(Selector Sel) {
Douglas Gregor319ac892009-04-23 22:29:11 +0000102 if (!Sel.getAsOpaquePtr()) {
Douglas Gregor813a97b2009-10-17 17:25:45 +0000103 Ptr = 0;
Douglas Gregor319ac892009-04-23 22:29:11 +0000104 return;
105 }
106
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000107 switch (Sel.getNumArgs()) {
108 case 0:
109 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000110 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000111 Ptr |= StoredObjCZeroArgSelector;
112 break;
113
114 case 1:
115 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000116 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000117 Ptr |= StoredObjCOneArgSelector;
118 break;
119
120 default:
121 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Ted Kremenek3eb8dd72009-03-14 00:27:40 +0000122 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000123 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000124 break;
125 }
126}
127
128DeclarationName::NameKind DeclarationName::getNameKind() const {
129 switch (getStoredNameKind()) {
130 case StoredIdentifier: return Identifier;
131 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
132 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
133
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000134 case StoredDeclarationNameExtra:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000135 switch (getExtra()->ExtraKindOrNumArgs) {
Mike Stump1eb44332009-09-09 15:08:12 +0000136 case DeclarationNameExtra::CXXConstructor:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000137 return CXXConstructorName;
138
Mike Stump1eb44332009-09-09 15:08:12 +0000139 case DeclarationNameExtra::CXXDestructor:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000140 return CXXDestructorName;
141
Mike Stump1eb44332009-09-09 15:08:12 +0000142 case DeclarationNameExtra::CXXConversionFunction:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000143 return CXXConversionFunctionName;
144
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000145 case DeclarationNameExtra::CXXUsingDirective:
146 return CXXUsingDirective;
147
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000148 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000149 // Check if we have one of the CXXOperator* enumeration values.
Mike Stump1eb44332009-09-09 15:08:12 +0000150 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000151 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000152 return CXXOperatorName;
153
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000154 return ObjCMultiArgSelector;
155 }
156 break;
157 }
158
159 // Can't actually get here.
Chris Lattnerac8d75f2009-03-21 06:40:50 +0000160 assert(0 && "This should be unreachable!");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000161 return Identifier;
162}
163
Douglas Gregor10bd3682008-11-17 22:58:34 +0000164std::string DeclarationName::getAsString() const {
165 switch (getNameKind()) {
166 case Identifier:
167 if (const IdentifierInfo *II = getAsIdentifierInfo())
168 return II->getName();
169 return "";
170
171 case ObjCZeroArgSelector:
172 case ObjCOneArgSelector:
173 case ObjCMultiArgSelector:
Chris Lattner077bf5e2008-11-24 03:33:13 +0000174 return getObjCSelector().getAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000175
176 case CXXConstructorName: {
177 QualType ClassType = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000178 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000179 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000180 return ClassType.getAsString();
181 }
182
183 case CXXDestructorName: {
184 std::string Result = "~";
185 QualType Type = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000186 if (const RecordType *Rec = Type->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000187 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000188 else
189 Result += Type.getAsString();
190 return Result;
191 }
192
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000193 case CXXOperatorName: {
194 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
195 0,
196#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
197 Spelling,
198#include "clang/Basic/OperatorKinds.def"
199 };
200 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
201 assert(OpName && "not an overloaded operator");
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000203 std::string Result = "operator";
204 if (OpName[0] >= 'a' && OpName[0] <= 'z')
205 Result += ' ';
206 Result += OpName;
207 return Result;
208 }
209
Douglas Gregor10bd3682008-11-17 22:58:34 +0000210 case CXXConversionFunctionName: {
211 std::string Result = "operator ";
212 QualType Type = getCXXNameType();
Ted Kremenek6217b802009-07-29 21:53:49 +0000213 if (const RecordType *Rec = Type->getAs<RecordType>())
Chris Lattner39f34e92008-11-24 04:00:27 +0000214 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000215 else
216 Result += Type.getAsString();
217 return Result;
218 }
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000219 case CXXUsingDirective:
220 return "<using-directive>";
Douglas Gregor10bd3682008-11-17 22:58:34 +0000221 }
222
223 assert(false && "Unexpected declaration name kind");
224 return "";
225}
226
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000227QualType DeclarationName::getCXXNameType() const {
228 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
229 return CXXName->Type;
230 else
231 return QualType();
232}
233
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000234OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
235 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
Mike Stump1eb44332009-09-09 15:08:12 +0000236 unsigned value
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000237 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
238 return static_cast<OverloadedOperatorKind>(value);
239 } else {
240 return OO_None;
241 }
242}
243
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000244Selector DeclarationName::getObjCSelector() const {
245 switch (getNameKind()) {
246 case ObjCZeroArgSelector:
247 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
248
249 case ObjCOneArgSelector:
250 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
251
252 case ObjCMultiArgSelector:
253 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
254
255 default:
256 break;
257 }
258
259 return Selector();
260}
261
Douglas Gregor2def4832008-11-17 20:34:05 +0000262void *DeclarationName::getFETokenInfoAsVoid() const {
263 switch (getNameKind()) {
264 case Identifier:
265 return getAsIdentifierInfo()->getFETokenInfo<void>();
266
267 case CXXConstructorName:
268 case CXXDestructorName:
269 case CXXConversionFunctionName:
270 return getAsCXXSpecialName()->FETokenInfo;
271
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000272 case CXXOperatorName:
273 return getAsCXXOperatorIdName()->FETokenInfo;
274
Douglas Gregor2def4832008-11-17 20:34:05 +0000275 default:
276 assert(false && "Declaration name has no FETokenInfo");
277 }
278 return 0;
279}
280
281void DeclarationName::setFETokenInfo(void *T) {
282 switch (getNameKind()) {
283 case Identifier:
284 getAsIdentifierInfo()->setFETokenInfo(T);
285 break;
286
287 case CXXConstructorName:
288 case CXXDestructorName:
289 case CXXConversionFunctionName:
290 getAsCXXSpecialName()->FETokenInfo = T;
291 break;
292
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000293 case CXXOperatorName:
294 getAsCXXOperatorIdName()->FETokenInfo = T;
295 break;
296
Douglas Gregor2def4832008-11-17 20:34:05 +0000297 default:
298 assert(false && "Declaration name has no FETokenInfo");
299 }
300}
301
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000302DeclarationName DeclarationName::getUsingDirectiveName() {
303 // Single instance of DeclarationNameExtra for using-directive
304 static DeclarationNameExtra UDirExtra =
305 { DeclarationNameExtra::CXXUsingDirective };
306
307 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
308 Ptr |= StoredDeclarationNameExtra;
309
310 return DeclarationName(Ptr);
311}
312
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000313DeclarationNameTable::DeclarationNameTable() {
314 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000315
316 // Initialize the overloaded operator names.
317 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
318 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
Mike Stump1eb44332009-09-09 15:08:12 +0000319 CXXOperatorNames[Op].ExtraKindOrNumArgs
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000320 = Op + DeclarationNameExtra::CXXConversionFunction;
321 CXXOperatorNames[Op].FETokenInfo = 0;
322 }
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000323}
324
325DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000326 llvm::FoldingSet<CXXSpecialName> *set =
327 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000328 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000329
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000330 while (I != E) {
331 CXXSpecialName *n = &*I++;
332 delete n;
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000333 }
334
335 delete set;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000336 delete [] CXXOperatorNames;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000337}
338
Mike Stump1eb44332009-09-09 15:08:12 +0000339DeclarationName
340DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
Douglas Gregor50d62d12009-08-05 05:36:45 +0000341 CanQualType Ty) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000342 assert(Kind >= DeclarationName::CXXConstructorName &&
343 Kind <= DeclarationName::CXXConversionFunctionName &&
344 "Kind must be a C++ special name kind");
Mike Stump1eb44332009-09-09 15:08:12 +0000345 llvm::FoldingSet<CXXSpecialName> *SpecialNames
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000346 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
347
348 DeclarationNameExtra::ExtraKind EKind;
349 switch (Kind) {
Mike Stump1eb44332009-09-09 15:08:12 +0000350 case DeclarationName::CXXConstructorName:
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000351 EKind = DeclarationNameExtra::CXXConstructor;
John McCall0953e762009-09-24 19:53:00 +0000352 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000353 break;
354 case DeclarationName::CXXDestructorName:
355 EKind = DeclarationNameExtra::CXXDestructor;
John McCall0953e762009-09-24 19:53:00 +0000356 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000357 break;
358 case DeclarationName::CXXConversionFunctionName:
359 EKind = DeclarationNameExtra::CXXConversionFunction;
360 break;
361 default:
362 return DeclarationName();
363 }
364
365 // Unique selector, to guarantee there is one per name.
366 llvm::FoldingSetNodeID ID;
367 ID.AddInteger(EKind);
368 ID.AddPointer(Ty.getAsOpaquePtr());
369
370 void *InsertPos = 0;
371 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
372 return DeclarationName(Name);
373
374 CXXSpecialName *SpecialName = new CXXSpecialName;
375 SpecialName->ExtraKindOrNumArgs = EKind;
376 SpecialName->Type = Ty;
Douglas Gregor2def4832008-11-17 20:34:05 +0000377 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000378
379 SpecialNames->InsertNode(SpecialName, InsertPos);
380 return DeclarationName(SpecialName);
381}
382
Mike Stump1eb44332009-09-09 15:08:12 +0000383DeclarationName
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000384DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
385 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
386}
387
Mike Stump1eb44332009-09-09 15:08:12 +0000388unsigned
Douglas Gregor44b43212008-12-11 16:49:14 +0000389llvm::DenseMapInfo<clang::DeclarationName>::
390getHashValue(clang::DeclarationName N) {
391 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
392}
393