blob: d58016a44cc772a446e9e51fde3054d805f8b8e5 [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
43bool operator<(DeclarationName LHS, DeclarationName RHS) {
44 if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
45 if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
46 return strcmp(LhsId->getName(), RhsId->getName()) < 0;
47
48 return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
49}
50
51} // end namespace clang
52
53DeclarationName::DeclarationName(Selector Sel) {
54 switch (Sel.getNumArgs()) {
55 case 0:
56 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
57 Ptr |= StoredObjCZeroArgSelector;
58 break;
59
60 case 1:
61 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
62 Ptr |= StoredObjCOneArgSelector;
63 break;
64
65 default:
66 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
67 Ptr |= StoredObjCMultiArgSelectorOrCXXName;
68 break;
69 }
70}
71
72DeclarationName::NameKind DeclarationName::getNameKind() const {
73 switch (getStoredNameKind()) {
74 case StoredIdentifier: return Identifier;
75 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
76 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
77
78 case StoredObjCMultiArgSelectorOrCXXName:
79 switch (getExtra()->ExtraKindOrNumArgs) {
80 case DeclarationNameExtra::CXXConstructor:
81 return CXXConstructorName;
82
83 case DeclarationNameExtra::CXXDestructor:
84 return CXXDestructorName;
85
86 case DeclarationNameExtra::CXXConversionFunction:
87 return CXXConversionFunctionName;
88
89 default:
90 return ObjCMultiArgSelector;
91 }
92 break;
93 }
94
95 // Can't actually get here.
96 return Identifier;
97}
98
Douglas Gregor10bd3682008-11-17 22:58:34 +000099std::string DeclarationName::getAsString() const {
100 switch (getNameKind()) {
101 case Identifier:
102 if (const IdentifierInfo *II = getAsIdentifierInfo())
103 return II->getName();
104 return "";
105
106 case ObjCZeroArgSelector:
107 case ObjCOneArgSelector:
108 case ObjCMultiArgSelector:
109 return getObjCSelector().getName();
110
111 case CXXConstructorName: {
112 QualType ClassType = getCXXNameType();
113 if (const RecordType *ClassRec = ClassType->getAsRecordType())
114 return ClassRec->getDecl()->getName();
115 return ClassType.getAsString();
116 }
117
118 case CXXDestructorName: {
119 std::string Result = "~";
120 QualType Type = getCXXNameType();
121 if (const RecordType *Rec = Type->getAsRecordType())
122 Result += Rec->getDecl()->getName();
123 else
124 Result += Type.getAsString();
125 return Result;
126 }
127
128 case CXXConversionFunctionName: {
129 std::string Result = "operator ";
130 QualType Type = getCXXNameType();
131 if (const RecordType *Rec = Type->getAsRecordType())
132 Result += Rec->getDecl()->getName();
133 else
134 Result += Type.getAsString();
135 return Result;
136 }
137 }
138
139 assert(false && "Unexpected declaration name kind");
140 return "";
141}
142
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000143QualType DeclarationName::getCXXNameType() const {
144 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
145 return CXXName->Type;
146 else
147 return QualType();
148}
149
150Selector DeclarationName::getObjCSelector() const {
151 switch (getNameKind()) {
152 case ObjCZeroArgSelector:
153 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
154
155 case ObjCOneArgSelector:
156 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
157
158 case ObjCMultiArgSelector:
159 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
160
161 default:
162 break;
163 }
164
165 return Selector();
166}
167
Douglas Gregor2def4832008-11-17 20:34:05 +0000168void *DeclarationName::getFETokenInfoAsVoid() const {
169 switch (getNameKind()) {
170 case Identifier:
171 return getAsIdentifierInfo()->getFETokenInfo<void>();
172
173 case CXXConstructorName:
174 case CXXDestructorName:
175 case CXXConversionFunctionName:
176 return getAsCXXSpecialName()->FETokenInfo;
177
178 default:
179 assert(false && "Declaration name has no FETokenInfo");
180 }
181 return 0;
182}
183
184void DeclarationName::setFETokenInfo(void *T) {
185 switch (getNameKind()) {
186 case Identifier:
187 getAsIdentifierInfo()->setFETokenInfo(T);
188 break;
189
190 case CXXConstructorName:
191 case CXXDestructorName:
192 case CXXConversionFunctionName:
193 getAsCXXSpecialName()->FETokenInfo = T;
194 break;
195
196 default:
197 assert(false && "Declaration name has no FETokenInfo");
198 }
199}
200
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000201DeclarationNameTable::DeclarationNameTable() {
202 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
203}
204
205DeclarationNameTable::~DeclarationNameTable() {
206 delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
207}
208
209DeclarationName
210DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
211 QualType Ty) {
212 assert(Kind >= DeclarationName::CXXConstructorName &&
213 Kind <= DeclarationName::CXXConversionFunctionName &&
214 "Kind must be a C++ special name kind");
215
216 llvm::FoldingSet<CXXSpecialName> *SpecialNames
217 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
218
219 DeclarationNameExtra::ExtraKind EKind;
220 switch (Kind) {
221 case DeclarationName::CXXConstructorName:
222 EKind = DeclarationNameExtra::CXXConstructor;
223 break;
224 case DeclarationName::CXXDestructorName:
225 EKind = DeclarationNameExtra::CXXDestructor;
226 break;
227 case DeclarationName::CXXConversionFunctionName:
228 EKind = DeclarationNameExtra::CXXConversionFunction;
229 break;
230 default:
231 return DeclarationName();
232 }
233
234 // Unique selector, to guarantee there is one per name.
235 llvm::FoldingSetNodeID ID;
236 ID.AddInteger(EKind);
237 ID.AddPointer(Ty.getAsOpaquePtr());
238
239 void *InsertPos = 0;
240 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
241 return DeclarationName(Name);
242
243 CXXSpecialName *SpecialName = new CXXSpecialName;
244 SpecialName->ExtraKindOrNumArgs = EKind;
245 SpecialName->Type = Ty;
Douglas Gregor2def4832008-11-17 20:34:05 +0000246 SpecialName->FETokenInfo = 0;
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000247
248 SpecialNames->InsertNode(SpecialName, InsertPos);
249 return DeclarationName(SpecialName);
250}
251