blob: 96e194be8c9bed9c5b063478bcd61886b99a7c85 [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"
15#include "clang/Basic/IdentifierTable.h"
16#include "llvm/ADT/FoldingSet.h"
17#include "llvm/Bitcode/Serialize.h"
18#include "llvm/Bitcode/Deserialize.h"
19using namespace clang;
20
21namespace clang {
22/// CXXSpecialName - Records the type associated with one of the
23/// "special" kinds of declaration names in C++, e.g., constructors,
24/// destructors, and conversion functions.
25class CXXSpecialName
26 : public DeclarationNameExtra, public llvm::FoldingSetNode {
27public:
28 QualType Type;
29
30 void Profile(llvm::FoldingSetNodeID &ID) {
31 ID.AddInteger(ExtraKindOrNumArgs);
32 ID.AddPointer(Type.getAsOpaquePtr());
33 }
34};
35
36bool operator<(DeclarationName LHS, DeclarationName RHS) {
37 if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
38 if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
39 return strcmp(LhsId->getName(), RhsId->getName()) < 0;
40
41 return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
42}
43
44} // end namespace clang
45
46DeclarationName::DeclarationName(Selector Sel) {
47 switch (Sel.getNumArgs()) {
48 case 0:
49 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
50 Ptr |= StoredObjCZeroArgSelector;
51 break;
52
53 case 1:
54 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
55 Ptr |= StoredObjCOneArgSelector;
56 break;
57
58 default:
59 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
60 Ptr |= StoredObjCMultiArgSelectorOrCXXName;
61 break;
62 }
63}
64
65DeclarationName::NameKind DeclarationName::getNameKind() const {
66 switch (getStoredNameKind()) {
67 case StoredIdentifier: return Identifier;
68 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
69 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
70
71 case StoredObjCMultiArgSelectorOrCXXName:
72 switch (getExtra()->ExtraKindOrNumArgs) {
73 case DeclarationNameExtra::CXXConstructor:
74 return CXXConstructorName;
75
76 case DeclarationNameExtra::CXXDestructor:
77 return CXXDestructorName;
78
79 case DeclarationNameExtra::CXXConversionFunction:
80 return CXXConversionFunctionName;
81
82 default:
83 return ObjCMultiArgSelector;
84 }
85 break;
86 }
87
88 // Can't actually get here.
89 return Identifier;
90}
91
92QualType DeclarationName::getCXXNameType() const {
93 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
94 return CXXName->Type;
95 else
96 return QualType();
97}
98
99Selector DeclarationName::getObjCSelector() const {
100 switch (getNameKind()) {
101 case ObjCZeroArgSelector:
102 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
103
104 case ObjCOneArgSelector:
105 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
106
107 case ObjCMultiArgSelector:
108 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
109
110 default:
111 break;
112 }
113
114 return Selector();
115}
116
117DeclarationNameTable::DeclarationNameTable() {
118 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
119}
120
121DeclarationNameTable::~DeclarationNameTable() {
122 delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
123}
124
125DeclarationName
126DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
127 QualType Ty) {
128 assert(Kind >= DeclarationName::CXXConstructorName &&
129 Kind <= DeclarationName::CXXConversionFunctionName &&
130 "Kind must be a C++ special name kind");
131
132 llvm::FoldingSet<CXXSpecialName> *SpecialNames
133 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
134
135 DeclarationNameExtra::ExtraKind EKind;
136 switch (Kind) {
137 case DeclarationName::CXXConstructorName:
138 EKind = DeclarationNameExtra::CXXConstructor;
139 break;
140 case DeclarationName::CXXDestructorName:
141 EKind = DeclarationNameExtra::CXXDestructor;
142 break;
143 case DeclarationName::CXXConversionFunctionName:
144 EKind = DeclarationNameExtra::CXXConversionFunction;
145 break;
146 default:
147 return DeclarationName();
148 }
149
150 // Unique selector, to guarantee there is one per name.
151 llvm::FoldingSetNodeID ID;
152 ID.AddInteger(EKind);
153 ID.AddPointer(Ty.getAsOpaquePtr());
154
155 void *InsertPos = 0;
156 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
157 return DeclarationName(Name);
158
159 CXXSpecialName *SpecialName = new CXXSpecialName;
160 SpecialName->ExtraKindOrNumArgs = EKind;
161 SpecialName->Type = Ty;
162
163 SpecialNames->InsertNode(SpecialName, InsertPos);
164 return DeclarationName(SpecialName);
165}
166