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/ASTContext.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclarationName.h"
17#include "clang/AST/Type.h"
18#include "clang/AST/TypeLoc.h"
19#include "clang/AST/TypeOrdering.h"
20#include "clang/Basic/IdentifierTable.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/raw_ostream.h"
25using namespace clang;
26
27namespace clang {
28/// CXXSpecialName - Records the type associated with one of the
29/// "special" kinds of declaration names in C++, e.g., constructors,
30/// destructors, and conversion functions.
31class CXXSpecialName
32  : public DeclarationNameExtra, public llvm::FoldingSetNode {
33public:
34  /// Type - The type associated with this declaration name.
35  QualType Type;
36
37  /// FETokenInfo - Extra information associated with this declaration
38  /// name that can be used by the front end.
39  void *FETokenInfo;
40
41  void Profile(llvm::FoldingSetNodeID &ID) {
42    ID.AddInteger(ExtraKindOrNumArgs);
43    ID.AddPointer(Type.getAsOpaquePtr());
44  }
45};
46
47/// CXXOperatorIdName - Contains extra information for the name of an
48/// overloaded operator in C++, such as "operator+.
49class CXXOperatorIdName : public DeclarationNameExtra {
50public:
51  /// FETokenInfo - Extra information associated with this operator
52  /// name that can be used by the front end.
53  void *FETokenInfo;
54};
55
56/// CXXLiteralOperatorName - Contains the actual identifier that makes up the
57/// name.
58///
59/// This identifier is stored here rather than directly in DeclarationName so as
60/// to allow Objective-C selectors, which are about a million times more common,
61/// to consume minimal memory.
62class CXXLiteralOperatorIdName
63  : public DeclarationNameExtra, public llvm::FoldingSetNode {
64public:
65  IdentifierInfo *ID;
66
67  /// FETokenInfo - Extra information associated with this operator
68  /// name that can be used by the front end.
69  void *FETokenInfo;
70
71  void Profile(llvm::FoldingSetNodeID &FSID) {
72    FSID.AddPointer(ID);
73  }
74};
75
76static int compareInt(unsigned A, unsigned B) {
77  return (A < B ? -1 : (A > B ? 1 : 0));
78}
79
80int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
81  if (LHS.getNameKind() != RHS.getNameKind())
82    return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
83
84  switch (LHS.getNameKind()) {
85  case DeclarationName::Identifier: {
86    IdentifierInfo *LII = LHS.getAsIdentifierInfo();
87    IdentifierInfo *RII = RHS.getAsIdentifierInfo();
88    if (!LII) return RII ? -1 : 0;
89    if (!RII) return 1;
90
91    return LII->getName().compare(RII->getName());
92  }
93
94  case DeclarationName::ObjCZeroArgSelector:
95  case DeclarationName::ObjCOneArgSelector:
96  case DeclarationName::ObjCMultiArgSelector: {
97    Selector LHSSelector = LHS.getObjCSelector();
98    Selector RHSSelector = RHS.getObjCSelector();
99    unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
100    for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
101      switch (LHSSelector.getNameForSlot(I).compare(
102                                               RHSSelector.getNameForSlot(I))) {
103      case -1: return true;
104      case 1: return false;
105      default: break;
106      }
107    }
108
109    return compareInt(LN, RN);
110  }
111
112  case DeclarationName::CXXConstructorName:
113  case DeclarationName::CXXDestructorName:
114  case DeclarationName::CXXConversionFunctionName:
115    if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
116      return -1;
117    if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
118      return 1;
119    return 0;
120
121  case DeclarationName::CXXOperatorName:
122    return compareInt(LHS.getCXXOverloadedOperator(),
123                      RHS.getCXXOverloadedOperator());
124
125  case DeclarationName::CXXLiteralOperatorName:
126    return LHS.getCXXLiteralIdentifier()->getName().compare(
127                                   RHS.getCXXLiteralIdentifier()->getName());
128
129  case DeclarationName::CXXUsingDirective:
130    return 0;
131  }
132
133  llvm_unreachable("Invalid DeclarationName Kind!");
134}
135
136} // end namespace clang
137
138DeclarationName::NameKind DeclarationName::getNameKind() const {
139  switch (getStoredNameKind()) {
140  case StoredIdentifier:          return Identifier;
141  case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
142  case StoredObjCOneArgSelector:  return ObjCOneArgSelector;
143
144  case StoredDeclarationNameExtra:
145    switch (getExtra()->ExtraKindOrNumArgs) {
146    case DeclarationNameExtra::CXXConstructor:
147      return CXXConstructorName;
148
149    case DeclarationNameExtra::CXXDestructor:
150      return CXXDestructorName;
151
152    case DeclarationNameExtra::CXXConversionFunction:
153      return CXXConversionFunctionName;
154
155    case DeclarationNameExtra::CXXLiteralOperator:
156      return CXXLiteralOperatorName;
157
158    case DeclarationNameExtra::CXXUsingDirective:
159      return CXXUsingDirective;
160
161    default:
162      // Check if we have one of the CXXOperator* enumeration values.
163      if (getExtra()->ExtraKindOrNumArgs <
164            DeclarationNameExtra::CXXUsingDirective)
165        return CXXOperatorName;
166
167      return ObjCMultiArgSelector;
168    }
169  }
170
171  // Can't actually get here.
172  llvm_unreachable("This should be unreachable!");
173}
174
175bool DeclarationName::isDependentName() const {
176  QualType T = getCXXNameType();
177  return !T.isNull() && T->isDependentType();
178}
179
180std::string DeclarationName::getAsString() const {
181  std::string Result;
182  llvm::raw_string_ostream OS(Result);
183  printName(OS);
184  return OS.str();
185}
186
187void DeclarationName::printName(raw_ostream &OS) const {
188  switch (getNameKind()) {
189  case Identifier:
190    if (const IdentifierInfo *II = getAsIdentifierInfo())
191      OS << II->getName();
192    return;
193
194  case ObjCZeroArgSelector:
195  case ObjCOneArgSelector:
196  case ObjCMultiArgSelector:
197    OS << getObjCSelector().getAsString();
198    return;
199
200  case CXXConstructorName: {
201    QualType ClassType = getCXXNameType();
202    if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
203      OS << *ClassRec->getDecl();
204    else
205      OS << ClassType.getAsString();
206    return;
207  }
208
209  case CXXDestructorName: {
210    OS << '~';
211    QualType Type = getCXXNameType();
212    if (const RecordType *Rec = Type->getAs<RecordType>())
213      OS << *Rec->getDecl();
214    else
215      OS << Type.getAsString();
216    return;
217  }
218
219  case CXXOperatorName: {
220    static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
221      0,
222#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
223      Spelling,
224#include "clang/Basic/OperatorKinds.def"
225    };
226    const char *OpName = OperatorNames[getCXXOverloadedOperator()];
227    assert(OpName && "not an overloaded operator");
228
229    OS << "operator";
230    if (OpName[0] >= 'a' && OpName[0] <= 'z')
231      OS << ' ';
232    OS << OpName;
233    return;
234  }
235
236  case CXXLiteralOperatorName:
237    OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
238    return;
239
240  case CXXConversionFunctionName: {
241    OS << "operator ";
242    QualType Type = getCXXNameType();
243    if (const RecordType *Rec = Type->getAs<RecordType>())
244      OS << *Rec->getDecl();
245    else
246      OS << Type.getAsString();
247    return;
248  }
249  case CXXUsingDirective:
250    OS << "<using-directive>";
251    return;
252  }
253
254  llvm_unreachable("Unexpected declaration name kind");
255}
256
257QualType DeclarationName::getCXXNameType() const {
258  if (CXXSpecialName *CXXName = getAsCXXSpecialName())
259    return CXXName->Type;
260  else
261    return QualType();
262}
263
264OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
265  if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
266    unsigned value
267      = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
268    return static_cast<OverloadedOperatorKind>(value);
269  } else {
270    return OO_None;
271  }
272}
273
274IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
275  if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
276    return CXXLit->ID;
277  else
278    return 0;
279}
280
281void *DeclarationName::getFETokenInfoAsVoidSlow() const {
282  switch (getNameKind()) {
283  case Identifier:
284    llvm_unreachable("Handled by getFETokenInfo()");
285
286  case CXXConstructorName:
287  case CXXDestructorName:
288  case CXXConversionFunctionName:
289    return getAsCXXSpecialName()->FETokenInfo;
290
291  case CXXOperatorName:
292    return getAsCXXOperatorIdName()->FETokenInfo;
293
294  case CXXLiteralOperatorName:
295    return getAsCXXLiteralOperatorIdName()->FETokenInfo;
296
297  default:
298    llvm_unreachable("Declaration name has no FETokenInfo");
299  }
300}
301
302void DeclarationName::setFETokenInfo(void *T) {
303  switch (getNameKind()) {
304  case Identifier:
305    getAsIdentifierInfo()->setFETokenInfo(T);
306    break;
307
308  case CXXConstructorName:
309  case CXXDestructorName:
310  case CXXConversionFunctionName:
311    getAsCXXSpecialName()->FETokenInfo = T;
312    break;
313
314  case CXXOperatorName:
315    getAsCXXOperatorIdName()->FETokenInfo = T;
316    break;
317
318  case CXXLiteralOperatorName:
319    getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
320    break;
321
322  default:
323    llvm_unreachable("Declaration name has no FETokenInfo");
324  }
325}
326
327DeclarationName DeclarationName::getUsingDirectiveName() {
328  // Single instance of DeclarationNameExtra for using-directive
329  static const DeclarationNameExtra UDirExtra =
330    { DeclarationNameExtra::CXXUsingDirective };
331
332  uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
333  Ptr |= StoredDeclarationNameExtra;
334
335  return DeclarationName(Ptr);
336}
337
338void DeclarationName::dump() const {
339  printName(llvm::errs());
340  llvm::errs() << '\n';
341}
342
343DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
344  CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
345  CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
346
347  // Initialize the overloaded operator names.
348  CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
349  for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
350    CXXOperatorNames[Op].ExtraKindOrNumArgs
351      = Op + DeclarationNameExtra::CXXConversionFunction;
352    CXXOperatorNames[Op].FETokenInfo = 0;
353  }
354}
355
356DeclarationNameTable::~DeclarationNameTable() {
357  llvm::FoldingSet<CXXSpecialName> *SpecialNames =
358    static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
359  llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
360    = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
361        (CXXLiteralOperatorNames);
362
363  delete SpecialNames;
364  delete LiteralNames;
365}
366
367DeclarationName
368DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
369                                        CanQualType Ty) {
370  assert(Kind >= DeclarationName::CXXConstructorName &&
371         Kind <= DeclarationName::CXXConversionFunctionName &&
372         "Kind must be a C++ special name kind");
373  llvm::FoldingSet<CXXSpecialName> *SpecialNames
374    = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
375
376  DeclarationNameExtra::ExtraKind EKind;
377  switch (Kind) {
378  case DeclarationName::CXXConstructorName:
379    EKind = DeclarationNameExtra::CXXConstructor;
380    assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
381    break;
382  case DeclarationName::CXXDestructorName:
383    EKind = DeclarationNameExtra::CXXDestructor;
384    assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
385    break;
386  case DeclarationName::CXXConversionFunctionName:
387    EKind = DeclarationNameExtra::CXXConversionFunction;
388    break;
389  default:
390    return DeclarationName();
391  }
392
393  // Unique selector, to guarantee there is one per name.
394  llvm::FoldingSetNodeID ID;
395  ID.AddInteger(EKind);
396  ID.AddPointer(Ty.getAsOpaquePtr());
397
398  void *InsertPos = 0;
399  if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
400    return DeclarationName(Name);
401
402  CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
403  SpecialName->ExtraKindOrNumArgs = EKind;
404  SpecialName->Type = Ty;
405  SpecialName->FETokenInfo = 0;
406
407  SpecialNames->InsertNode(SpecialName, InsertPos);
408  return DeclarationName(SpecialName);
409}
410
411DeclarationName
412DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
413  return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
414}
415
416DeclarationName
417DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
418  llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
419    = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
420                                                      (CXXLiteralOperatorNames);
421
422  llvm::FoldingSetNodeID ID;
423  ID.AddPointer(II);
424
425  void *InsertPos = 0;
426  if (CXXLiteralOperatorIdName *Name =
427                               LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
428    return DeclarationName (Name);
429
430  CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
431  LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
432  LiteralName->ID = II;
433  LiteralName->FETokenInfo = 0;
434
435  LiteralNames->InsertNode(LiteralName, InsertPos);
436  return DeclarationName(LiteralName);
437}
438
439DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
440  switch (Name.getNameKind()) {
441  case DeclarationName::Identifier:
442    break;
443  case DeclarationName::CXXConstructorName:
444  case DeclarationName::CXXDestructorName:
445  case DeclarationName::CXXConversionFunctionName:
446    NamedType.TInfo = 0;
447    break;
448  case DeclarationName::CXXOperatorName:
449    CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
450    CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
451    break;
452  case DeclarationName::CXXLiteralOperatorName:
453    CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
454    break;
455  case DeclarationName::ObjCZeroArgSelector:
456  case DeclarationName::ObjCOneArgSelector:
457  case DeclarationName::ObjCMultiArgSelector:
458    // FIXME: ?
459    break;
460  case DeclarationName::CXXUsingDirective:
461    break;
462  }
463}
464
465bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
466  switch (Name.getNameKind()) {
467  case DeclarationName::Identifier:
468  case DeclarationName::ObjCZeroArgSelector:
469  case DeclarationName::ObjCOneArgSelector:
470  case DeclarationName::ObjCMultiArgSelector:
471  case DeclarationName::CXXOperatorName:
472  case DeclarationName::CXXLiteralOperatorName:
473  case DeclarationName::CXXUsingDirective:
474    return false;
475
476  case DeclarationName::CXXConstructorName:
477  case DeclarationName::CXXDestructorName:
478  case DeclarationName::CXXConversionFunctionName:
479    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
480      return TInfo->getType()->containsUnexpandedParameterPack();
481
482    return Name.getCXXNameType()->containsUnexpandedParameterPack();
483  }
484  llvm_unreachable("All name kinds handled.");
485}
486
487bool DeclarationNameInfo::isInstantiationDependent() const {
488  switch (Name.getNameKind()) {
489  case DeclarationName::Identifier:
490  case DeclarationName::ObjCZeroArgSelector:
491  case DeclarationName::ObjCOneArgSelector:
492  case DeclarationName::ObjCMultiArgSelector:
493  case DeclarationName::CXXOperatorName:
494  case DeclarationName::CXXLiteralOperatorName:
495  case DeclarationName::CXXUsingDirective:
496    return false;
497
498  case DeclarationName::CXXConstructorName:
499  case DeclarationName::CXXDestructorName:
500  case DeclarationName::CXXConversionFunctionName:
501    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
502      return TInfo->getType()->isInstantiationDependentType();
503
504    return Name.getCXXNameType()->isInstantiationDependentType();
505  }
506  llvm_unreachable("All name kinds handled.");
507}
508
509std::string DeclarationNameInfo::getAsString() const {
510  std::string Result;
511  llvm::raw_string_ostream OS(Result);
512  printName(OS);
513  return OS.str();
514}
515
516void DeclarationNameInfo::printName(raw_ostream &OS) const {
517  switch (Name.getNameKind()) {
518  case DeclarationName::Identifier:
519  case DeclarationName::ObjCZeroArgSelector:
520  case DeclarationName::ObjCOneArgSelector:
521  case DeclarationName::ObjCMultiArgSelector:
522  case DeclarationName::CXXOperatorName:
523  case DeclarationName::CXXLiteralOperatorName:
524  case DeclarationName::CXXUsingDirective:
525    Name.printName(OS);
526    return;
527
528  case DeclarationName::CXXConstructorName:
529  case DeclarationName::CXXDestructorName:
530  case DeclarationName::CXXConversionFunctionName:
531    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
532      if (Name.getNameKind() == DeclarationName::CXXDestructorName)
533        OS << '~';
534      else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
535        OS << "operator ";
536      OS << TInfo->getType().getAsString();
537    }
538    else
539      Name.printName(OS);
540    return;
541  }
542  llvm_unreachable("Unexpected declaration name kind");
543}
544
545SourceLocation DeclarationNameInfo::getEndLoc() const {
546  switch (Name.getNameKind()) {
547  case DeclarationName::Identifier:
548    return NameLoc;
549
550  case DeclarationName::CXXOperatorName: {
551    unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
552    return SourceLocation::getFromRawEncoding(raw);
553  }
554
555  case DeclarationName::CXXLiteralOperatorName: {
556    unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
557    return SourceLocation::getFromRawEncoding(raw);
558  }
559
560  case DeclarationName::CXXConstructorName:
561  case DeclarationName::CXXDestructorName:
562  case DeclarationName::CXXConversionFunctionName:
563    if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
564      return TInfo->getTypeLoc().getEndLoc();
565    else
566      return NameLoc;
567
568    // DNInfo work in progress: FIXME.
569  case DeclarationName::ObjCZeroArgSelector:
570  case DeclarationName::ObjCOneArgSelector:
571  case DeclarationName::ObjCMultiArgSelector:
572  case DeclarationName::CXXUsingDirective:
573    return NameLoc;
574  }
575  llvm_unreachable("Unexpected declaration name kind");
576}
577