diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/clang/lib/AST/DeclarationName.cpp | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/DeclarationName.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/DeclarationName.cpp | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp b/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp new file mode 100644 index 000000000000..fe69c71aa3dd --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp @@ -0,0 +1,520 @@ +//===- DeclarationName.cpp - Declaration names implementation -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the DeclarationName and DeclarationNameTable +// classes. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <string> + +using namespace clang; + +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.castAsIdentifierInfo(); + IdentifierInfo *RII = RHS.castAsIdentifierInfo(); + 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(); + // getNumArgs for ZeroArgSelector returns 0, but we still need to compare. + if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector && + RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) { + return LHSSelector.getAsIdentifierInfo()->getName().compare( + RHSSelector.getAsIdentifierInfo()->getName()); + } + 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 -1; + case 1: + return 1; + 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::CXXDeductionGuideName: + // We never want to compare deduction guide names for templates from + // different scopes, so just compare the template-name. + return compare(LHS.getCXXDeductionGuideTemplate()->getDeclName(), + RHS.getCXXDeductionGuideTemplate()->getDeclName()); + + 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!"); +} + +static void printCXXConstructorDestructorName(QualType ClassType, + raw_ostream &OS, + PrintingPolicy Policy) { + // We know we're printing C++ here. Ensure we print types properly. + Policy.adjustForCPlusPlus(); + + if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) { + OS << *ClassRec->getDecl(); + return; + } + if (Policy.SuppressTemplateArgsInCXXConstructors) { + if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) { + OS << *InjTy->getDecl(); + return; + } + } + ClassType.print(OS, Policy); +} + +void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { + switch (getNameKind()) { + case DeclarationName::Identifier: + if (const IdentifierInfo *II = getAsIdentifierInfo()) + OS << II->getName(); + return; + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + getObjCSelector().print(OS); + return; + + case DeclarationName::CXXConstructorName: + return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); + + case DeclarationName::CXXDestructorName: + OS << '~'; + return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); + + case DeclarationName::CXXDeductionGuideName: + OS << "<deduction guide for "; + getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy); + OS << '>'; + return; + + case DeclarationName::CXXOperatorName: { + const char *OpName = getOperatorSpelling(getCXXOverloadedOperator()); + assert(OpName && "not an overloaded operator"); + + OS << "operator"; + if (OpName[0] >= 'a' && OpName[0] <= 'z') + OS << ' '; + OS << OpName; + return; + } + + case DeclarationName::CXXLiteralOperatorName: + OS << "operator\"\"" << getCXXLiteralIdentifier()->getName(); + return; + + case DeclarationName::CXXConversionFunctionName: { + OS << "operator "; + QualType Type = getCXXNameType(); + if (const RecordType *Rec = Type->getAs<RecordType>()) { + OS << *Rec->getDecl(); + return; + } + // We know we're printing C++ here, ensure we print 'bool' properly. + PrintingPolicy CXXPolicy = Policy; + CXXPolicy.adjustForCPlusPlus(); + Type.print(OS, CXXPolicy); + return; + } + case DeclarationName::CXXUsingDirective: + OS << "<using-directive>"; + return; + } + + llvm_unreachable("Unexpected declaration name kind"); +} + +namespace clang { + +raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { + LangOptions LO; + N.print(OS, PrintingPolicy(LO)); + return OS; +} + +} // namespace clang + +bool DeclarationName::isDependentName() const { + QualType T = getCXXNameType(); + if (!T.isNull() && T->isDependentType()) + return true; + + // A class-scope deduction guide in a dependent context has a dependent name. + auto *TD = getCXXDeductionGuideTemplate(); + if (TD && TD->getDeclContext()->isDependentContext()) + return true; + + return false; +} + +std::string DeclarationName::getAsString() const { + std::string Result; + llvm::raw_string_ostream OS(Result); + OS << *this; + return OS.str(); +} + +void *DeclarationName::getFETokenInfoSlow() const { + switch (getNameKind()) { + case Identifier: + llvm_unreachable("case Identifier already handled by getFETokenInfo!"); + case CXXConstructorName: + case CXXDestructorName: + case CXXConversionFunctionName: + return castAsCXXSpecialNameExtra()->FETokenInfo; + case CXXOperatorName: + return castAsCXXOperatorIdName()->FETokenInfo; + case CXXDeductionGuideName: + return castAsCXXDeductionGuideNameExtra()->FETokenInfo; + case CXXLiteralOperatorName: + return castAsCXXLiteralOperatorIdName()->FETokenInfo; + default: + llvm_unreachable("DeclarationName has no FETokenInfo!"); + } +} + +void DeclarationName::setFETokenInfoSlow(void *T) { + switch (getNameKind()) { + case Identifier: + llvm_unreachable("case Identifier already handled by setFETokenInfo!"); + case CXXConstructorName: + case CXXDestructorName: + case CXXConversionFunctionName: + castAsCXXSpecialNameExtra()->FETokenInfo = T; + break; + case CXXOperatorName: + castAsCXXOperatorIdName()->FETokenInfo = T; + break; + case CXXDeductionGuideName: + castAsCXXDeductionGuideNameExtra()->FETokenInfo = T; + break; + case CXXLiteralOperatorName: + castAsCXXLiteralOperatorIdName()->FETokenInfo = T; + break; + default: + llvm_unreachable("DeclarationName has no FETokenInfo!"); + } +} + +LLVM_DUMP_METHOD void DeclarationName::dump() const { + llvm::errs() << *this << '\n'; +} + +DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { + // Initialize the overloaded operator names. + for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) + CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op); +} + +DeclarationName +DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) { + Template = cast<TemplateDecl>(Template->getCanonicalDecl()); + + llvm::FoldingSetNodeID ID; + ID.AddPointer(Template); + + void *InsertPos = nullptr; + if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName(Name); + + auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template); + CXXDeductionGuideNames.InsertNode(Name, InsertPos); + return DeclarationName(Name); +} + +DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { + // The type of constructors is unqualified. + Ty = Ty.getUnqualifiedType(); + // Do we already have this C++ constructor name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXConstructorName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXConstructorNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXConstructorName}; +} + +DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { + // The type of destructors is unqualified. + Ty = Ty.getUnqualifiedType(); + // Do we already have this C++ destructor name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXDestructorName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXDestructorNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXDestructorName}; +} + +DeclarationName +DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) { + // Do we already have this C++ conversion function name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = + CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXConversionFunctionName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXConversionFunctionName}; +} + +DeclarationName +DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, + CanQualType Ty) { + switch (Kind) { + case DeclarationName::CXXConstructorName: + return getCXXConstructorName(Ty); + case DeclarationName::CXXDestructorName: + return getCXXDestructorName(Ty); + case DeclarationName::CXXConversionFunctionName: + return getCXXConversionFunctionName(Ty); + default: + llvm_unreachable("Invalid kind in getCXXSpecialName!"); + } +} + +DeclarationName +DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { + llvm::FoldingSetNodeID ID; + ID.AddPointer(II); + + void *InsertPos = nullptr; + if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName(Name); + + auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II); + CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos); + return DeclarationName(LiteralName); +} + +DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::CXXDeductionGuideName: + break; + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + NamedType.TInfo = nullptr; + 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: + case DeclarationName::CXXDeductionGuideName: + 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: + case DeclarationName::CXXDeductionGuideName: + 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: + case DeclarationName::CXXDeductionGuideName: + OS << Name; + 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 "; + LangOptions LO; + LO.CPlusPlus = true; + LO.Bool = true; + PrintingPolicy PP(LO); + PP.SuppressScope = true; + OS << TInfo->getType().getAsString(PP); + } else + OS << Name; + return; + } + llvm_unreachable("Unexpected declaration name kind"); +} + +SourceLocation DeclarationNameInfo::getEndLocPrivate() const { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::CXXDeductionGuideName: + 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"); +} |