blob: c1077c189b675f56a7b1fe9a42fc709d0efb864b [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"
16#include "clang/AST/Decl.h"
Douglas Gregor2e1cd422008-11-17 14:58:09 +000017#include "clang/Basic/IdentifierTable.h"
18#include "llvm/ADT/FoldingSet.h"
19#include "llvm/Bitcode/Serialize.h"
20#include "llvm/Bitcode/Deserialize.h"
21using 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.
27class CXXSpecialName
28 : 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
44/// overloaded operator in C++, such as "operator+.
45class 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) {
53 if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
54 if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
55 return strcmp(LhsId->getName(), RhsId->getName()) < 0;
56
57 return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
58}
59
60} // end namespace clang
61
62DeclarationName::DeclarationName(Selector Sel) {
63 switch (Sel.getNumArgs()) {
64 case 0:
65 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
66 Ptr |= StoredObjCZeroArgSelector;
67 break;
68
69 case 1:
70 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
71 Ptr |= StoredObjCOneArgSelector;
72 break;
73
74 default:
75 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Douglas Gregore94ca9e42008-11-18 14:39:36 +000076 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor2e1cd422008-11-17 14:58:09 +000077 break;
78 }
79}
80
81DeclarationName::NameKind DeclarationName::getNameKind() const {
82 switch (getStoredNameKind()) {
83 case StoredIdentifier: return Identifier;
84 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
85 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
86
Douglas Gregore94ca9e42008-11-18 14:39:36 +000087 case StoredDeclarationNameExtra:
Douglas Gregor2e1cd422008-11-17 14:58:09 +000088 switch (getExtra()->ExtraKindOrNumArgs) {
89 case DeclarationNameExtra::CXXConstructor:
90 return CXXConstructorName;
91
92 case DeclarationNameExtra::CXXDestructor:
93 return CXXDestructorName;
94
95 case DeclarationNameExtra::CXXConversionFunction:
96 return CXXConversionFunctionName;
97
Douglas Gregor2a3009a2009-02-03 19:21:40 +000098 case DeclarationNameExtra::CXXUsingDirective:
99 return CXXUsingDirective;
100
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000101 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000102 // Check if we have one of the CXXOperator* enumeration values.
103 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000104 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000105 return CXXOperatorName;
106
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000107 return ObjCMultiArgSelector;
108 }
109 break;
110 }
111
112 // Can't actually get here.
113 return Identifier;
114}
115
Douglas Gregor10bd3682008-11-17 22:58:34 +0000116std::string DeclarationName::getAsString() const {
117 switch (getNameKind()) {
118 case Identifier:
119 if (const IdentifierInfo *II = getAsIdentifierInfo())
120 return II->getName();
121 return "";
122
123 case ObjCZeroArgSelector:
124 case ObjCOneArgSelector:
125 case ObjCMultiArgSelector:
Chris Lattner077bf5e2008-11-24 03:33:13 +0000126 return getObjCSelector().getAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000127
128 case CXXConstructorName: {
129 QualType ClassType = getCXXNameType();
130 if (const RecordType *ClassRec = ClassType->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000131 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000132 return ClassType.getAsString();
133 }
134
135 case CXXDestructorName: {
136 std::string Result = "~";
137 QualType Type = getCXXNameType();
138 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000139 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000140 else
141 Result += Type.getAsString();
142 return Result;
143 }
144
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000145 case CXXOperatorName: {
146 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
147 0,
148#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
149 Spelling,
150#include "clang/Basic/OperatorKinds.def"
151 };
152 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
153 assert(OpName && "not an overloaded operator");
154
155 std::string Result = "operator";
156 if (OpName[0] >= 'a' && OpName[0] <= 'z')
157 Result += ' ';
158 Result += OpName;
159 return Result;
160 }
161
Douglas Gregor10bd3682008-11-17 22:58:34 +0000162 case CXXConversionFunctionName: {
163 std::string Result = "operator ";
164 QualType Type = getCXXNameType();
165 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000166 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000167 else
168 Result += Type.getAsString();
169 return Result;
170 }
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000171 case CXXUsingDirective:
172 return "<using-directive>";
Douglas Gregor10bd3682008-11-17 22:58:34 +0000173 }
174
175 assert(false && "Unexpected declaration name kind");
176 return "";
177}
178
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000179QualType DeclarationName::getCXXNameType() const {
180 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
181 return CXXName->Type;
182 else
183 return QualType();
184}
185
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000186OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
187 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
188 unsigned value
189 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
190 return static_cast<OverloadedOperatorKind>(value);
191 } else {
192 return OO_None;
193 }
194}
195
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000196Selector DeclarationName::getObjCSelector() const {
197 switch (getNameKind()) {
198 case ObjCZeroArgSelector:
199 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
200
201 case ObjCOneArgSelector:
202 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
203
204 case ObjCMultiArgSelector:
205 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
206
207 default:
208 break;
209 }
210
211 return Selector();
212}
213
Douglas Gregor2def4832008-11-17 20:34:05 +0000214void *DeclarationName::getFETokenInfoAsVoid() const {
215 switch (getNameKind()) {
216 case Identifier:
217 return getAsIdentifierInfo()->getFETokenInfo<void>();
218
219 case CXXConstructorName:
220 case CXXDestructorName:
221 case CXXConversionFunctionName:
222 return getAsCXXSpecialName()->FETokenInfo;
223
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000224 case CXXOperatorName:
225 return getAsCXXOperatorIdName()->FETokenInfo;
226
Douglas Gregor2def4832008-11-17 20:34:05 +0000227 default:
228 assert(false && "Declaration name has no FETokenInfo");
229 }
230 return 0;
231}
232
233void DeclarationName::setFETokenInfo(void *T) {
234 switch (getNameKind()) {
235 case Identifier:
236 getAsIdentifierInfo()->setFETokenInfo(T);
237 break;
238
239 case CXXConstructorName:
240 case CXXDestructorName:
241 case CXXConversionFunctionName:
242 getAsCXXSpecialName()->FETokenInfo = T;
243 break;
244
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000245 case CXXOperatorName:
246 getAsCXXOperatorIdName()->FETokenInfo = T;
247 break;
248
Douglas Gregor2def4832008-11-17 20:34:05 +0000249 default:
250 assert(false && "Declaration name has no FETokenInfo");
251 }
252}
253
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000254DeclarationName DeclarationName::getUsingDirectiveName() {
255 // Single instance of DeclarationNameExtra for using-directive
256 static DeclarationNameExtra UDirExtra =
257 { DeclarationNameExtra::CXXUsingDirective };
258
259 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
260 Ptr |= StoredDeclarationNameExtra;
261
262 return DeclarationName(Ptr);
263}
264
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000265DeclarationNameTable::DeclarationNameTable() {
266 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000267
268 // Initialize the overloaded operator names.
269 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
270 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
271 CXXOperatorNames[Op].ExtraKindOrNumArgs
272 = Op + DeclarationNameExtra::CXXConversionFunction;
273 CXXOperatorNames[Op].FETokenInfo = 0;
274 }
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000275}
276
277DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000278 llvm::FoldingSet<CXXSpecialName> *set =
279 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000280 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000281
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000282 while (I != E) {
283 CXXSpecialName *n = &*I++;
284 delete n;
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000285 }
286
287 delete set;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000288 delete [] CXXOperatorNames;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000289}
290
291DeclarationName
292DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
293 QualType Ty) {
294 assert(Kind >= DeclarationName::CXXConstructorName &&
295 Kind <= DeclarationName::CXXConversionFunctionName &&
296 "Kind must be a C++ special name kind");
297
298 llvm::FoldingSet<CXXSpecialName> *SpecialNames
299 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
300
301 DeclarationNameExtra::ExtraKind EKind;
302 switch (Kind) {
303 case DeclarationName::CXXConstructorName:
304 EKind = DeclarationNameExtra::CXXConstructor;
Chris Lattnerd603eaa2009-02-16 22:33:34 +0000305 assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000306 break;
307 case DeclarationName::CXXDestructorName:
308 EKind = DeclarationNameExtra::CXXDestructor;
Douglas Gregore63ef482009-01-13 00:11:19 +0000309 assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000310 break;
311 case DeclarationName::CXXConversionFunctionName:
312 EKind = DeclarationNameExtra::CXXConversionFunction;
313 break;
314 default:
315 return DeclarationName();
316 }
317
318 // Unique selector, to guarantee there is one per name.
319 llvm::FoldingSetNodeID ID;
320 ID.AddInteger(EKind);
321 ID.AddPointer(Ty.getAsOpaquePtr());
322
323 void *InsertPos = 0;
324 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
325 return DeclarationName(Name);
326
327 CXXSpecialName *SpecialName = new CXXSpecialName;
328 SpecialName->ExtraKindOrNumArgs = EKind;
329 SpecialName->Type = Ty;
Douglas Gregor2def4832008-11-17 20:34:05 +0000330 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000331
332 SpecialNames->InsertNode(SpecialName, InsertPos);
333 return DeclarationName(SpecialName);
334}
335
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000336DeclarationName
337DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
338 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
339}
340
Douglas Gregor44b43212008-12-11 16:49:14 +0000341unsigned
342llvm::DenseMapInfo<clang::DeclarationName>::
343getHashValue(clang::DeclarationName N) {
344 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
345}
346