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/ErrorHandling.h"
24 #include "llvm/Support/raw_ostream.h"
25 using namespace 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.
32 : public DeclarationNameExtra, public llvm::FoldingSetNode {
34 /// Type - The type associated with this declaration name.
37 /// FETokenInfo - Extra information associated with this declaration
38 /// name that can be used by the front end.
41 void Profile(llvm::FoldingSetNodeID &ID) {
42 ID.AddInteger(ExtraKindOrNumArgs);
43 ID.AddPointer(Type.getAsOpaquePtr());
47 /// CXXOperatorIdName - Contains extra information for the name of an
48 /// overloaded operator in C++, such as "operator+.
49 class CXXOperatorIdName : public DeclarationNameExtra {
51 /// FETokenInfo - Extra information associated with this operator
52 /// name that can be used by the front end.
56 /// CXXLiteralOperatorName - Contains the actual identifier that makes up the
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.
62 class CXXLiteralOperatorIdName
63 : public DeclarationNameExtra, public llvm::FoldingSetNode {
67 /// FETokenInfo - Extra information associated with this operator
68 /// name that can be used by the front end.
71 void Profile(llvm::FoldingSetNodeID &FSID) {
76 static int compareInt(unsigned A, unsigned B) {
77 return (A < B ? -1 : (A > B ? 1 : 0));
80 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
81 if (LHS.getNameKind() != RHS.getNameKind())
82 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
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;
91 return LII->getName().compare(RII->getName());
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;
109 return compareInt(LN, RN);
112 case DeclarationName::CXXConstructorName:
113 case DeclarationName::CXXDestructorName:
114 case DeclarationName::CXXConversionFunctionName:
115 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
117 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
121 case DeclarationName::CXXOperatorName:
122 return compareInt(LHS.getCXXOverloadedOperator(),
123 RHS.getCXXOverloadedOperator());
125 case DeclarationName::CXXLiteralOperatorName:
126 return LHS.getCXXLiteralIdentifier()->getName().compare(
127 RHS.getCXXLiteralIdentifier()->getName());
129 case DeclarationName::CXXUsingDirective:
133 llvm_unreachable("Invalid DeclarationName Kind!");
136 } // end namespace clang
138 DeclarationName::DeclarationName(Selector Sel) {
139 if (!Sel.getAsOpaquePtr()) {
144 switch (Sel.getNumArgs()) {
146 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
147 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
148 Ptr |= StoredObjCZeroArgSelector;
152 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
153 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
154 Ptr |= StoredObjCOneArgSelector;
158 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
159 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
160 Ptr |= StoredDeclarationNameExtra;
165 DeclarationName::NameKind DeclarationName::getNameKind() const {
166 switch (getStoredNameKind()) {
167 case StoredIdentifier: return Identifier;
168 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
169 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
171 case StoredDeclarationNameExtra:
172 switch (getExtra()->ExtraKindOrNumArgs) {
173 case DeclarationNameExtra::CXXConstructor:
174 return CXXConstructorName;
176 case DeclarationNameExtra::CXXDestructor:
177 return CXXDestructorName;
179 case DeclarationNameExtra::CXXConversionFunction:
180 return CXXConversionFunctionName;
182 case DeclarationNameExtra::CXXLiteralOperator:
183 return CXXLiteralOperatorName;
185 case DeclarationNameExtra::CXXUsingDirective:
186 return CXXUsingDirective;
189 // Check if we have one of the CXXOperator* enumeration values.
190 if (getExtra()->ExtraKindOrNumArgs <
191 DeclarationNameExtra::CXXUsingDirective)
192 return CXXOperatorName;
194 return ObjCMultiArgSelector;
198 // Can't actually get here.
199 llvm_unreachable("This should be unreachable!");
202 bool DeclarationName::isDependentName() const {
203 QualType T = getCXXNameType();
204 return !T.isNull() && T->isDependentType();
207 std::string DeclarationName::getAsString() const {
209 llvm::raw_string_ostream OS(Result);
214 void DeclarationName::printName(raw_ostream &OS) const {
215 switch (getNameKind()) {
217 if (const IdentifierInfo *II = getAsIdentifierInfo())
221 case ObjCZeroArgSelector:
222 case ObjCOneArgSelector:
223 case ObjCMultiArgSelector:
224 OS << getObjCSelector().getAsString();
227 case CXXConstructorName: {
228 QualType ClassType = getCXXNameType();
229 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
230 OS << *ClassRec->getDecl();
232 OS << ClassType.getAsString();
236 case CXXDestructorName: {
238 QualType Type = getCXXNameType();
239 if (const RecordType *Rec = Type->getAs<RecordType>())
240 OS << *Rec->getDecl();
242 OS << Type.getAsString();
246 case CXXOperatorName: {
247 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
249 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
251 #include "clang/Basic/OperatorKinds.def"
253 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
254 assert(OpName && "not an overloaded operator");
257 if (OpName[0] >= 'a' && OpName[0] <= 'z')
263 case CXXLiteralOperatorName:
264 OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
267 case CXXConversionFunctionName: {
269 QualType Type = getCXXNameType();
270 if (const RecordType *Rec = Type->getAs<RecordType>())
271 OS << *Rec->getDecl();
273 OS << Type.getAsString();
276 case CXXUsingDirective:
277 OS << "<using-directive>";
281 llvm_unreachable("Unexpected declaration name kind");
284 QualType DeclarationName::getCXXNameType() const {
285 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
286 return CXXName->Type;
291 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
292 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
294 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
295 return static_cast<OverloadedOperatorKind>(value);
301 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
302 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
308 Selector DeclarationName::getObjCSelector() const {
309 switch (getNameKind()) {
310 case ObjCZeroArgSelector:
311 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
313 case ObjCOneArgSelector:
314 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
316 case ObjCMultiArgSelector:
317 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
326 void *DeclarationName::getFETokenInfoAsVoid() const {
327 switch (getNameKind()) {
329 return getAsIdentifierInfo()->getFETokenInfo<void>();
331 case CXXConstructorName:
332 case CXXDestructorName:
333 case CXXConversionFunctionName:
334 return getAsCXXSpecialName()->FETokenInfo;
336 case CXXOperatorName:
337 return getAsCXXOperatorIdName()->FETokenInfo;
339 case CXXLiteralOperatorName:
340 return getAsCXXLiteralOperatorIdName()->FETokenInfo;
343 llvm_unreachable("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 getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
368 llvm_unreachable("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(const 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;
478 LiteralName->FETokenInfo = 0;
480 LiteralNames->InsertNode(LiteralName, InsertPos);
481 return DeclarationName(LiteralName);
485 llvm::DenseMapInfo<clang::DeclarationName>::
486 getHashValue(clang::DeclarationName N) {
487 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
490 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
491 switch (Name.getNameKind()) {
492 case DeclarationName::Identifier:
494 case DeclarationName::CXXConstructorName:
495 case DeclarationName::CXXDestructorName:
496 case DeclarationName::CXXConversionFunctionName:
499 case DeclarationName::CXXOperatorName:
500 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
501 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
503 case DeclarationName::CXXLiteralOperatorName:
504 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
506 case DeclarationName::ObjCZeroArgSelector:
507 case DeclarationName::ObjCOneArgSelector:
508 case DeclarationName::ObjCMultiArgSelector:
511 case DeclarationName::CXXUsingDirective:
516 bool DeclarationNameInfo::containsUnexpandedParameterPack() 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:
527 case DeclarationName::CXXConstructorName:
528 case DeclarationName::CXXDestructorName:
529 case DeclarationName::CXXConversionFunctionName:
530 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
531 return TInfo->getType()->containsUnexpandedParameterPack();
533 return Name.getCXXNameType()->containsUnexpandedParameterPack();
535 llvm_unreachable("All name kinds handled.");
538 bool DeclarationNameInfo::isInstantiationDependent() const {
539 switch (Name.getNameKind()) {
540 case DeclarationName::Identifier:
541 case DeclarationName::ObjCZeroArgSelector:
542 case DeclarationName::ObjCOneArgSelector:
543 case DeclarationName::ObjCMultiArgSelector:
544 case DeclarationName::CXXOperatorName:
545 case DeclarationName::CXXLiteralOperatorName:
546 case DeclarationName::CXXUsingDirective:
549 case DeclarationName::CXXConstructorName:
550 case DeclarationName::CXXDestructorName:
551 case DeclarationName::CXXConversionFunctionName:
552 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
553 return TInfo->getType()->isInstantiationDependentType();
555 return Name.getCXXNameType()->isInstantiationDependentType();
557 llvm_unreachable("All name kinds handled.");
560 std::string DeclarationNameInfo::getAsString() const {
562 llvm::raw_string_ostream OS(Result);
567 void DeclarationNameInfo::printName(raw_ostream &OS) const {
568 switch (Name.getNameKind()) {
569 case DeclarationName::Identifier:
570 case DeclarationName::ObjCZeroArgSelector:
571 case DeclarationName::ObjCOneArgSelector:
572 case DeclarationName::ObjCMultiArgSelector:
573 case DeclarationName::CXXOperatorName:
574 case DeclarationName::CXXLiteralOperatorName:
575 case DeclarationName::CXXUsingDirective:
579 case DeclarationName::CXXConstructorName:
580 case DeclarationName::CXXDestructorName:
581 case DeclarationName::CXXConversionFunctionName:
582 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
583 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
585 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
587 OS << TInfo->getType().getAsString();
593 llvm_unreachable("Unexpected declaration name kind");
596 SourceLocation DeclarationNameInfo::getEndLoc() const {
597 switch (Name.getNameKind()) {
598 case DeclarationName::Identifier:
601 case DeclarationName::CXXOperatorName: {
602 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
603 return SourceLocation::getFromRawEncoding(raw);
606 case DeclarationName::CXXLiteralOperatorName: {
607 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
608 return SourceLocation::getFromRawEncoding(raw);
611 case DeclarationName::CXXConstructorName:
612 case DeclarationName::CXXDestructorName:
613 case DeclarationName::CXXConversionFunctionName:
614 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
615 return TInfo->getTypeLoc().getEndLoc();
619 // DNInfo work in progress: FIXME.
620 case DeclarationName::ObjCZeroArgSelector:
621 case DeclarationName::ObjCOneArgSelector:
622 case DeclarationName::ObjCMultiArgSelector:
623 case DeclarationName::CXXUsingDirective:
626 llvm_unreachable("Unexpected declaration name kind");