blob: e2ed8925951da647501fd72b5171dd7ace79406d [file] [log] [blame]
Douglas Gregor24afd4a2008-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 Gregor6704b312008-11-17 22:58:34 +000015#include "clang/AST/Type.h"
16#include "clang/AST/Decl.h"
Douglas Gregor24afd4a2008-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 Gregorb0212bd2008-11-17 20:34:05 +000030 /// Type - The type associated with this declaration name.
Douglas Gregor24afd4a2008-11-17 14:58:09 +000031 QualType Type;
32
Douglas Gregorb0212bd2008-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 Gregor24afd4a2008-11-17 14:58:09 +000037 void Profile(llvm::FoldingSetNodeID &ID) {
38 ID.AddInteger(ExtraKindOrNumArgs);
39 ID.AddPointer(Type.getAsOpaquePtr());
40 }
41};
42
Douglas Gregor96a32dd2008-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 Gregor24afd4a2008-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 Kremenekc5f6de02009-03-14 00:27:40 +000066 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor24afd4a2008-11-17 14:58:09 +000067 Ptr |= StoredObjCZeroArgSelector;
68 break;
69
70 case 1:
71 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
Ted Kremenekc5f6de02009-03-14 00:27:40 +000072 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
Douglas Gregor24afd4a2008-11-17 14:58:09 +000073 Ptr |= StoredObjCOneArgSelector;
74 break;
75
76 default:
77 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
Ted Kremenekc5f6de02009-03-14 00:27:40 +000078 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Douglas Gregor96a32dd2008-11-18 14:39:36 +000079 Ptr |= StoredDeclarationNameExtra;
Douglas Gregor24afd4a2008-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 Gregor96a32dd2008-11-18 14:39:36 +000090 case StoredDeclarationNameExtra:
Douglas Gregor24afd4a2008-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 Gregor7a7be652009-02-03 19:21:40 +0000101 case DeclarationNameExtra::CXXUsingDirective:
102 return CXXUsingDirective;
103
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000104 default:
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000105 // Check if we have one of the CXXOperator* enumeration values.
106 if (getExtra()->ExtraKindOrNumArgs <
Douglas Gregor7a7be652009-02-03 19:21:40 +0000107 DeclarationNameExtra::CXXUsingDirective)
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000108 return CXXOperatorName;
109
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000110 return ObjCMultiArgSelector;
111 }
112 break;
113 }
114
115 // Can't actually get here.
Chris Lattner86913d42009-03-21 06:40:50 +0000116 assert(0 && "This should be unreachable!");
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000117 return Identifier;
118}
119
Douglas Gregor6704b312008-11-17 22:58:34 +0000120std::string DeclarationName::getAsString() const {
121 switch (getNameKind()) {
122 case Identifier:
123 if (const IdentifierInfo *II = getAsIdentifierInfo())
124 return II->getName();
125 return "";
126
127 case ObjCZeroArgSelector:
128 case ObjCOneArgSelector:
129 case ObjCMultiArgSelector:
Chris Lattner3a8f2942008-11-24 03:33:13 +0000130 return getObjCSelector().getAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000131
132 case CXXConstructorName: {
133 QualType ClassType = getCXXNameType();
134 if (const RecordType *ClassRec = ClassType->getAsRecordType())
Chris Lattner6c5ec622008-11-24 04:00:27 +0000135 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000136 return ClassType.getAsString();
137 }
138
139 case CXXDestructorName: {
140 std::string Result = "~";
141 QualType Type = getCXXNameType();
142 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner6c5ec622008-11-24 04:00:27 +0000143 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000144 else
145 Result += Type.getAsString();
146 return Result;
147 }
148
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000149 case CXXOperatorName: {
150 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
151 0,
152#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
153 Spelling,
154#include "clang/Basic/OperatorKinds.def"
155 };
156 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
157 assert(OpName && "not an overloaded operator");
158
159 std::string Result = "operator";
160 if (OpName[0] >= 'a' && OpName[0] <= 'z')
161 Result += ' ';
162 Result += OpName;
163 return Result;
164 }
165
Douglas Gregor6704b312008-11-17 22:58:34 +0000166 case CXXConversionFunctionName: {
167 std::string Result = "operator ";
168 QualType Type = getCXXNameType();
169 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner6c5ec622008-11-24 04:00:27 +0000170 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor6704b312008-11-17 22:58:34 +0000171 else
172 Result += Type.getAsString();
173 return Result;
174 }
Douglas Gregor7a7be652009-02-03 19:21:40 +0000175 case CXXUsingDirective:
176 return "<using-directive>";
Douglas Gregor6704b312008-11-17 22:58:34 +0000177 }
178
179 assert(false && "Unexpected declaration name kind");
180 return "";
181}
182
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000183QualType DeclarationName::getCXXNameType() const {
184 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
185 return CXXName->Type;
186 else
187 return QualType();
188}
189
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000190OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
191 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
192 unsigned value
193 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
194 return static_cast<OverloadedOperatorKind>(value);
195 } else {
196 return OO_None;
197 }
198}
199
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000200Selector DeclarationName::getObjCSelector() const {
201 switch (getNameKind()) {
202 case ObjCZeroArgSelector:
203 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
204
205 case ObjCOneArgSelector:
206 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
207
208 case ObjCMultiArgSelector:
209 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
210
211 default:
212 break;
213 }
214
215 return Selector();
216}
217
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000218void *DeclarationName::getFETokenInfoAsVoid() const {
219 switch (getNameKind()) {
220 case Identifier:
221 return getAsIdentifierInfo()->getFETokenInfo<void>();
222
223 case CXXConstructorName:
224 case CXXDestructorName:
225 case CXXConversionFunctionName:
226 return getAsCXXSpecialName()->FETokenInfo;
227
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000228 case CXXOperatorName:
229 return getAsCXXOperatorIdName()->FETokenInfo;
230
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000231 default:
232 assert(false && "Declaration name has no FETokenInfo");
233 }
234 return 0;
235}
236
237void DeclarationName::setFETokenInfo(void *T) {
238 switch (getNameKind()) {
239 case Identifier:
240 getAsIdentifierInfo()->setFETokenInfo(T);
241 break;
242
243 case CXXConstructorName:
244 case CXXDestructorName:
245 case CXXConversionFunctionName:
246 getAsCXXSpecialName()->FETokenInfo = T;
247 break;
248
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000249 case CXXOperatorName:
250 getAsCXXOperatorIdName()->FETokenInfo = T;
251 break;
252
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000253 default:
254 assert(false && "Declaration name has no FETokenInfo");
255 }
256}
257
Douglas Gregor7a7be652009-02-03 19:21:40 +0000258DeclarationName DeclarationName::getUsingDirectiveName() {
259 // Single instance of DeclarationNameExtra for using-directive
260 static DeclarationNameExtra UDirExtra =
261 { DeclarationNameExtra::CXXUsingDirective };
262
263 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
264 Ptr |= StoredDeclarationNameExtra;
265
266 return DeclarationName(Ptr);
267}
268
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000269DeclarationNameTable::DeclarationNameTable() {
270 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000271
272 // Initialize the overloaded operator names.
273 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
274 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
275 CXXOperatorNames[Op].ExtraKindOrNumArgs
276 = Op + DeclarationNameExtra::CXXConversionFunction;
277 CXXOperatorNames[Op].FETokenInfo = 0;
278 }
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000279}
280
281DeclarationNameTable::~DeclarationNameTable() {
Nuno Lopes8f3bb2a2008-12-14 17:27:25 +0000282 llvm::FoldingSet<CXXSpecialName> *set =
283 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Nuno Lopes1640bf22008-12-14 21:53:25 +0000284 llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
Nuno Lopes8f3bb2a2008-12-14 17:27:25 +0000285
Nuno Lopes1640bf22008-12-14 21:53:25 +0000286 while (I != E) {
287 CXXSpecialName *n = &*I++;
288 delete n;
Nuno Lopes8f3bb2a2008-12-14 17:27:25 +0000289 }
290
291 delete set;
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000292 delete [] CXXOperatorNames;
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000293}
294
295DeclarationName
296DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
297 QualType Ty) {
298 assert(Kind >= DeclarationName::CXXConstructorName &&
299 Kind <= DeclarationName::CXXConversionFunctionName &&
300 "Kind must be a C++ special name kind");
301
302 llvm::FoldingSet<CXXSpecialName> *SpecialNames
303 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
304
305 DeclarationNameExtra::ExtraKind EKind;
306 switch (Kind) {
307 case DeclarationName::CXXConstructorName:
308 EKind = DeclarationNameExtra::CXXConstructor;
Chris Lattnerb6eccdc2009-02-16 22:33:34 +0000309 assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000310 break;
311 case DeclarationName::CXXDestructorName:
312 EKind = DeclarationNameExtra::CXXDestructor;
Douglas Gregor036b5a02009-01-13 00:11:19 +0000313 assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000314 break;
315 case DeclarationName::CXXConversionFunctionName:
316 EKind = DeclarationNameExtra::CXXConversionFunction;
317 break;
318 default:
319 return DeclarationName();
320 }
321
322 // Unique selector, to guarantee there is one per name.
323 llvm::FoldingSetNodeID ID;
324 ID.AddInteger(EKind);
325 ID.AddPointer(Ty.getAsOpaquePtr());
326
327 void *InsertPos = 0;
328 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
329 return DeclarationName(Name);
330
331 CXXSpecialName *SpecialName = new CXXSpecialName;
332 SpecialName->ExtraKindOrNumArgs = EKind;
333 SpecialName->Type = Ty;
Douglas Gregorb0212bd2008-11-17 20:34:05 +0000334 SpecialName->FETokenInfo = 0;
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000335
336 SpecialNames->InsertNode(SpecialName, InsertPos);
337 return DeclarationName(SpecialName);
338}
339
Douglas Gregor96a32dd2008-11-18 14:39:36 +0000340DeclarationName
341DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
342 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
343}
344
Douglas Gregor8acb7272008-12-11 16:49:14 +0000345unsigned
346llvm::DenseMapInfo<clang::DeclarationName>::
347getHashValue(clang::DeclarationName N) {
348 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
349}
350