1 //===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the DeclarationName and DeclarationNameTable
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/raw_ostream.h"
24 using namespace clang;
27 /// CXXSpecialName - Records the type associated with one of the
28 /// "special" kinds of declaration names in C++, e.g., constructors,
29 /// destructors, and conversion functions.
31 : public DeclarationNameExtra, public llvm::FoldingSetNode {
33 /// Type - The type associated with this declaration name.
36 /// FETokenInfo - Extra information associated with this declaration
37 /// name that can be used by the front end.
40 void Profile(llvm::FoldingSetNodeID &ID) {
41 ID.AddInteger(ExtraKindOrNumArgs);
42 ID.AddPointer(Type.getAsOpaquePtr());
46 /// CXXOperatorIdName - Contains extra information for the name of an
47 /// overloaded operator in C++, such as "operator+.
48 class CXXOperatorIdName : public DeclarationNameExtra {
50 /// FETokenInfo - Extra information associated with this operator
51 /// name that can be used by the front end.
55 /// CXXLiberalOperatorName - Contains the actual identifier that makes up the
58 /// This identifier is stored here rather than directly in DeclarationName so as
59 /// to allow Objective-C selectors, which are about a million times more common,
60 /// to consume minimal memory.
61 class CXXLiteralOperatorIdName
62 : public DeclarationNameExtra, public llvm::FoldingSetNode {
66 void Profile(llvm::FoldingSetNodeID &FSID) {
71 static int compareInt(unsigned A, unsigned B) {
72 return (A < B ? -1 : (A > B ? 1 : 0));
75 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
76 if (LHS.getNameKind() != RHS.getNameKind())
77 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
79 switch (LHS.getNameKind()) {
80 case DeclarationName::Identifier: {
81 IdentifierInfo *LII = LHS.getAsIdentifierInfo();
82 IdentifierInfo *RII = RHS.getAsIdentifierInfo();
83 if (!LII) return RII ? -1 : 0;
86 return LII->getName().compare(RII->getName());
89 case DeclarationName::ObjCZeroArgSelector:
90 case DeclarationName::ObjCOneArgSelector:
91 case DeclarationName::ObjCMultiArgSelector: {
92 Selector LHSSelector = LHS.getObjCSelector();
93 Selector RHSSelector = RHS.getObjCSelector();
94 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
95 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
96 IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
97 IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
99 switch (LHSId->getName().compare(RHSId->getName())) {
100 case -1: return true;
101 case 1: return false;
106 return compareInt(LN, RN);
109 case DeclarationName::CXXConstructorName:
110 case DeclarationName::CXXDestructorName:
111 case DeclarationName::CXXConversionFunctionName:
112 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
114 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
118 case DeclarationName::CXXOperatorName:
119 return compareInt(LHS.getCXXOverloadedOperator(),
120 RHS.getCXXOverloadedOperator());
122 case DeclarationName::CXXLiteralOperatorName:
123 return LHS.getCXXLiteralIdentifier()->getName().compare(
124 RHS.getCXXLiteralIdentifier()->getName());
126 case DeclarationName::CXXUsingDirective:
133 } // end namespace clang
135 DeclarationName::DeclarationName(Selector Sel) {
136 if (!Sel.getAsOpaquePtr()) {
141 switch (Sel.getNumArgs()) {
143 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
144 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
145 Ptr |= StoredObjCZeroArgSelector;
149 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
150 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
151 Ptr |= StoredObjCOneArgSelector;
155 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
156 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
157 Ptr |= StoredDeclarationNameExtra;
162 DeclarationName::NameKind DeclarationName::getNameKind() const {
163 switch (getStoredNameKind()) {
164 case StoredIdentifier: return Identifier;
165 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
166 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
168 case StoredDeclarationNameExtra:
169 switch (getExtra()->ExtraKindOrNumArgs) {
170 case DeclarationNameExtra::CXXConstructor:
171 return CXXConstructorName;
173 case DeclarationNameExtra::CXXDestructor:
174 return CXXDestructorName;
176 case DeclarationNameExtra::CXXConversionFunction:
177 return CXXConversionFunctionName;
179 case DeclarationNameExtra::CXXLiteralOperator:
180 return CXXLiteralOperatorName;
182 case DeclarationNameExtra::CXXUsingDirective:
183 return CXXUsingDirective;
186 // Check if we have one of the CXXOperator* enumeration values.
187 if (getExtra()->ExtraKindOrNumArgs <
188 DeclarationNameExtra::CXXUsingDirective)
189 return CXXOperatorName;
191 return ObjCMultiArgSelector;
196 // Can't actually get here.
197 assert(0 && "This should be unreachable!");
201 bool DeclarationName::isDependentName() const {
202 QualType T = getCXXNameType();
203 return !T.isNull() && T->isDependentType();
206 std::string DeclarationName::getAsString() const {
208 llvm::raw_string_ostream OS(Result);
213 void DeclarationName::printName(llvm::raw_ostream &OS) const {
214 switch (getNameKind()) {
216 if (const IdentifierInfo *II = getAsIdentifierInfo())
220 case ObjCZeroArgSelector:
221 case ObjCOneArgSelector:
222 case ObjCMultiArgSelector:
223 OS << getObjCSelector().getAsString();
226 case CXXConstructorName: {
227 QualType ClassType = getCXXNameType();
228 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
229 OS << ClassRec->getDecl();
231 OS << ClassType.getAsString();
235 case CXXDestructorName: {
237 QualType Type = getCXXNameType();
238 if (const RecordType *Rec = Type->getAs<RecordType>())
239 OS << Rec->getDecl();
241 OS << Type.getAsString();
245 case CXXOperatorName: {
246 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
248 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
250 #include "clang/Basic/OperatorKinds.def"
252 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
253 assert(OpName && "not an overloaded operator");
256 if (OpName[0] >= 'a' && OpName[0] <= 'z')
262 case CXXLiteralOperatorName:
263 OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
266 case CXXConversionFunctionName: {
268 QualType Type = getCXXNameType();
269 if (const RecordType *Rec = Type->getAs<RecordType>())
270 OS << Rec->getDecl();
272 OS << Type.getAsString();
275 case CXXUsingDirective:
276 OS << "<using-directive>";
280 assert(false && "Unexpected declaration name kind");
283 QualType DeclarationName::getCXXNameType() const {
284 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
285 return CXXName->Type;
290 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
291 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
293 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
294 return static_cast<OverloadedOperatorKind>(value);
300 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
301 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
307 Selector DeclarationName::getObjCSelector() const {
308 switch (getNameKind()) {
309 case ObjCZeroArgSelector:
310 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
312 case ObjCOneArgSelector:
313 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
315 case ObjCMultiArgSelector:
316 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
325 void *DeclarationName::getFETokenInfoAsVoid() const {
326 switch (getNameKind()) {
328 return getAsIdentifierInfo()->getFETokenInfo<void>();
330 case CXXConstructorName:
331 case CXXDestructorName:
332 case CXXConversionFunctionName:
333 return getAsCXXSpecialName()->FETokenInfo;
335 case CXXOperatorName:
336 return getAsCXXOperatorIdName()->FETokenInfo;
338 case CXXLiteralOperatorName:
339 return getCXXLiteralIdentifier()->getFETokenInfo<void>();
342 assert(false && "Declaration name has no FETokenInfo");
347 void DeclarationName::setFETokenInfo(void *T) {
348 switch (getNameKind()) {
350 getAsIdentifierInfo()->setFETokenInfo(T);
353 case CXXConstructorName:
354 case CXXDestructorName:
355 case CXXConversionFunctionName:
356 getAsCXXSpecialName()->FETokenInfo = T;
359 case CXXOperatorName:
360 getAsCXXOperatorIdName()->FETokenInfo = T;
363 case CXXLiteralOperatorName:
364 getCXXLiteralIdentifier()->setFETokenInfo(T);
368 assert(false && "Declaration name has no FETokenInfo");
372 DeclarationName DeclarationName::getUsingDirectiveName() {
373 // Single instance of DeclarationNameExtra for using-directive
374 static const DeclarationNameExtra UDirExtra =
375 { DeclarationNameExtra::CXXUsingDirective };
377 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
378 Ptr |= StoredDeclarationNameExtra;
380 return DeclarationName(Ptr);
383 void DeclarationName::dump() const {
384 printName(llvm::errs());
385 llvm::errs() << '\n';
388 DeclarationNameTable::DeclarationNameTable(ASTContext &C) : Ctx(C) {
389 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
390 CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
392 // Initialize the overloaded operator names.
393 CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
394 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
395 CXXOperatorNames[Op].ExtraKindOrNumArgs
396 = Op + DeclarationNameExtra::CXXConversionFunction;
397 CXXOperatorNames[Op].FETokenInfo = 0;
401 DeclarationNameTable::~DeclarationNameTable() {
402 llvm::FoldingSet<CXXSpecialName> *SpecialNames =
403 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
404 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
405 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
406 (CXXLiteralOperatorNames);
413 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
415 assert(Kind >= DeclarationName::CXXConstructorName &&
416 Kind <= DeclarationName::CXXConversionFunctionName &&
417 "Kind must be a C++ special name kind");
418 llvm::FoldingSet<CXXSpecialName> *SpecialNames
419 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
421 DeclarationNameExtra::ExtraKind EKind;
423 case DeclarationName::CXXConstructorName:
424 EKind = DeclarationNameExtra::CXXConstructor;
425 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
427 case DeclarationName::CXXDestructorName:
428 EKind = DeclarationNameExtra::CXXDestructor;
429 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
431 case DeclarationName::CXXConversionFunctionName:
432 EKind = DeclarationNameExtra::CXXConversionFunction;
435 return DeclarationName();
438 // Unique selector, to guarantee there is one per name.
439 llvm::FoldingSetNodeID ID;
440 ID.AddInteger(EKind);
441 ID.AddPointer(Ty.getAsOpaquePtr());
444 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
445 return DeclarationName(Name);
447 CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
448 SpecialName->ExtraKindOrNumArgs = EKind;
449 SpecialName->Type = Ty;
450 SpecialName->FETokenInfo = 0;
452 SpecialNames->InsertNode(SpecialName, InsertPos);
453 return DeclarationName(SpecialName);
457 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
458 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
462 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
463 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
464 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
465 (CXXLiteralOperatorNames);
467 llvm::FoldingSetNodeID ID;
471 if (CXXLiteralOperatorIdName *Name =
472 LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
473 return DeclarationName (Name);
475 CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
476 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
477 LiteralName->ID = II;
479 LiteralNames->InsertNode(LiteralName, InsertPos);
480 return DeclarationName(LiteralName);
484 llvm::DenseMapInfo<clang::DeclarationName>::
485 getHashValue(clang::DeclarationName N) {
486 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
489 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
490 switch (Name.getNameKind()) {
491 case DeclarationName::Identifier:
493 case DeclarationName::CXXConstructorName:
494 case DeclarationName::CXXDestructorName:
495 case DeclarationName::CXXConversionFunctionName:
498 case DeclarationName::CXXOperatorName:
499 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
500 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
502 case DeclarationName::CXXLiteralOperatorName:
503 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
505 case DeclarationName::ObjCZeroArgSelector:
506 case DeclarationName::ObjCOneArgSelector:
507 case DeclarationName::ObjCMultiArgSelector:
510 case DeclarationName::CXXUsingDirective:
515 std::string DeclarationNameInfo::getAsString() const {
517 llvm::raw_string_ostream OS(Result);
522 void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const {
523 switch (Name.getNameKind()) {
524 case DeclarationName::Identifier:
525 case DeclarationName::ObjCZeroArgSelector:
526 case DeclarationName::ObjCOneArgSelector:
527 case DeclarationName::ObjCMultiArgSelector:
528 case DeclarationName::CXXOperatorName:
529 case DeclarationName::CXXLiteralOperatorName:
530 case DeclarationName::CXXUsingDirective:
534 case DeclarationName::CXXConstructorName:
535 case DeclarationName::CXXDestructorName:
536 case DeclarationName::CXXConversionFunctionName:
537 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
538 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
540 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
542 OS << TInfo->getType().getAsString();
548 assert(false && "Unexpected declaration name kind");
551 SourceLocation DeclarationNameInfo::getEndLoc() const {
552 switch (Name.getNameKind()) {
553 case DeclarationName::Identifier:
556 case DeclarationName::CXXOperatorName: {
557 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
558 return SourceLocation::getFromRawEncoding(raw);
561 case DeclarationName::CXXLiteralOperatorName: {
562 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
563 return SourceLocation::getFromRawEncoding(raw);
566 case DeclarationName::CXXConstructorName:
567 case DeclarationName::CXXDestructorName:
568 case DeclarationName::CXXConversionFunctionName:
569 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
570 return TInfo->getTypeLoc().getEndLoc();
574 // DNInfo work in progress: FIXME.
575 case DeclarationName::ObjCZeroArgSelector:
576 case DeclarationName::ObjCOneArgSelector:
577 case DeclarationName::ObjCMultiArgSelector:
578 case DeclarationName::CXXUsingDirective:
581 assert(false && "Unexpected declaration name kind");
582 return SourceLocation();