blob: af983feed1e8ce4d009b8ea60e9266c0da7b1659 [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
98 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +000099 // Check if we have one of the CXXOperator* enumeration values.
100 if (getExtra()->ExtraKindOrNumArgs <
101 DeclarationNameExtra::NUM_EXTRA_KINDS)
102 return CXXOperatorName;
103
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000104 return ObjCMultiArgSelector;
105 }
106 break;
107 }
108
109 // Can't actually get here.
110 return Identifier;
111}
112
Douglas Gregor10bd3682008-11-17 22:58:34 +0000113std::string DeclarationName::getAsString() const {
114 switch (getNameKind()) {
115 case Identifier:
116 if (const IdentifierInfo *II = getAsIdentifierInfo())
117 return II->getName();
118 return "";
119
120 case ObjCZeroArgSelector:
121 case ObjCOneArgSelector:
122 case ObjCMultiArgSelector:
Chris Lattner077bf5e2008-11-24 03:33:13 +0000123 return getObjCSelector().getAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000124
125 case CXXConstructorName: {
126 QualType ClassType = getCXXNameType();
127 if (const RecordType *ClassRec = ClassType->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000128 return ClassRec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000129 return ClassType.getAsString();
130 }
131
132 case CXXDestructorName: {
133 std::string Result = "~";
134 QualType Type = getCXXNameType();
135 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000136 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000137 else
138 Result += Type.getAsString();
139 return Result;
140 }
141
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000142 case CXXOperatorName: {
143 static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
144 0,
145#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
146 Spelling,
147#include "clang/Basic/OperatorKinds.def"
148 };
149 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
150 assert(OpName && "not an overloaded operator");
151
152 std::string Result = "operator";
153 if (OpName[0] >= 'a' && OpName[0] <= 'z')
154 Result += ' ';
155 Result += OpName;
156 return Result;
157 }
158
Douglas Gregor10bd3682008-11-17 22:58:34 +0000159 case CXXConversionFunctionName: {
160 std::string Result = "operator ";
161 QualType Type = getCXXNameType();
162 if (const RecordType *Rec = Type->getAsRecordType())
Chris Lattner39f34e92008-11-24 04:00:27 +0000163 Result += Rec->getDecl()->getNameAsString();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000164 else
165 Result += Type.getAsString();
166 return Result;
167 }
168 }
169
170 assert(false && "Unexpected declaration name kind");
171 return "";
172}
173
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000174QualType DeclarationName::getCXXNameType() const {
175 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
176 return CXXName->Type;
177 else
178 return QualType();
179}
180
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000181OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
182 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
183 unsigned value
184 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
185 return static_cast<OverloadedOperatorKind>(value);
186 } else {
187 return OO_None;
188 }
189}
190
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000191Selector DeclarationName::getObjCSelector() const {
192 switch (getNameKind()) {
193 case ObjCZeroArgSelector:
194 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
195
196 case ObjCOneArgSelector:
197 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
198
199 case ObjCMultiArgSelector:
200 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
201
202 default:
203 break;
204 }
205
206 return Selector();
207}
208
Douglas Gregor2def4832008-11-17 20:34:05 +0000209void *DeclarationName::getFETokenInfoAsVoid() const {
210 switch (getNameKind()) {
211 case Identifier:
212 return getAsIdentifierInfo()->getFETokenInfo<void>();
213
214 case CXXConstructorName:
215 case CXXDestructorName:
216 case CXXConversionFunctionName:
217 return getAsCXXSpecialName()->FETokenInfo;
218
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000219 case CXXOperatorName:
220 return getAsCXXOperatorIdName()->FETokenInfo;
221
Douglas Gregor2def4832008-11-17 20:34:05 +0000222 default:
223 assert(false && "Declaration name has no FETokenInfo");
224 }
225 return 0;
226}
227
228void DeclarationName::setFETokenInfo(void *T) {
229 switch (getNameKind()) {
230 case Identifier:
231 getAsIdentifierInfo()->setFETokenInfo(T);
232 break;
233
234 case CXXConstructorName:
235 case CXXDestructorName:
236 case CXXConversionFunctionName:
237 getAsCXXSpecialName()->FETokenInfo = T;
238 break;
239
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000240 case CXXOperatorName:
241 getAsCXXOperatorIdName()->FETokenInfo = T;
242 break;
243
Douglas Gregor2def4832008-11-17 20:34:05 +0000244 default:
245 assert(false && "Declaration name has no FETokenInfo");
246 }
247}
248
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000249DeclarationNameTable::DeclarationNameTable() {
250 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000251
252 // Initialize the overloaded operator names.
253 CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
254 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
255 CXXOperatorNames[Op].ExtraKindOrNumArgs
256 = Op + DeclarationNameExtra::CXXConversionFunction;
257 CXXOperatorNames[Op].FETokenInfo = 0;
258 }
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000259}
260
261DeclarationNameTable::~DeclarationNameTable() {
262 delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000263 delete [] CXXOperatorNames;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000264}
265
266DeclarationName
267DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
268 QualType Ty) {
269 assert(Kind >= DeclarationName::CXXConstructorName &&
270 Kind <= DeclarationName::CXXConversionFunctionName &&
271 "Kind must be a C++ special name kind");
272
273 llvm::FoldingSet<CXXSpecialName> *SpecialNames
274 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
275
276 DeclarationNameExtra::ExtraKind EKind;
277 switch (Kind) {
278 case DeclarationName::CXXConstructorName:
279 EKind = DeclarationNameExtra::CXXConstructor;
280 break;
281 case DeclarationName::CXXDestructorName:
282 EKind = DeclarationNameExtra::CXXDestructor;
283 break;
284 case DeclarationName::CXXConversionFunctionName:
285 EKind = DeclarationNameExtra::CXXConversionFunction;
286 break;
287 default:
288 return DeclarationName();
289 }
290
291 // Unique selector, to guarantee there is one per name.
292 llvm::FoldingSetNodeID ID;
293 ID.AddInteger(EKind);
294 ID.AddPointer(Ty.getAsOpaquePtr());
295
296 void *InsertPos = 0;
297 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
298 return DeclarationName(Name);
299
300 CXXSpecialName *SpecialName = new CXXSpecialName;
301 SpecialName->ExtraKindOrNumArgs = EKind;
302 SpecialName->Type = Ty;
Douglas Gregor2def4832008-11-17 20:34:05 +0000303 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000304
305 SpecialNames->InsertNode(SpecialName, InsertPos);
306 return DeclarationName(SpecialName);
307}
308
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000309DeclarationName
310DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
311 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
312}
313
Douglas Gregor44b43212008-12-11 16:49:14 +0000314unsigned
315llvm::DenseMapInfo<clang::DeclarationName>::
316getHashValue(clang::DeclarationName N) {
317 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
318}
319