123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- //===-- 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 "clang/Basic/PartialDiagnostic.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;
- };
- /// CXXLiberalOperatorName - 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;
- 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 getCXXLiteralIdentifier()->getFETokenInfo<void>();
- 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:
- getCXXLiteralIdentifier()->setFETokenInfo(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;
- 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");
- }
- const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
- DeclarationName N) {
- DB.AddTaggedVal(N.getAsOpaqueInteger(),
- DiagnosticsEngine::ak_declarationname);
- return DB;
- }
- const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &PD,
- DeclarationName N) {
- PD.AddTaggedVal(N.getAsOpaqueInteger(),
- DiagnosticsEngine::ak_declarationname);
- return PD;
- }
|