DeclarationName.cpp revision 25cf760b54d3b88633827501013bc51a29b28aba
1//===-- 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"
15#include "clang/AST/Type.h"
16#include "clang/AST/Decl.h"
17#include "clang/Basic/IdentifierTable.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/FoldingSet.h"
20using namespace clang;
21
22namespace clang {
23/// CXXSpecialName - Records the type associated with one of the
24/// "special" kinds of declaration names in C++, e.g., constructors,
25/// destructors, and conversion functions.
26class CXXSpecialName
27  : public DeclarationNameExtra, public llvm::FoldingSetNode {
28public:
29  /// Type - The type associated with this declaration name.
30  QualType Type;
31
32  /// FETokenInfo - Extra information associated with this declaration
33  /// name that can be used by the front end.
34  void *FETokenInfo;
35
36  void Profile(llvm::FoldingSetNodeID &ID) {
37    ID.AddInteger(ExtraKindOrNumArgs);
38    ID.AddPointer(Type.getAsOpaquePtr());
39  }
40};
41
42/// CXXOperatorIdName - Contains extra information for the name of an
43/// overloaded operator in C++, such as "operator+.
44class CXXOperatorIdName : public DeclarationNameExtra {
45public:
46  /// FETokenInfo - Extra information associated with this operator
47  /// name that can be used by the front end.
48  void *FETokenInfo;
49};
50
51bool operator<(DeclarationName LHS, DeclarationName RHS) {
52  if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
53    if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
54      return strcmp(LhsId->getName(), RhsId->getName()) < 0;
55
56  return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
57}
58
59} // end namespace clang
60
61DeclarationName::DeclarationName(Selector Sel) {
62  if (!Sel.getAsOpaquePtr()) {
63    Ptr = StoredObjCZeroArgSelector;
64    return;
65  }
66
67  switch (Sel.getNumArgs()) {
68  case 0:
69    Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
70    assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
71    Ptr |= StoredObjCZeroArgSelector;
72    break;
73
74  case 1:
75    Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
76    assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
77    Ptr |= StoredObjCOneArgSelector;
78    break;
79
80  default:
81    Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
82    assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
83    Ptr |= StoredDeclarationNameExtra;
84    break;
85  }
86}
87
88DeclarationName::NameKind DeclarationName::getNameKind() const {
89  switch (getStoredNameKind()) {
90  case StoredIdentifier:          return Identifier;
91  case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
92  case StoredObjCOneArgSelector:  return ObjCOneArgSelector;
93
94  case StoredDeclarationNameExtra:
95    switch (getExtra()->ExtraKindOrNumArgs) {
96    case DeclarationNameExtra::CXXConstructor:
97      return CXXConstructorName;
98
99    case DeclarationNameExtra::CXXDestructor:
100      return CXXDestructorName;
101
102    case DeclarationNameExtra::CXXConversionFunction:
103      return CXXConversionFunctionName;
104
105    case DeclarationNameExtra::CXXUsingDirective:
106      return CXXUsingDirective;
107
108    default:
109      // Check if we have one of the CXXOperator* enumeration values.
110      if (getExtra()->ExtraKindOrNumArgs <
111            DeclarationNameExtra::CXXUsingDirective)
112        return CXXOperatorName;
113
114      return ObjCMultiArgSelector;
115    }
116    break;
117  }
118
119  // Can't actually get here.
120  assert(0 && "This should be unreachable!");
121  return Identifier;
122}
123
124std::string DeclarationName::getAsString() const {
125  switch (getNameKind()) {
126  case Identifier:
127    if (const IdentifierInfo *II = getAsIdentifierInfo())
128      return II->getName();
129    return "";
130
131  case ObjCZeroArgSelector:
132  case ObjCOneArgSelector:
133  case ObjCMultiArgSelector:
134    return getObjCSelector().getAsString();
135
136  case CXXConstructorName: {
137    QualType ClassType = getCXXNameType();
138    if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
139      return ClassRec->getDecl()->getNameAsString();
140    return ClassType.getAsString();
141  }
142
143  case CXXDestructorName: {
144    std::string Result = "~";
145    QualType Type = getCXXNameType();
146    if (const RecordType *Rec = Type->getAs<RecordType>())
147      Result += Rec->getDecl()->getNameAsString();
148    else
149      Result += Type.getAsString();
150    return Result;
151  }
152
153  case CXXOperatorName: {
154    static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
155      0,
156#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
157      Spelling,
158#include "clang/Basic/OperatorKinds.def"
159    };
160    const char *OpName = OperatorNames[getCXXOverloadedOperator()];
161    assert(OpName && "not an overloaded operator");
162
163    std::string Result = "operator";
164    if (OpName[0] >= 'a' && OpName[0] <= 'z')
165      Result += ' ';
166    Result += OpName;
167    return Result;
168  }
169
170  case CXXConversionFunctionName: {
171    std::string Result = "operator ";
172    QualType Type = getCXXNameType();
173    if (const RecordType *Rec = Type->getAs<RecordType>())
174      Result += Rec->getDecl()->getNameAsString();
175    else
176      Result += Type.getAsString();
177    return Result;
178  }
179  case CXXUsingDirective:
180    return "<using-directive>";
181  }
182
183  assert(false && "Unexpected declaration name kind");
184  return "";
185}
186
187QualType DeclarationName::getCXXNameType() const {
188  if (CXXSpecialName *CXXName = getAsCXXSpecialName())
189    return CXXName->Type;
190  else
191    return QualType();
192}
193
194OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
195  if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
196    unsigned value
197      = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
198    return static_cast<OverloadedOperatorKind>(value);
199  } else {
200    return OO_None;
201  }
202}
203
204Selector DeclarationName::getObjCSelector() const {
205  switch (getNameKind()) {
206  case ObjCZeroArgSelector:
207    return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
208
209  case ObjCOneArgSelector:
210    return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
211
212  case ObjCMultiArgSelector:
213    return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
214
215  default:
216    break;
217  }
218
219  return Selector();
220}
221
222void *DeclarationName::getFETokenInfoAsVoid() const {
223  switch (getNameKind()) {
224  case Identifier:
225    return getAsIdentifierInfo()->getFETokenInfo<void>();
226
227  case CXXConstructorName:
228  case CXXDestructorName:
229  case CXXConversionFunctionName:
230    return getAsCXXSpecialName()->FETokenInfo;
231
232  case CXXOperatorName:
233    return getAsCXXOperatorIdName()->FETokenInfo;
234
235  default:
236    assert(false && "Declaration name has no FETokenInfo");
237  }
238  return 0;
239}
240
241void DeclarationName::setFETokenInfo(void *T) {
242  switch (getNameKind()) {
243  case Identifier:
244    getAsIdentifierInfo()->setFETokenInfo(T);
245    break;
246
247  case CXXConstructorName:
248  case CXXDestructorName:
249  case CXXConversionFunctionName:
250    getAsCXXSpecialName()->FETokenInfo = T;
251    break;
252
253  case CXXOperatorName:
254    getAsCXXOperatorIdName()->FETokenInfo = T;
255    break;
256
257  default:
258    assert(false && "Declaration name has no FETokenInfo");
259  }
260}
261
262DeclarationName DeclarationName::getUsingDirectiveName() {
263  // Single instance of DeclarationNameExtra for using-directive
264  static DeclarationNameExtra UDirExtra =
265    { DeclarationNameExtra::CXXUsingDirective };
266
267  uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
268  Ptr |= StoredDeclarationNameExtra;
269
270  return DeclarationName(Ptr);
271}
272
273DeclarationNameTable::DeclarationNameTable() {
274  CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
275
276  // Initialize the overloaded operator names.
277  CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
278  for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
279    CXXOperatorNames[Op].ExtraKindOrNumArgs
280      = Op + DeclarationNameExtra::CXXConversionFunction;
281    CXXOperatorNames[Op].FETokenInfo = 0;
282  }
283}
284
285DeclarationNameTable::~DeclarationNameTable() {
286  llvm::FoldingSet<CXXSpecialName> *set =
287    static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
288  llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
289
290  while (I != E) {
291    CXXSpecialName *n = &*I++;
292    delete n;
293  }
294
295  delete set;
296  delete [] CXXOperatorNames;
297}
298
299DeclarationName
300DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
301                                        CanQualType Ty) {
302  assert(Kind >= DeclarationName::CXXConstructorName &&
303         Kind <= DeclarationName::CXXConversionFunctionName &&
304         "Kind must be a C++ special name kind");
305  llvm::FoldingSet<CXXSpecialName> *SpecialNames
306    = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
307
308  DeclarationNameExtra::ExtraKind EKind;
309  switch (Kind) {
310  case DeclarationName::CXXConstructorName:
311    EKind = DeclarationNameExtra::CXXConstructor;
312    assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
313    break;
314  case DeclarationName::CXXDestructorName:
315    EKind = DeclarationNameExtra::CXXDestructor;
316    assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
317    break;
318  case DeclarationName::CXXConversionFunctionName:
319    EKind = DeclarationNameExtra::CXXConversionFunction;
320    break;
321  default:
322    return DeclarationName();
323  }
324
325  // Unique selector, to guarantee there is one per name.
326  llvm::FoldingSetNodeID ID;
327  ID.AddInteger(EKind);
328  ID.AddPointer(Ty.getAsOpaquePtr());
329
330  void *InsertPos = 0;
331  if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
332    return DeclarationName(Name);
333
334  CXXSpecialName *SpecialName = new CXXSpecialName;
335  SpecialName->ExtraKindOrNumArgs = EKind;
336  SpecialName->Type = Ty;
337  SpecialName->FETokenInfo = 0;
338
339  SpecialNames->InsertNode(SpecialName, InsertPos);
340  return DeclarationName(SpecialName);
341}
342
343DeclarationName
344DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
345  return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
346}
347
348unsigned
349llvm::DenseMapInfo<clang::DeclarationName>::
350getHashValue(clang::DeclarationName N) {
351  return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
352}
353
354