diff options
Diffstat (limited to 'lib/AST/ItaniumMangle.cpp')
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 190 |
1 files changed, 162 insertions, 28 deletions
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 4e7c6c4edf370..f95dc8458e8a8 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -11,7 +11,7 @@ // which is used in GCC 3.2 and newer (and many compilers that are // ABI-compatible with GCC): // -// http://mentorembedded.github.io/cxx-abi/abi.html#mangling +// http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling // //===----------------------------------------------------------------------===// #include "clang/AST/Mangle.h" @@ -381,6 +381,7 @@ class CXXNameMangler { AbiTagState AbiTagsRoot; llvm::DenseMap<uintptr_t, unsigned> Substitutions; + llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -475,6 +476,8 @@ private: void mangleNameWithAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags); + void mangleModuleName(const Module *M); + void mangleModuleNamePrefix(StringRef Name); void mangleTemplateName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); @@ -517,7 +520,7 @@ private: void mangleOperatorName(DeclarationName Name, unsigned Arity); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleVendorQualifier(StringRef qualifier); - void mangleQualifiers(Qualifiers Quals); + void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr); void mangleRefQualifier(RefQualifierKind RefQualifier); void mangleObjCMethodName(const ObjCMethodDecl *MD); @@ -845,9 +848,9 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) { - // <name> ::= <nested-name> - // ::= <unscoped-name> - // ::= <unscoped-template-name> <template-args> + // <name> ::= [<module-name>] <nested-name> + // ::= [<module-name>] <unscoped-name> + // ::= [<module-name>] <unscoped-template-name> <template-args> // ::= <local-name> // const DeclContext *DC = getEffectiveDeclContext(ND); @@ -866,6 +869,19 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, DC = IgnoreLinkageSpecDecls(DC); + if (isLocalContainerContext(DC)) { + mangleLocalName(ND, AdditionalAbiTags); + return; + } + + // Do not mangle the owning module for an external linkage declaration. + // This enables backwards-compatibility with non-modular code, and is + // a valid choice since conflicts are not permitted by C++ Modules TS + // [basic.def.odr]/6.2. + if (!ND->hasExternalFormalLinkage()) + if (Module *M = ND->getOwningModuleForLinkage()) + mangleModuleName(M); + if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; @@ -879,12 +895,42 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, return; } - if (isLocalContainerContext(DC)) { - mangleLocalName(ND, AdditionalAbiTags); + mangleNestedName(ND, DC, AdditionalAbiTags); +} + +void CXXNameMangler::mangleModuleName(const Module *M) { + // Implement the C++ Modules TS name mangling proposal; see + // https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile + // + // <module-name> ::= W <unscoped-name>+ E + // ::= W <module-subst> <unscoped-name>* E + Out << 'W'; + mangleModuleNamePrefix(M->Name); + Out << 'E'; +} + +void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) { + // <module-subst> ::= _ <seq-id> # 0 < seq-id < 10 + // ::= W <seq-id - 10> _ # otherwise + auto It = ModuleSubstitutions.find(Name); + if (It != ModuleSubstitutions.end()) { + if (It->second < 10) + Out << '_' << static_cast<char>('0' + It->second); + else + Out << 'W' << (It->second - 10) << '_'; return; } - mangleNestedName(ND, DC, AdditionalAbiTags); + // FIXME: Preserve hierarchy in module names rather than flattening + // them to strings; use Module*s as substitution keys. + auto Parts = Name.rsplit('.'); + if (Parts.second.empty()) + Parts.second = Parts.first; + else + mangleModuleNamePrefix(Parts.first); + + Out << Parts.second.size() << Parts.second; + ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()}); } void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, @@ -1233,14 +1279,23 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } if (II) { - // We must avoid conflicts between internally- and externally- - // linked variable and function declaration names in the same TU: + // Match GCC's naming convention for internal linkage symbols, for + // symbols that are not actually visible outside of this TU. GCC + // distinguishes between internal and external linkage symbols in + // its mangling, to support cases like this that were valid C++ prior + // to DR426: + // // void test() { extern void foo(); } // static void foo(); - // This naming convention is the same as that followed by GCC, - // though it shouldn't actually matter. + // + // Don't bother with the L marker for names in anonymous namespaces; the + // 12_GLOBAL__N_1 mangling is quite sufficient there, and this better + // matches GCC anyway, because GCC does not treat anonymous namespaces as + // implying internal linkage. if (ND && ND->getFormalLinkage() == InternalLinkage && - getEffectiveDeclContext(ND)->isFileContext()) + !ND->isExternallyVisible() && + getEffectiveDeclContext(ND)->isFileContext() && + !ND->isInAnonymousNamespace()) Out << 'L'; auto *FD = dyn_cast<FunctionDecl>(ND); @@ -1620,6 +1675,10 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { // the symbol in question isn't externally visible. if (!Number) Number = Context.getBlockId(Block, false); + else { + // Stored mangling numbers are 1-based. + --Number; + } Out << "Ub"; if (Number > 0) Out << Number - 1; @@ -1638,10 +1697,15 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // to emit that last part of the prefix here. if (Decl *Context = Lambda->getLambdaContextDecl()) { if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && - Context->getDeclContext()->isRecord()) { + !isa<ParmVarDecl>(Context)) { + // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a + // reasonable mangling here. if (const IdentifierInfo *Name = cast<NamedDecl>(Context)->getIdentifier()) { mangleSourceName(Name); + const TemplateArgumentList *TemplateArgs = nullptr; + if (isTemplate(cast<NamedDecl>(Context), TemplateArgs)) + mangleTemplateArgs(*TemplateArgs); Out << 'M'; } } @@ -1866,6 +1930,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: + case Type::DependentAddressSpace: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -2130,6 +2195,9 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { // Proposal on cxx-abi-dev, 2015-10-21. // ::= aw # co_await case OO_Coawait: Out << "aw"; break; + // Proposed in cxx-abi github issue 43. + // ::= ss # <=> + case OO_Spaceship: Out << "ss"; break; case OO_None: case NUM_OVERLOADED_OPERATORS: @@ -2137,10 +2205,17 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } } -void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { +void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST) { // Vendor qualifiers come first and if they are order-insensitive they must // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. + // <type> ::= U <addrspace-expr> + if (DAST) { + Out << "U2ASI"; + mangleExpression(DAST->getAddrSpaceExpr()); + Out << "E"; + } + // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { // Address space extension: @@ -2150,20 +2225,22 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // <type> ::= U <CUDA-addrspace> SmallString<64> ASString; - unsigned AS = Quals.getAddressSpace(); + LangAS AS = Quals.getAddressSpace(); if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { // <target-addrspace> ::= "AS" <address-space-number> unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); - ASString = "AS" + llvm::utostr(TargetAS); + if (TargetAS != 0) + ASString = "AS" + llvm::utostr(TargetAS); } else { switch (AS) { default: llvm_unreachable("Not a language specific address space"); - // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant | - // "generic" ] + // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" | + // "private"| "generic" ] case LangAS::opencl_global: ASString = "CLglobal"; break; case LangAS::opencl_local: ASString = "CLlocal"; break; case LangAS::opencl_constant: ASString = "CLconstant"; break; + case LangAS::opencl_private: ASString = "CLprivate"; break; case LangAS::opencl_generic: ASString = "CLgeneric"; break; // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ] case LangAS::cuda_device: ASString = "CUdevice"; break; @@ -2171,7 +2248,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { case LangAS::cuda_shared: ASString = "CUshared"; break; } } - mangleVendorQualifier(ASString); + if (!ASString.empty()) + mangleVendorQualifier(ASString); } // The ARC ownership qualifiers start with underscores. @@ -2336,11 +2414,19 @@ void CXXNameMangler::mangleType(QualType T) { // substitution at the original type. } - if (quals) { - mangleQualifiers(quals); - // Recurse: even if the qualified type isn't yet substitutable, - // the unqualified type might be. - mangleType(QualType(ty, 0)); + if (quals || ty->isDependentAddressSpaceType()) { + if (const DependentAddressSpaceType *DAST = + dyn_cast<DependentAddressSpaceType>(ty)) { + SplitQualType splitDAST = DAST->getPointeeType().split(); + mangleQualifiers(splitDAST.Quals, DAST); + mangleType(QualType(splitDAST.Ty, 0)); + } else { + mangleQualifiers(quals); + + // Recurse: even if the qualified type isn't yet substitutable, + // the unqualified type might be. + mangleType(QualType(ty, 0)); + } } else { switch (ty->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) @@ -2392,6 +2478,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) // ::= Dh # IEEE 754r half-precision floating point (16 bits) + // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits); // ::= Di # char32_t // ::= Ds # char16_t // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) @@ -2454,6 +2541,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Int128: Out << 'n'; break; + case BuiltinType::Float16: + Out << "DF16_"; + break; case BuiltinType::Half: Out << "Dh"; break; @@ -2586,6 +2676,9 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) { if (PI.isConsumed()) mangleVendorQualifier("ns_consumed"); + + if (PI.isNoEscape()) + mangleVendorQualifier("noescape"); } // <type> ::= <function-type> @@ -2981,6 +3074,12 @@ void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) { mangleType(T->getElementType()); } +void CXXNameMangler::mangleType(const DependentAddressSpaceType *T) { + SplitQualType split = T->getPointeeType().split(); + mangleQualifiers(split.Quals, T); + mangleType(QualType(split.Ty, 0)); +} + void CXXNameMangler::mangleType(const PackExpansionType *T) { // <type> ::= Dp <type> # pack expansion (C++0x) Out << "Dp"; @@ -3343,7 +3442,6 @@ recurse: case Expr::BlockExprClass: case Expr::ChooseExprClass: case Expr::CompoundLiteralExprClass: - case Expr::DesignatedInitExprClass: case Expr::ExtVectorElementExprClass: case Expr::GenericSelectionExprClass: case Expr::ObjCEncodeExprClass: @@ -3421,6 +3519,27 @@ recurse: break; } + case Expr::DesignatedInitExprClass: { + auto *DIE = cast<DesignatedInitExpr>(E); + for (const auto &Designator : DIE->designators()) { + if (Designator.isFieldDesignator()) { + Out << "di"; + mangleSourceName(Designator.getFieldName()); + } else if (Designator.isArrayDesignator()) { + Out << "dx"; + mangleExpression(DIE->getArrayIndex(Designator)); + } else { + assert(Designator.isArrayRangeDesignator() && + "unknown designator kind"); + Out << "dX"; + mangleExpression(DIE->getArrayRangeStart(Designator)); + mangleExpression(DIE->getArrayRangeEnd(Designator)); + } + } + mangleExpression(DIE->getInit()); + break; + } + case Expr::CXXDefaultArgExprClass: mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity); break; @@ -3512,7 +3631,6 @@ recurse: if (const Expr *Base = PDE->getBase()) mangleMemberExprBase(Base, PDE->isArrow()); NestedNameSpecifier *Qualifier = PDE->getQualifier(); - QualType ScopeType; if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) { if (Qualifier) { mangleUnresolvedPrefix(Qualifier, @@ -3578,6 +3696,16 @@ recurse: const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E); unsigned N = CE->arg_size(); + if (CE->isListInitialization()) { + assert(N == 1 && "unexpected form for list initialization"); + auto *IL = cast<InitListExpr>(CE->getArg(0)); + Out << "tl"; + mangleType(CE->getType()); + mangleInitListElements(IL); + Out << "E"; + return; + } + Out << "cv"; mangleType(CE->getType()); if (N != 1) Out << '_'; @@ -4114,7 +4242,13 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) { // get mangled if used as an rvalue of a known non-class type? assert(!parm->getType()->isArrayType() && "parameter's type is still an array type?"); - mangleQualifiers(parm->getType().getQualifiers()); + + if (const DependentAddressSpaceType *DAST = + dyn_cast<DependentAddressSpaceType>(parm->getType())) { + mangleQualifiers(DAST->getPointeeType().getQualifiers(), DAST); + } else { + mangleQualifiers(parm->getType().getQualifiers()); + } // Parameter index. if (parmIndex != 0) { |