blob: 3815a08a6522084f8323026dc390ece553c0bad2 [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());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +000066 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +000067 Ptr |= StoredObjCZeroArgSelector;
68 break;
69
70 case 1:
71 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenek3eb8dd72009-03-14 00:27:40 +000072 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor2e1cd422008-11-17 14:58:09 +000073 Ptr |= StoredObjCOneArgSelector;
74 break;
75
76 default:
77 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Ted Kremenek3eb8dd72009-03-14 00:27:40 +000078 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Douglas Gregore94ca9e42008-11-18 14:39:36 +000079 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor2e1cd422008-11-17 14:58:09 +000080 break;
81 }
82}
83
84DeclarationName::NameKind DeclarationName::getNameKind() const {
85 switch (getStoredNameKind()) {
86 case StoredIdentifier: return Identifier;
87 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
88 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
89
Douglas Gregore94ca9e42008-11-18 14:39:36 +000090 case StoredDeclarationNameExtra:
Douglas Gregor2e1cd422008-11-17 14:58:09 +000091 switch (getExtra()->ExtraKindOrNumArgs) {
92 case DeclarationNameExtra::CXXConstructor:
93 return CXXConstructorName;
94
95 case DeclarationNameExtra::CXXDestructor:
96 return CXXDestructorName;
97
98 case DeclarationNameExtra::CXXConversionFunction:
99 return CXXConversionFunctionName;
100
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000101 case DeclarationNameExtra::CXXUsingDirective:
102 return CXXUsingDirective;
103
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000104 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000105 // Check if we have one of the CXXOperator* enumeration values.
106 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000107 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000108 return CXXOperatorName;
109
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000110 return ObjCMultiArgSelector;
111 }
112 break;
113 }
114
115 // Can't actually get here.
116 return Identifier;
117}
118
Douglas Gregor10bd3682008-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 Lattner077bf5e2008-11-24 03:33:13 +0000129 return getObjCSelector().getAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000130
131 case CXXConstructorName: {
132 QualType ClassType = getCXXNameType();
133 if (const RecordType *ClassRec = ClassType->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000134 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-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 Lattner39f34e92008-11-24 04:00:27 +0000142 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000143 else
144 Result += Type.getAsString();
145 return Result;
146 }
147
Douglas Gregore94ca9e42008-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 Gregor10bd3682008-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 Lattner39f34e92008-11-24 04:00:27 +0000169 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000170 else
171 Result += Type.getAsString();
172 return Result;
173 }
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000174 case CXXUsingDirective:
175 return "<using-directive>";
Douglas Gregor10bd3682008-11-17 22:58:34 +0000176 }
177
178 assert(false && "Unexpected declaration name kind");
179 return "";
180}
181
Douglas Gregor2e1cd422008-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 Gregore94ca9e42008-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 Gregor2e1cd422008-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 Gregor2def4832008-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 Gregore94ca9e42008-11-18 14:39:36 +0000227 case CXXOperatorName:
228 return getAsCXXOperatorIdName()->FETokenInfo;
229
Douglas Gregor2def4832008-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 Gregore94ca9e42008-11-18 14:39:36 +0000248 case CXXOperatorName:
249 getAsCXXOperatorIdName()->FETokenInfo = T;
250 break;
251
Douglas Gregor2def4832008-11-17 20:34:05 +0000252 default:
253 assert(false && "Declaration name has no FETokenInfo");
254 }
255}
256
Douglas Gregor2a3009a2009-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 Gregor2e1cd422008-11-17 14:58:09 +0000268DeclarationNameTable::DeclarationNameTable() {
269 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregore94ca9e42008-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 Gregor2e1cd422008-11-17 14:58:09 +0000278}
279
280DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000281 llvm::FoldingSet<CXXSpecialName> *set =
282 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000283 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000284
Nuno Lopesf9d1e4b2008-12-14 21:53:25 +0000285 while (I != E) {
286 CXXSpecialName *n = &*I++;
287 delete n;
Nuno Lopes6d34ae52008-12-14 17:27:25 +0000288 }
289
290 delete set;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000291 delete [] CXXOperatorNames;
Douglas Gregor2e1cd422008-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 Lattnerd603eaa2009-02-16 22:33:34 +0000308 assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000309 break;
310 case DeclarationName::CXXDestructorName:
311 EKind = DeclarationNameExtra::CXXDestructor;
Douglas Gregore63ef482009-01-13 00:11:19 +0000312 assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
Douglas Gregor2e1cd422008-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 Gregor2def4832008-11-17 20:34:05 +0000333 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000334
335 SpecialNames->InsertNode(SpecialName, InsertPos);
336 return DeclarationName(SpecialName);
337}
338
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000339DeclarationName
340DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
341 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
342}
343
Douglas Gregor44b43212008-12-11 16:49:14 +0000344unsigned
345llvm::DenseMapInfo<clang::DeclarationName>::
346getHashValue(clang::DeclarationName N) {
347 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
348}
349