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 /// CXXLiberalOperatorName - 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 void Profile(llvm::FoldingSetNodeID &FSID) {
72 static int compareInt(unsigned A, unsigned B) {
73 return (A < B ? -1 : (A > B ? 1 : 0));
76 int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
77 if (LHS.getNameKind() != RHS.getNameKind())
78 return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
80 switch (LHS.getNameKind()) {
81 case DeclarationName::Identifier: {
82 IdentifierInfo *LII = LHS.getAsIdentifierInfo();
83 IdentifierInfo *RII = RHS.getAsIdentifierInfo();
84 if (!LII) return RII ? -1 : 0;
87 return LII->getName().compare(RII->getName());
90 case DeclarationName::ObjCZeroArgSelector:
91 case DeclarationName::ObjCOneArgSelector:
92 case DeclarationName::ObjCMultiArgSelector: {
93 Selector LHSSelector = LHS.getObjCSelector();
94 Selector RHSSelector = RHS.getObjCSelector();
95 unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
96 for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
97 switch (LHSSelector.getNameForSlot(I).compare(
98 RHSSelector.getNameForSlot(I))) {
100 case 1: return false;
105 return compareInt(LN, RN);
108 case DeclarationName::CXXConstructorName:
109 case DeclarationName::CXXDestructorName:
110 case DeclarationName::CXXConversionFunctionName:
111 if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
113 if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
117 case DeclarationName::CXXOperatorName:
118 return compareInt(LHS.getCXXOverloadedOperator(),
119 RHS.getCXXOverloadedOperator());
121 case DeclarationName::CXXLiteralOperatorName:
122 return LHS.getCXXLiteralIdentifier()->getName().compare(
123 RHS.getCXXLiteralIdentifier()->getName());
125 case DeclarationName::CXXUsingDirective:
132 } // end namespace clang
134 DeclarationName::DeclarationName(Selector Sel) {
135 if (!Sel.getAsOpaquePtr()) {
140 switch (Sel.getNumArgs()) {
142 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
143 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
144 Ptr |= StoredObjCZeroArgSelector;
148 Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
149 assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
150 Ptr |= StoredObjCOneArgSelector;
154 Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
155 assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
156 Ptr |= StoredDeclarationNameExtra;
161 DeclarationName::NameKind DeclarationName::getNameKind() const {
162 switch (getStoredNameKind()) {
163 case StoredIdentifier: return Identifier;
164 case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
165 case StoredObjCOneArgSelector: return ObjCOneArgSelector;
167 case StoredDeclarationNameExtra:
168 switch (getExtra()->ExtraKindOrNumArgs) {
169 case DeclarationNameExtra::CXXConstructor:
170 return CXXConstructorName;
172 case DeclarationNameExtra::CXXDestructor:
173 return CXXDestructorName;
175 case DeclarationNameExtra::CXXConversionFunction:
176 return CXXConversionFunctionName;
178 case DeclarationNameExtra::CXXLiteralOperator:
179 return CXXLiteralOperatorName;
181 case DeclarationNameExtra::CXXUsingDirective:
182 return CXXUsingDirective;
185 // Check if we have one of the CXXOperator* enumeration values.
186 if (getExtra()->ExtraKindOrNumArgs <
187 DeclarationNameExtra::CXXUsingDirective)
188 return CXXOperatorName;
190 return ObjCMultiArgSelector;
195 // Can't actually get here.
196 llvm_unreachable("This should be unreachable!");
199 bool DeclarationName::isDependentName() const {
200 QualType T = getCXXNameType();
201 return !T.isNull() && T->isDependentType();
204 std::string DeclarationName::getAsString() const {
206 llvm::raw_string_ostream OS(Result);
211 void DeclarationName::printName(raw_ostream &OS) const {
212 switch (getNameKind()) {
214 if (const IdentifierInfo *II = getAsIdentifierInfo())
218 case ObjCZeroArgSelector:
219 case ObjCOneArgSelector:
220 case ObjCMultiArgSelector:
221 OS << getObjCSelector().getAsString();
224 case CXXConstructorName: {
225 QualType ClassType = getCXXNameType();
226 if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
227 OS << *ClassRec->getDecl();
229 OS << ClassType.getAsString();
233 case CXXDestructorName: {
235 QualType Type = getCXXNameType();
236 if (const RecordType *Rec = Type->getAs<RecordType>())
237 OS << *Rec->getDecl();
239 OS << Type.getAsString();
243 case CXXOperatorName: {
244 static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
246 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
248 #include "clang/Basic/OperatorKinds.def"
250 const char *OpName = OperatorNames[getCXXOverloadedOperator()];
251 assert(OpName && "not an overloaded operator");
254 if (OpName[0] >= 'a' && OpName[0] <= 'z')
260 case CXXLiteralOperatorName:
261 OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
264 case CXXConversionFunctionName: {
266 QualType Type = getCXXNameType();
267 if (const RecordType *Rec = Type->getAs<RecordType>())
268 OS << *Rec->getDecl();
270 OS << Type.getAsString();
273 case CXXUsingDirective:
274 OS << "<using-directive>";
278 llvm_unreachable("Unexpected declaration name kind");
281 QualType DeclarationName::getCXXNameType() const {
282 if (CXXSpecialName *CXXName = getAsCXXSpecialName())
283 return CXXName->Type;
288 OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
289 if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
291 = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
292 return static_cast<OverloadedOperatorKind>(value);
298 IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
299 if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
305 Selector DeclarationName::getObjCSelector() const {
306 switch (getNameKind()) {
307 case ObjCZeroArgSelector:
308 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
310 case ObjCOneArgSelector:
311 return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
313 case ObjCMultiArgSelector:
314 return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
323 void *DeclarationName::getFETokenInfoAsVoid() const {
324 switch (getNameKind()) {
326 return getAsIdentifierInfo()->getFETokenInfo<void>();
328 case CXXConstructorName:
329 case CXXDestructorName:
330 case CXXConversionFunctionName:
331 return getAsCXXSpecialName()->FETokenInfo;
333 case CXXOperatorName:
334 return getAsCXXOperatorIdName()->FETokenInfo;
336 case CXXLiteralOperatorName:
337 return getCXXLiteralIdentifier()->getFETokenInfo<void>();
340 llvm_unreachable("Declaration name has no FETokenInfo");
344 void DeclarationName::setFETokenInfo(void *T) {
345 switch (getNameKind()) {
347 getAsIdentifierInfo()->setFETokenInfo(T);
350 case CXXConstructorName:
351 case CXXDestructorName:
352 case CXXConversionFunctionName:
353 getAsCXXSpecialName()->FETokenInfo = T;
356 case CXXOperatorName:
357 getAsCXXOperatorIdName()->FETokenInfo = T;
360 case CXXLiteralOperatorName:
361 getCXXLiteralIdentifier()->setFETokenInfo(T);
365 llvm_unreachable("Declaration name has no FETokenInfo");
369 DeclarationName DeclarationName::getUsingDirectiveName() {
370 // Single instance of DeclarationNameExtra for using-directive
371 static const DeclarationNameExtra UDirExtra =
372 { DeclarationNameExtra::CXXUsingDirective };
374 uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
375 Ptr |= StoredDeclarationNameExtra;
377 return DeclarationName(Ptr);
380 void DeclarationName::dump() const {
381 printName(llvm::errs());
382 llvm::errs() << '\n';
385 DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
386 CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
387 CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
389 // Initialize the overloaded operator names.
390 CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
391 for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
392 CXXOperatorNames[Op].ExtraKindOrNumArgs
393 = Op + DeclarationNameExtra::CXXConversionFunction;
394 CXXOperatorNames[Op].FETokenInfo = 0;
398 DeclarationNameTable::~DeclarationNameTable() {
399 llvm::FoldingSet<CXXSpecialName> *SpecialNames =
400 static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
401 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
402 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
403 (CXXLiteralOperatorNames);
410 DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
412 assert(Kind >= DeclarationName::CXXConstructorName &&
413 Kind <= DeclarationName::CXXConversionFunctionName &&
414 "Kind must be a C++ special name kind");
415 llvm::FoldingSet<CXXSpecialName> *SpecialNames
416 = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
418 DeclarationNameExtra::ExtraKind EKind;
420 case DeclarationName::CXXConstructorName:
421 EKind = DeclarationNameExtra::CXXConstructor;
422 assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
424 case DeclarationName::CXXDestructorName:
425 EKind = DeclarationNameExtra::CXXDestructor;
426 assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
428 case DeclarationName::CXXConversionFunctionName:
429 EKind = DeclarationNameExtra::CXXConversionFunction;
432 return DeclarationName();
435 // Unique selector, to guarantee there is one per name.
436 llvm::FoldingSetNodeID ID;
437 ID.AddInteger(EKind);
438 ID.AddPointer(Ty.getAsOpaquePtr());
441 if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
442 return DeclarationName(Name);
444 CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
445 SpecialName->ExtraKindOrNumArgs = EKind;
446 SpecialName->Type = Ty;
447 SpecialName->FETokenInfo = 0;
449 SpecialNames->InsertNode(SpecialName, InsertPos);
450 return DeclarationName(SpecialName);
454 DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
455 return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
459 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
460 llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
461 = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
462 (CXXLiteralOperatorNames);
464 llvm::FoldingSetNodeID ID;
468 if (CXXLiteralOperatorIdName *Name =
469 LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
470 return DeclarationName (Name);
472 CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
473 LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
474 LiteralName->ID = II;
476 LiteralNames->InsertNode(LiteralName, InsertPos);
477 return DeclarationName(LiteralName);
481 llvm::DenseMapInfo<clang::DeclarationName>::
482 getHashValue(clang::DeclarationName N) {
483 return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
486 DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
487 switch (Name.getNameKind()) {
488 case DeclarationName::Identifier:
490 case DeclarationName::CXXConstructorName:
491 case DeclarationName::CXXDestructorName:
492 case DeclarationName::CXXConversionFunctionName:
495 case DeclarationName::CXXOperatorName:
496 CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
497 CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
499 case DeclarationName::CXXLiteralOperatorName:
500 CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
502 case DeclarationName::ObjCZeroArgSelector:
503 case DeclarationName::ObjCOneArgSelector:
504 case DeclarationName::ObjCMultiArgSelector:
507 case DeclarationName::CXXUsingDirective:
512 bool DeclarationNameInfo::containsUnexpandedParameterPack() const {
513 switch (Name.getNameKind()) {
514 case DeclarationName::Identifier:
515 case DeclarationName::ObjCZeroArgSelector:
516 case DeclarationName::ObjCOneArgSelector:
517 case DeclarationName::ObjCMultiArgSelector:
518 case DeclarationName::CXXOperatorName:
519 case DeclarationName::CXXLiteralOperatorName:
520 case DeclarationName::CXXUsingDirective:
523 case DeclarationName::CXXConstructorName:
524 case DeclarationName::CXXDestructorName:
525 case DeclarationName::CXXConversionFunctionName:
526 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
527 return TInfo->getType()->containsUnexpandedParameterPack();
529 return Name.getCXXNameType()->containsUnexpandedParameterPack();
531 llvm_unreachable("All name kinds handled.");
534 bool DeclarationNameInfo::isInstantiationDependent() const {
535 switch (Name.getNameKind()) {
536 case DeclarationName::Identifier:
537 case DeclarationName::ObjCZeroArgSelector:
538 case DeclarationName::ObjCOneArgSelector:
539 case DeclarationName::ObjCMultiArgSelector:
540 case DeclarationName::CXXOperatorName:
541 case DeclarationName::CXXLiteralOperatorName:
542 case DeclarationName::CXXUsingDirective:
545 case DeclarationName::CXXConstructorName:
546 case DeclarationName::CXXDestructorName:
547 case DeclarationName::CXXConversionFunctionName:
548 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
549 return TInfo->getType()->isInstantiationDependentType();
551 return Name.getCXXNameType()->isInstantiationDependentType();
553 llvm_unreachable("All name kinds handled.");
556 std::string DeclarationNameInfo::getAsString() const {
558 llvm::raw_string_ostream OS(Result);
563 void DeclarationNameInfo::printName(raw_ostream &OS) const {
564 switch (Name.getNameKind()) {
565 case DeclarationName::Identifier:
566 case DeclarationName::ObjCZeroArgSelector:
567 case DeclarationName::ObjCOneArgSelector:
568 case DeclarationName::ObjCMultiArgSelector:
569 case DeclarationName::CXXOperatorName:
570 case DeclarationName::CXXLiteralOperatorName:
571 case DeclarationName::CXXUsingDirective:
575 case DeclarationName::CXXConstructorName:
576 case DeclarationName::CXXDestructorName:
577 case DeclarationName::CXXConversionFunctionName:
578 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
579 if (Name.getNameKind() == DeclarationName::CXXDestructorName)
581 else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
583 OS << TInfo->getType().getAsString();
589 llvm_unreachable("Unexpected declaration name kind");
592 SourceLocation DeclarationNameInfo::getEndLoc() const {
593 switch (Name.getNameKind()) {
594 case DeclarationName::Identifier:
597 case DeclarationName::CXXOperatorName: {
598 unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
599 return SourceLocation::getFromRawEncoding(raw);
602 case DeclarationName::CXXLiteralOperatorName: {
603 unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
604 return SourceLocation::getFromRawEncoding(raw);
607 case DeclarationName::CXXConstructorName:
608 case DeclarationName::CXXDestructorName:
609 case DeclarationName::CXXConversionFunctionName:
610 if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
611 return TInfo->getTypeLoc().getEndLoc();
615 // DNInfo work in progress: FIXME.
616 case DeclarationName::ObjCZeroArgSelector:
617 case DeclarationName::ObjCOneArgSelector:
618 case DeclarationName::ObjCMultiArgSelector:
619 case DeclarationName::CXXUsingDirective:
622 llvm_unreachable("Unexpected declaration name kind");