diff options
Diffstat (limited to 'clang/lib/AST/DeclarationName.cpp')
-rw-r--r-- | clang/lib/AST/DeclarationName.cpp | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp new file mode 100644 index 0000000..64924ad --- /dev/null +++ b/clang/lib/AST/DeclarationName.cpp @@ -0,0 +1,627 @@ +//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the DeclarationName and DeclarationNameTable +// classes. +// +//===----------------------------------------------------------------------===// +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +namespace clang { +/// CXXSpecialName - Records the type associated with one of the +/// "special" kinds of declaration names in C++, e.g., constructors, +/// destructors, and conversion functions. +class CXXSpecialName + : public DeclarationNameExtra, public llvm::FoldingSetNode { +public: + /// Type - The type associated with this declaration name. + QualType Type; + + /// FETokenInfo - Extra information associated with this declaration + /// name that can be used by the front end. + void *FETokenInfo; + + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddInteger(ExtraKindOrNumArgs); + ID.AddPointer(Type.getAsOpaquePtr()); + } +}; + +/// CXXOperatorIdName - Contains extra information for the name of an +/// overloaded operator in C++, such as "operator+. +class CXXOperatorIdName : public DeclarationNameExtra { +public: + /// FETokenInfo - Extra information associated with this operator + /// name that can be used by the front end. + void *FETokenInfo; +}; + +/// CXXLiteralOperatorName - Contains the actual identifier that makes up the +/// name. +/// +/// This identifier is stored here rather than directly in DeclarationName so as +/// to allow Objective-C selectors, which are about a million times more common, +/// to consume minimal memory. +class CXXLiteralOperatorIdName + : public DeclarationNameExtra, public llvm::FoldingSetNode { +public: + IdentifierInfo *ID; + + /// FETokenInfo - Extra information associated with this operator + /// name that can be used by the front end. + void *FETokenInfo; + + void Profile(llvm::FoldingSetNodeID &FSID) { + FSID.AddPointer(ID); + } +}; + +static int compareInt(unsigned A, unsigned B) { + return (A < B ? -1 : (A > B ? 1 : 0)); +} + +int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { + if (LHS.getNameKind() != RHS.getNameKind()) + return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1); + + switch (LHS.getNameKind()) { + case DeclarationName::Identifier: { + IdentifierInfo *LII = LHS.getAsIdentifierInfo(); + IdentifierInfo *RII = RHS.getAsIdentifierInfo(); + if (!LII) return RII ? -1 : 0; + if (!RII) return 1; + + return LII->getName().compare(RII->getName()); + } + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: { + Selector LHSSelector = LHS.getObjCSelector(); + Selector RHSSelector = RHS.getObjCSelector(); + unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); + for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { + switch (LHSSelector.getNameForSlot(I).compare( + RHSSelector.getNameForSlot(I))) { + case -1: return true; + case 1: return false; + default: break; + } + } + + return compareInt(LN, RN); + } + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType())) + return -1; + if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType())) + return 1; + return 0; + + case DeclarationName::CXXOperatorName: + return compareInt(LHS.getCXXOverloadedOperator(), + RHS.getCXXOverloadedOperator()); + + case DeclarationName::CXXLiteralOperatorName: + return LHS.getCXXLiteralIdentifier()->getName().compare( + RHS.getCXXLiteralIdentifier()->getName()); + + case DeclarationName::CXXUsingDirective: + return 0; + } + + llvm_unreachable("Invalid DeclarationName Kind!"); +} + +} // end namespace clang + +DeclarationName::DeclarationName(Selector Sel) { + if (!Sel.getAsOpaquePtr()) { + Ptr = 0; + return; + } + + switch (Sel.getNumArgs()) { + case 0: + Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo()); + assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); + Ptr |= StoredObjCZeroArgSelector; + break; + + case 1: + Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo()); + assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); + Ptr |= StoredObjCOneArgSelector; + break; + + default: + Ptr = Sel.InfoPtr & ~Selector::ArgFlags; + assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector"); + Ptr |= StoredDeclarationNameExtra; + break; + } +} + +DeclarationName::NameKind DeclarationName::getNameKind() const { + switch (getStoredNameKind()) { + case StoredIdentifier: return Identifier; + case StoredObjCZeroArgSelector: return ObjCZeroArgSelector; + case StoredObjCOneArgSelector: return ObjCOneArgSelector; + + case StoredDeclarationNameExtra: + switch (getExtra()->ExtraKindOrNumArgs) { + case DeclarationNameExtra::CXXConstructor: + return CXXConstructorName; + + case DeclarationNameExtra::CXXDestructor: + return CXXDestructorName; + + case DeclarationNameExtra::CXXConversionFunction: + return CXXConversionFunctionName; + + case DeclarationNameExtra::CXXLiteralOperator: + return CXXLiteralOperatorName; + + case DeclarationNameExtra::CXXUsingDirective: + return CXXUsingDirective; + + default: + // Check if we have one of the CXXOperator* enumeration values. + if (getExtra()->ExtraKindOrNumArgs < + DeclarationNameExtra::CXXUsingDirective) + return CXXOperatorName; + + return ObjCMultiArgSelector; + } + } + + // Can't actually get here. + llvm_unreachable("This should be unreachable!"); +} + +bool DeclarationName::isDependentName() const { + QualType T = getCXXNameType(); + return !T.isNull() && T->isDependentType(); +} + +std::string DeclarationName::getAsString() const { + std::string Result; + llvm::raw_string_ostream OS(Result); + printName(OS); + return OS.str(); +} + +void DeclarationName::printName(raw_ostream &OS) const { + switch (getNameKind()) { + case Identifier: + if (const IdentifierInfo *II = getAsIdentifierInfo()) + OS << II->getName(); + return; + + case ObjCZeroArgSelector: + case ObjCOneArgSelector: + case ObjCMultiArgSelector: + OS << getObjCSelector().getAsString(); + return; + + case CXXConstructorName: { + QualType ClassType = getCXXNameType(); + if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) + OS << *ClassRec->getDecl(); + else + OS << ClassType.getAsString(); + return; + } + + case CXXDestructorName: { + OS << '~'; + QualType Type = getCXXNameType(); + if (const RecordType *Rec = Type->getAs<RecordType>()) + OS << *Rec->getDecl(); + else + OS << Type.getAsString(); + return; + } + + case CXXOperatorName: { + static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { + 0, +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + Spelling, +#include "clang/Basic/OperatorKinds.def" + }; + const char *OpName = OperatorNames[getCXXOverloadedOperator()]; + assert(OpName && "not an overloaded operator"); + + OS << "operator"; + if (OpName[0] >= 'a' && OpName[0] <= 'z') + OS << ' '; + OS << OpName; + return; + } + + case CXXLiteralOperatorName: + OS << "operator \"\" " << getCXXLiteralIdentifier()->getName(); + return; + + case CXXConversionFunctionName: { + OS << "operator "; + QualType Type = getCXXNameType(); + if (const RecordType *Rec = Type->getAs<RecordType>()) + OS << *Rec->getDecl(); + else + OS << Type.getAsString(); + return; + } + case CXXUsingDirective: + OS << "<using-directive>"; + return; + } + + llvm_unreachable("Unexpected declaration name kind"); +} + +QualType DeclarationName::getCXXNameType() const { + if (CXXSpecialName *CXXName = getAsCXXSpecialName()) + return CXXName->Type; + else + return QualType(); +} + +OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const { + if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) { + unsigned value + = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction; + return static_cast<OverloadedOperatorKind>(value); + } else { + return OO_None; + } +} + +IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const { + if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName()) + return CXXLit->ID; + else + return 0; +} + +Selector DeclarationName::getObjCSelector() const { + switch (getNameKind()) { + case ObjCZeroArgSelector: + return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0); + + case ObjCOneArgSelector: + return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1); + + case ObjCMultiArgSelector: + return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask)); + + default: + break; + } + + return Selector(); +} + +void *DeclarationName::getFETokenInfoAsVoid() const { + switch (getNameKind()) { + case Identifier: + return getAsIdentifierInfo()->getFETokenInfo<void>(); + + case CXXConstructorName: + case CXXDestructorName: + case CXXConversionFunctionName: + return getAsCXXSpecialName()->FETokenInfo; + + case CXXOperatorName: + return getAsCXXOperatorIdName()->FETokenInfo; + + case CXXLiteralOperatorName: + return getAsCXXLiteralOperatorIdName()->FETokenInfo; + + default: + llvm_unreachable("Declaration name has no FETokenInfo"); + } +} + +void DeclarationName::setFETokenInfo(void *T) { + switch (getNameKind()) { + case Identifier: + getAsIdentifierInfo()->setFETokenInfo(T); + break; + + case CXXConstructorName: + case CXXDestructorName: + case CXXConversionFunctionName: + getAsCXXSpecialName()->FETokenInfo = T; + break; + + case CXXOperatorName: + getAsCXXOperatorIdName()->FETokenInfo = T; + break; + + case CXXLiteralOperatorName: + getAsCXXLiteralOperatorIdName()->FETokenInfo = T; + break; + + default: + llvm_unreachable("Declaration name has no FETokenInfo"); + } +} + +DeclarationName DeclarationName::getUsingDirectiveName() { + // Single instance of DeclarationNameExtra for using-directive + static const DeclarationNameExtra UDirExtra = + { DeclarationNameExtra::CXXUsingDirective }; + + uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra); + Ptr |= StoredDeclarationNameExtra; + + return DeclarationName(Ptr); +} + +void DeclarationName::dump() const { + printName(llvm::errs()); + llvm::errs() << '\n'; +} + +DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { + CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>; + CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>; + + // Initialize the overloaded operator names. + CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; + for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) { + CXXOperatorNames[Op].ExtraKindOrNumArgs + = Op + DeclarationNameExtra::CXXConversionFunction; + CXXOperatorNames[Op].FETokenInfo = 0; + } +} + +DeclarationNameTable::~DeclarationNameTable() { + llvm::FoldingSet<CXXSpecialName> *SpecialNames = + static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); + llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames + = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*> + (CXXLiteralOperatorNames); + + delete SpecialNames; + delete LiteralNames; +} + +DeclarationName +DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, + CanQualType Ty) { + assert(Kind >= DeclarationName::CXXConstructorName && + Kind <= DeclarationName::CXXConversionFunctionName && + "Kind must be a C++ special name kind"); + llvm::FoldingSet<CXXSpecialName> *SpecialNames + = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); + + DeclarationNameExtra::ExtraKind EKind; + switch (Kind) { + case DeclarationName::CXXConstructorName: + EKind = DeclarationNameExtra::CXXConstructor; + assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified"); + break; + case DeclarationName::CXXDestructorName: + EKind = DeclarationNameExtra::CXXDestructor; + assert(!Ty.hasQualifiers() && "Destructor type must be unqualified"); + break; + case DeclarationName::CXXConversionFunctionName: + EKind = DeclarationNameExtra::CXXConversionFunction; + break; + default: + return DeclarationName(); + } + + // Unique selector, to guarantee there is one per name. + llvm::FoldingSetNodeID ID; + ID.AddInteger(EKind); + ID.AddPointer(Ty.getAsOpaquePtr()); + + void *InsertPos = 0; + if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName(Name); + + CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName; + SpecialName->ExtraKindOrNumArgs = EKind; + SpecialName->Type = Ty; + SpecialName->FETokenInfo = 0; + + SpecialNames->InsertNode(SpecialName, InsertPos); + return DeclarationName(SpecialName); +} + +DeclarationName +DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) { + return DeclarationName(&CXXOperatorNames[(unsigned)Op]); +} + +DeclarationName +DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { + llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames + = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*> + (CXXLiteralOperatorNames); + + llvm::FoldingSetNodeID ID; + ID.AddPointer(II); + + void *InsertPos = 0; + if (CXXLiteralOperatorIdName *Name = + LiteralNames->FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName (Name); + + CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName; + LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; + LiteralName->ID = II; + LiteralName->FETokenInfo = 0; + + LiteralNames->InsertNode(LiteralName, InsertPos); + return DeclarationName(LiteralName); +} + +unsigned +llvm::DenseMapInfo<clang::DeclarationName>:: +getHashValue(clang::DeclarationName N) { + return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr()); +} + +DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + break; + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + NamedType.TInfo = 0; + break; + case DeclarationName::CXXOperatorName: + CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding(); + CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding(); + break; + case DeclarationName::CXXLiteralOperatorName: + CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding(); + break; + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + // FIXME: ? + break; + case DeclarationName::CXXUsingDirective: + break; + } +} + +bool DeclarationNameInfo::containsUnexpandedParameterPack() const { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + return false; + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) + return TInfo->getType()->containsUnexpandedParameterPack(); + + return Name.getCXXNameType()->containsUnexpandedParameterPack(); + } + llvm_unreachable("All name kinds handled."); +} + +bool DeclarationNameInfo::isInstantiationDependent() const { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + return false; + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) + return TInfo->getType()->isInstantiationDependentType(); + + return Name.getCXXNameType()->isInstantiationDependentType(); + } + llvm_unreachable("All name kinds handled."); +} + +std::string DeclarationNameInfo::getAsString() const { + std::string Result; + llvm::raw_string_ostream OS(Result); + printName(OS); + return OS.str(); +} + +void DeclarationNameInfo::printName(raw_ostream &OS) const { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + Name.printName(OS); + return; + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) { + if (Name.getNameKind() == DeclarationName::CXXDestructorName) + OS << '~'; + else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) + OS << "operator "; + OS << TInfo->getType().getAsString(); + } + else + Name.printName(OS); + return; + } + llvm_unreachable("Unexpected declaration name kind"); +} + +SourceLocation DeclarationNameInfo::getEndLoc() const { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + return NameLoc; + + case DeclarationName::CXXOperatorName: { + unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc; + return SourceLocation::getFromRawEncoding(raw); + } + + case DeclarationName::CXXLiteralOperatorName: { + unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc; + return SourceLocation::getFromRawEncoding(raw); + } + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) + return TInfo->getTypeLoc().getEndLoc(); + else + return NameLoc; + + // DNInfo work in progress: FIXME. + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXUsingDirective: + return NameLoc; + } + llvm_unreachable("Unexpected declaration name kind"); +} |