aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp1388
1 files changed, 1121 insertions, 267 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp
index 8b1419074df5..5cad84a96845 100644
--- a/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp
@@ -125,11 +125,12 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+ bool IsDevCtx = false;
+
public:
explicit ItaniumMangleContextImpl(ASTContext &Context,
- DiagnosticsEngine &Diags,
- bool IsUniqueNameMangler)
- : ItaniumMangleContext(Context, Diags, IsUniqueNameMangler) {}
+ DiagnosticsEngine &Diags)
+ : ItaniumMangleContext(Context, Diags) {}
/// @name Mangler Entry Points
/// @{
@@ -138,6 +139,10 @@ public:
bool shouldMangleStringLiteral(const StringLiteral *) override {
return false;
}
+
+ bool isDeviceMangleContext() const override { return IsDevCtx; }
+ void setDeviceMangleContext(bool IsDev) override { IsDevCtx = IsDev; }
+
void mangleCXXName(GlobalDecl GD, raw_ostream &) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
@@ -480,8 +485,6 @@ private:
const AbiTagList *AdditionalAbiTags);
void mangleUnscopedTemplateName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
- void mangleUnscopedTemplateName(TemplateName,
- const AbiTagList *AdditionalAbiTags);
void mangleSourceName(const IdentifierInfo *II);
void mangleRegCallName(const IdentifierInfo *II);
void mangleDeviceStubName(const IdentifierInfo *II);
@@ -531,8 +534,14 @@ private:
void mangleNeonVectorType(const DependentVectorType *T);
void mangleAArch64NeonVectorType(const VectorType *T);
void mangleAArch64NeonVectorType(const DependentVectorType *T);
+ void mangleAArch64FixedSveVectorType(const VectorType *T);
+ void mangleAArch64FixedSveVectorType(const DependentVectorType *T);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
+ void mangleFloatLiteral(QualType T, const llvm::APFloat &V);
+ void mangleFixedPointLiteral();
+ void mangleNullPointer(QualType T);
+
void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
@@ -543,17 +552,21 @@ private:
unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
- void mangleDeclRefExpr(const NamedDecl *D);
- void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
+ void mangleExpression(const Expr *E, unsigned Arity = UnknownArity,
+ bool AsTemplateArg = false);
void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom);
void mangleCXXDtorType(CXXDtorType T);
- void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
+ void mangleTemplateArgs(TemplateName TN,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs);
- void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
+ void mangleTemplateArgs(TemplateName TN, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
- void mangleTemplateArgs(const TemplateArgumentList &AL);
- void mangleTemplateArg(TemplateArgument A);
+ void mangleTemplateArgs(TemplateName TN, const TemplateArgumentList &AL);
+ void mangleTemplateArg(TemplateArgument A, bool NeedExactType);
+ void mangleTemplateArgExpr(const Expr *E);
+ void mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel,
+ bool NeedExactType = false);
void mangleTemplateParameter(unsigned Depth, unsigned Index);
@@ -648,15 +661,12 @@ void CXXNameMangler::mangle(GlobalDecl GD) {
Out << "_Z";
if (isa<FunctionDecl>(GD.getDecl()))
mangleFunctionEncoding(GD);
- else if (const VarDecl *VD = dyn_cast<VarDecl>(GD.getDecl()))
- mangleName(VD);
+ else if (isa<VarDecl, FieldDecl, MSGuidDecl, TemplateParamObjectDecl,
+ BindingDecl>(GD.getDecl()))
+ mangleName(GD);
else if (const IndirectFieldDecl *IFD =
dyn_cast<IndirectFieldDecl>(GD.getDecl()))
mangleName(IFD->getAnonField());
- else if (const FieldDecl *FD = dyn_cast<FieldDecl>(GD.getDecl()))
- mangleName(FD);
- else if (const MSGuidDecl *GuidD = dyn_cast<MSGuidDecl>(GD.getDecl()))
- mangleName(GuidD);
else
llvm_unreachable("unexpected kind of global decl");
}
@@ -723,9 +733,17 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
EnableIfAttr *EIA = dyn_cast<EnableIfAttr>(*I);
if (!EIA)
continue;
- Out << 'X';
- mangleExpression(EIA->getCond());
- Out << 'E';
+ if (Context.getASTContext().getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver11) {
+ mangleTemplateArgExpr(EIA->getCond());
+ } else {
+ // Prior to Clang 12, we hardcoded the X/E around enable-if's argument,
+ // even though <template-arg> should not include an X/E around
+ // <expr-primary>.
+ Out << 'X';
+ mangleExpression(EIA->getCond());
+ Out << 'E';
+ }
}
Out << 'E';
FunctionTypeDepth.pop(Saved);
@@ -822,6 +840,11 @@ isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) {
return GlobalDecl();
}
+static TemplateName asTemplateName(GlobalDecl GD) {
+ const TemplateDecl *TD = dyn_cast_or_null<TemplateDecl>(GD.getDecl());
+ return TemplateName(const_cast<TemplateDecl*>(TD));
+}
+
void CXXNameMangler::mangleName(GlobalDecl GD) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
@@ -898,7 +921,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
const TemplateArgumentList *TemplateArgs = nullptr;
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
mangleUnscopedTemplateName(TD, AdditionalAbiTags);
- mangleTemplateArgs(*TemplateArgs);
+ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
return;
}
@@ -951,7 +974,7 @@ void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
mangleUnscopedTemplateName(TD, nullptr);
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
+ mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs);
} else {
mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
}
@@ -991,29 +1014,6 @@ void CXXNameMangler::mangleUnscopedTemplateName(
addSubstitution(ND);
}
-void CXXNameMangler::mangleUnscopedTemplateName(
- TemplateName Template, const AbiTagList *AdditionalAbiTags) {
- // <unscoped-template-name> ::= <unscoped-name>
- // ::= <substitution>
- if (TemplateDecl *TD = Template.getAsTemplateDecl())
- return mangleUnscopedTemplateName(TD, AdditionalAbiTags);
-
- if (mangleSubstitution(Template))
- return;
-
- assert(!AdditionalAbiTags &&
- "dependent template name cannot have abi tags");
-
- DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
- assert(Dependent && "Not a dependent template name?");
- if (const IdentifierInfo *Id = Dependent->getIdentifier())
- mangleSourceName(Id);
- else
- mangleOperatorName(Dependent->getOperator(), UnknownArity);
-
- addSubstitution(Template);
-}
-
void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
// ABI:
// Floating-point literals are encoded using a fixed-length
@@ -1056,6 +1056,27 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
Out.write(buffer.data(), numCharacters);
}
+void CXXNameMangler::mangleFloatLiteral(QualType T, const llvm::APFloat &V) {
+ Out << 'L';
+ mangleType(T);
+ mangleFloat(V);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleFixedPointLiteral() {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot mangle fixed point literals yet");
+ Diags.Report(DiagID);
+}
+
+void CXXNameMangler::mangleNullPointer(QualType T) {
+ // <expr-primary> ::= L <type> 0 E
+ Out << 'L';
+ mangleType(T);
+ Out << "0E";
+}
+
void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
if (Value.isSigned() && Value.isNegative()) {
Out << 'n';
@@ -1103,7 +1124,8 @@ void CXXNameMangler::manglePrefix(QualType type) {
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
- mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
+ mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(),
+ TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
} else if (const auto *DTST =
@@ -1116,7 +1138,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
- mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
addSubstitution(QualType(DTST, 0));
}
} else {
@@ -1259,7 +1281,7 @@ void CXXNameMangler::mangleUnresolvedName(
// The <simple-id> and on <operator-name> productions end in an optional
// <template-args>.
if (TemplateArgs)
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
+ mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs);
}
void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
@@ -1302,6 +1324,14 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
break;
}
+ if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
+ // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63.
+ Out << "TA";
+ mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(),
+ TPO->getValue(), /*TopLevel=*/true);
+ break;
+ }
+
if (II) {
// Match GCC's naming convention for internal linkage symbols, for
// symbols that are not actually visible outside of this TU. GCC
@@ -1409,8 +1439,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
// <lambda-sig> ::= <template-param-decl>* <parameter-type>+
// # Parameter types or 'v' for 'void'.
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
- if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
- Context.isUniqueNameMangler())) {
+ if (Record->isLambda() && Record->getLambdaManglingNumber()) {
assert(!AdditionalAbiTags &&
"Lambda type cannot have additional abi tags");
mangleLambda(Record);
@@ -1451,10 +1480,13 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
case DeclarationName::CXXConstructorName: {
const CXXRecordDecl *InheritedFrom = nullptr;
+ TemplateName InheritedTemplateName;
const TemplateArgumentList *InheritedTemplateArgs = nullptr;
if (auto Inherited =
cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) {
InheritedFrom = Inherited.getConstructor()->getParent();
+ InheritedTemplateName =
+ TemplateName(Inherited.getConstructor()->getPrimaryTemplate());
InheritedTemplateArgs =
Inherited.getConstructor()->getTemplateSpecializationArgs();
}
@@ -1471,7 +1503,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
// FIXME: The template arguments are part of the enclosing prefix or
// nested-name, but it's more convenient to mangle them here.
if (InheritedTemplateArgs)
- mangleTemplateArgs(*InheritedTemplateArgs);
+ mangleTemplateArgs(InheritedTemplateName, *InheritedTemplateArgs);
writeAbiTags(ND, AdditionalAbiTags);
break;
@@ -1560,7 +1592,7 @@ void CXXNameMangler::mangleNestedName(GlobalDecl GD,
const TemplateArgumentList *TemplateArgs = nullptr;
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
mangleTemplatePrefix(TD, NoFunction);
- mangleTemplateArgs(*TemplateArgs);
+ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
}
else {
manglePrefix(DC, NoFunction);
@@ -1577,7 +1609,7 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
Out << 'N';
mangleTemplatePrefix(TD);
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
+ mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs);
Out << 'E';
}
@@ -1785,37 +1817,6 @@ void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) {
}
}
-// Handles the __builtin_unique_stable_name feature for lambdas. Instead of the
-// ordinal of the lambda in its mangling, this does line/column to uniquely and
-// reliably identify the lambda. Additionally, macro expansions are expressed
-// as well to prevent macros causing duplicates.
-static void mangleUniqueNameLambda(CXXNameMangler &Mangler, SourceManager &SM,
- raw_ostream &Out,
- const CXXRecordDecl *Lambda) {
- SourceLocation Loc = Lambda->getLocation();
-
- PresumedLoc PLoc = SM.getPresumedLoc(Loc);
- Mangler.mangleNumber(PLoc.getLine());
- Out << "_";
- Mangler.mangleNumber(PLoc.getColumn());
-
- while(Loc.isMacroID()) {
- SourceLocation SLToPrint = Loc;
- if (SM.isMacroArgExpansion(Loc))
- SLToPrint = SM.getImmediateExpansionRange(Loc).getBegin();
-
- PLoc = SM.getPresumedLoc(SM.getSpellingLoc(SLToPrint));
- Out << "m";
- Mangler.mangleNumber(PLoc.getLine());
- Out << "_";
- Mangler.mangleNumber(PLoc.getColumn());
-
- Loc = SM.getImmediateMacroCallerLoc(Loc);
- if (Loc.isFileID())
- Loc = SM.getImmediateMacroCallerLoc(SLToPrint);
- }
-}
-
void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
// If the context of a closure type is an initializer for a class member
// (static or nonstatic), it is encoded in a qualified name with a final
@@ -1835,8 +1836,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
= cast<NamedDecl>(Context)->getIdentifier()) {
mangleSourceName(Name);
const TemplateArgumentList *TemplateArgs = nullptr;
- if (isTemplate(cast<NamedDecl>(Context), TemplateArgs))
- mangleTemplateArgs(*TemplateArgs);
+ if (GlobalDecl TD = isTemplate(cast<NamedDecl>(Context), TemplateArgs))
+ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
Out << 'M';
}
}
@@ -1846,18 +1847,20 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
mangleLambdaSig(Lambda);
Out << "E";
- if (Context.isUniqueNameMangler()) {
- mangleUniqueNameLambda(
- *this, Context.getASTContext().getSourceManager(), Out, Lambda);
- return;
- }
-
// The number is omitted for the first closure type with a given
// <lambda-sig> in a given context; it is n-2 for the nth closure type
// (in lexical order) with that same <lambda-sig> and context.
//
// The AST keeps track of the number for us.
- unsigned Number = Lambda->getLambdaManglingNumber();
+ //
+ // In CUDA/HIP, to ensure the consistent lamba numbering between the device-
+ // and host-side compilations, an extra device mangle context may be created
+ // if the host-side CXX ABI has different numbering for lambda. In such case,
+ // if the mangle context is that device-side one, use the device-side lambda
+ // mangling number for this lambda.
+ unsigned Number = Context.isDeviceMangleContext()
+ ? Lambda->getDeviceLambdaManglingNumber()
+ : Lambda->getLambdaManglingNumber();
assert(Number > 0 && "Lambda should be mangled as an unnamed class");
if (Number > 1)
mangleNumber(Number - 2);
@@ -1933,7 +1936,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
const TemplateArgumentList *TemplateArgs = nullptr;
if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
- mangleTemplateArgs(*TemplateArgs);
+ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
} else {
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
mangleUnqualifiedName(ND, nullptr);
@@ -1949,21 +1952,28 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
if (TemplateDecl *TD = Template.getAsTemplateDecl())
return mangleTemplatePrefix(TD);
- if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
- manglePrefix(Qualified->getQualifier());
+ DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
+ assert(Dependent && "unexpected template name kind");
- if (OverloadedTemplateStorage *Overloaded
- = Template.getAsOverloadedTemplate()) {
- mangleUnqualifiedName(GlobalDecl(), (*Overloaded->begin())->getDeclName(),
- UnknownArity, nullptr);
+ // Clang 11 and before mangled the substitution for a dependent template name
+ // after already having emitted (a substitution for) the prefix.
+ bool Clang11Compat = getASTContext().getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver11;
+ if (!Clang11Compat && mangleSubstitution(Template))
return;
- }
- DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
- assert(Dependent && "Unknown template name kind?");
if (NestedNameSpecifier *Qualifier = Dependent->getQualifier())
manglePrefix(Qualifier);
- mangleUnscopedTemplateName(Template, /* AdditionalAbiTags */ nullptr);
+
+ if (Clang11Compat && mangleSubstitution(Template))
+ return;
+
+ if (const IdentifierInfo *Id = Dependent->getIdentifier())
+ mangleSourceName(Id);
+ else
+ mangleOperatorName(Dependent->getOperator(), UnknownArity);
+
+ addSubstitution(Template);
}
void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD,
@@ -2185,7 +2195,12 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
}
}
- mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
+ // Note: we don't pass in the template name here. We are mangling the
+ // original source-level template arguments, so we shouldn't consider
+ // conversions to the corresponding template parameter.
+ // FIXME: Other compilers mangle partially-resolved template arguments in
+ // unresolved-qualifier-levels.
+ mangleTemplateArgs(TemplateName(), TST->getArgs(), TST->getNumArgs());
break;
}
@@ -2201,8 +2216,10 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::DependentTemplateSpecialization: {
const DependentTemplateSpecializationType *DTST =
cast<DependentTemplateSpecializationType>(Ty);
+ TemplateName Template = getASTContext().getDependentTemplateName(
+ DTST->getQualifier(), DTST->getIdentifier());
mangleSourceName(DTST->getIdentifier());
- mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
break;
}
@@ -2388,16 +2405,39 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
switch (AS) {
default: llvm_unreachable("Not a language specific address space");
// <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;
+ // "private"| "generic" | "device" |
+ // "host" ]
+ case LangAS::opencl_global:
+ ASString = "CLglobal";
+ break;
+ case LangAS::opencl_global_device:
+ ASString = "CLdevice";
+ break;
+ case LangAS::opencl_global_host:
+ ASString = "CLhost";
+ 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;
- case LangAS::cuda_constant: ASString = "CUconstant"; break;
- case LangAS::cuda_shared: ASString = "CUshared"; break;
+ case LangAS::cuda_device:
+ ASString = "CUdevice";
+ break;
+ case LangAS::cuda_constant:
+ ASString = "CUconstant";
+ break;
+ case LangAS::cuda_shared:
+ ASString = "CUshared";
+ break;
// <ptrsize-addrspace> ::= [ "ptr32_sptr" | "ptr32_uptr" | "ptr64" ]
case LangAS::ptr32_sptr:
ASString = "ptr32_sptr";
@@ -2489,7 +2529,7 @@ void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
}
void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
- Context.mangleObjCMethodName(MD, Out);
+ Context.mangleObjCMethodNameAsSourceName(MD, Out);
}
static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty,
@@ -2507,6 +2547,12 @@ static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty,
if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver6 &&
isa<AutoType>(Ty))
return false;
+ // A placeholder type for class template deduction is substitutable with
+ // its corresponding template name; this is handled specially when mangling
+ // the type.
+ if (auto *DeducedTST = Ty->getAs<DeducedTemplateSpecializationType>())
+ if (DeducedTST->getDeducedType().isNull())
+ return false;
return true;
}
@@ -2555,6 +2601,10 @@ void CXXNameMangler::mangleType(QualType T) {
if (!TST->isTypeAlias())
break;
+ // FIXME: We presumably shouldn't strip off ElaboratedTypes with
+ // instantation-dependent qualifiers. See
+ // https://github.com/itanium-cxx-abi/cxx-abi/issues/114.
+
QualType Desugared
= T.getSingleStepDesugaredType(Context.getASTContext());
if (Desugared == T)
@@ -2835,6 +2885,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
<< type_name; \
break;
#include "clang/Basic/AArch64SVEACLETypes.def"
+#define PPC_VECTOR_TYPE(Name, Id, Size) \
+ case BuiltinType::Id: \
+ type_name = #Name; \
+ Out << 'u' << type_name.size() << type_name; \
+ break;
+#include "clang/Basic/PPCTypes.def"
}
}
@@ -3298,6 +3354,103 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) {
Diags.Report(T->getAttributeLoc(), DiagID);
}
+// The AArch64 ACLE specifies that fixed-length SVE vector and predicate types
+// defined with the 'arm_sve_vector_bits' attribute map to the same AAPCS64
+// type as the sizeless variants.
+//
+// The mangling scheme for VLS types is implemented as a "pseudo" template:
+//
+// '__SVE_VLS<<type>, <vector length>>'
+//
+// Combining the existing SVE type and a specific vector length (in bits).
+// For example:
+//
+// typedef __SVInt32_t foo __attribute__((arm_sve_vector_bits(512)));
+//
+// is described as '__SVE_VLS<__SVInt32_t, 512u>' and mangled as:
+//
+// "9__SVE_VLSI" + base type mangling + "Lj" + __ARM_FEATURE_SVE_BITS + "EE"
+//
+// i.e. 9__SVE_VLSIu11__SVInt32_tLj512EE
+//
+// The latest ACLE specification (00bet5) does not contain details of this
+// mangling scheme, it will be specified in the next revision. The mangling
+// scheme is otherwise defined in the appendices to the Procedure Call Standard
+// for the Arm Architecture, see
+// https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst#appendix-c-mangling
+void CXXNameMangler::mangleAArch64FixedSveVectorType(const VectorType *T) {
+ assert((T->getVectorKind() == VectorType::SveFixedLengthDataVector ||
+ T->getVectorKind() == VectorType::SveFixedLengthPredicateVector) &&
+ "expected fixed-length SVE vector!");
+
+ QualType EltType = T->getElementType();
+ assert(EltType->isBuiltinType() &&
+ "expected builtin type for fixed-length SVE vector!");
+
+ StringRef TypeName;
+ switch (cast<BuiltinType>(EltType)->getKind()) {
+ case BuiltinType::SChar:
+ TypeName = "__SVInt8_t";
+ break;
+ case BuiltinType::UChar: {
+ if (T->getVectorKind() == VectorType::SveFixedLengthDataVector)
+ TypeName = "__SVUint8_t";
+ else
+ TypeName = "__SVBool_t";
+ break;
+ }
+ case BuiltinType::Short:
+ TypeName = "__SVInt16_t";
+ break;
+ case BuiltinType::UShort:
+ TypeName = "__SVUint16_t";
+ break;
+ case BuiltinType::Int:
+ TypeName = "__SVInt32_t";
+ break;
+ case BuiltinType::UInt:
+ TypeName = "__SVUint32_t";
+ break;
+ case BuiltinType::Long:
+ TypeName = "__SVInt64_t";
+ break;
+ case BuiltinType::ULong:
+ TypeName = "__SVUint64_t";
+ break;
+ case BuiltinType::Half:
+ TypeName = "__SVFloat16_t";
+ break;
+ case BuiltinType::Float:
+ TypeName = "__SVFloat32_t";
+ break;
+ case BuiltinType::Double:
+ TypeName = "__SVFloat64_t";
+ break;
+ case BuiltinType::BFloat16:
+ TypeName = "__SVBfloat16_t";
+ break;
+ default:
+ llvm_unreachable("unexpected element type for fixed-length SVE vector!");
+ }
+
+ unsigned VecSizeInBits = getASTContext().getTypeInfo(T).Width;
+
+ if (T->getVectorKind() == VectorType::SveFixedLengthPredicateVector)
+ VecSizeInBits *= 8;
+
+ Out << "9__SVE_VLSI" << 'u' << TypeName.size() << TypeName << "Lj"
+ << VecSizeInBits << "EE";
+}
+
+void CXXNameMangler::mangleAArch64FixedSveVectorType(
+ const DependentVectorType *T) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this dependent fixed-length SVE vector type yet");
+ Diags.Report(T->getAttributeLoc(), DiagID);
+}
+
// GNU extension: vector types
// <type> ::= <vector-type>
// <vector-type> ::= Dv <positive dimension number> _
@@ -3318,6 +3471,10 @@ void CXXNameMangler::mangleType(const VectorType *T) {
else
mangleNeonVectorType(T);
return;
+ } else if (T->getVectorKind() == VectorType::SveFixedLengthDataVector ||
+ T->getVectorKind() == VectorType::SveFixedLengthPredicateVector) {
+ mangleAArch64FixedSveVectorType(T);
+ return;
}
Out << "Dv" << T->getNumElements() << '_';
if (T->getVectorKind() == VectorType::AltiVecPixel)
@@ -3340,6 +3497,10 @@ void CXXNameMangler::mangleType(const DependentVectorType *T) {
else
mangleNeonVectorType(T);
return;
+ } else if (T->getVectorKind() == VectorType::SveFixedLengthDataVector ||
+ T->getVectorKind() == VectorType::SveFixedLengthPredicateVector) {
+ mangleAArch64FixedSveVectorType(T);
+ return;
}
Out << "Dv";
@@ -3364,10 +3525,13 @@ void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
}
void CXXNameMangler::mangleType(const ConstantMatrixType *T) {
- // Mangle matrix types using a vendor extended type qualifier:
- // U<Len>matrix_type<Rows><Columns><element type>
+ // Mangle matrix types as a vendor extended type:
+ // u<Len>matrix_typeI<Rows><Columns><element type>E
+
StringRef VendorQualifier = "matrix_type";
- Out << "U" << VendorQualifier.size() << VendorQualifier;
+ Out << "u" << VendorQualifier.size() << VendorQualifier;
+
+ Out << "I";
auto &ASTCtx = getASTContext();
unsigned BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType());
llvm::APSInt Rows(BitWidth);
@@ -3377,15 +3541,20 @@ void CXXNameMangler::mangleType(const ConstantMatrixType *T) {
Columns = T->getNumColumns();
mangleIntegerLiteral(ASTCtx.getSizeType(), Columns);
mangleType(T->getElementType());
+ Out << "E";
}
void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) {
- // U<Len>matrix_type<row expr><column expr><element type>
+ // Mangle matrix types as a vendor extended type:
+ // u<Len>matrix_typeI<row expr><column expr><element type>E
StringRef VendorQualifier = "matrix_type";
- Out << "U" << VendorQualifier.size() << VendorQualifier;
- mangleTemplateArg(T->getRowExpr());
- mangleTemplateArg(T->getColumnExpr());
+ Out << "u" << VendorQualifier.size() << VendorQualifier;
+
+ Out << "I";
+ mangleTemplateArgExpr(T->getRowExpr());
+ mangleTemplateArgExpr(T->getColumnExpr());
mangleType(T->getElementType());
+ Out << "E";
}
void CXXNameMangler::mangleType(const DependentAddressSpaceType *T) {
@@ -3456,7 +3625,7 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
- mangleTemplateArgs(T->getArgs(), T->getNumArgs());
+ mangleTemplateArgs(T->getTemplateName(), T->getArgs(), T->getNumArgs());
addSubstitution(QualType(T, 0));
}
}
@@ -3508,7 +3677,7 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
// FIXME: GCC does not appear to mangle the template arguments when
// the template in question is a dependent template name. Should we
// emulate that badness?
- mangleTemplateArgs(T->getArgs(), T->getNumArgs());
+ mangleTemplateArgs(Prefix, T->getArgs(), T->getNumArgs());
Out << 'E';
}
@@ -3575,13 +3744,18 @@ void CXXNameMangler::mangleType(const AutoType *T) {
}
void CXXNameMangler::mangleType(const DeducedTemplateSpecializationType *T) {
- // FIXME: This is not the right mangling. We also need to include a scope
- // here in some cases.
- QualType D = T->getDeducedType();
- if (D.isNull())
- mangleUnscopedTemplateName(T->getTemplateName(), nullptr);
- else
- mangleType(D);
+ QualType Deduced = T->getDeducedType();
+ if (!Deduced.isNull())
+ return mangleType(Deduced);
+
+ TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl();
+ assert(TD && "shouldn't form deduced TST unless we know we have a template");
+
+ if (mangleSubstitution(TD))
+ return;
+
+ mangleName(GlobalDecl(TD));
+ addSubstitution(TD);
}
void CXXNameMangler::mangleType(const AtomicType *T) {
@@ -3603,7 +3777,7 @@ void CXXNameMangler::mangleType(const ExtIntType *T) {
llvm::APSInt BW(32, true);
BW = T->getNumBits();
TemplateArgument TA(Context.getASTContext(), BW, getASTContext().IntTy);
- mangleTemplateArgs(&TA, 1);
+ mangleTemplateArgs(TemplateName(), &TA, 1);
if (T->isUnsigned())
Out << "j";
else
@@ -3613,7 +3787,7 @@ void CXXNameMangler::mangleType(const ExtIntType *T) {
void CXXNameMangler::mangleType(const DependentExtIntType *T) {
Out << "U7_ExtInt";
TemplateArgument TA(T->getNumBitsExpr());
- mangleTemplateArgs(&TA, 1);
+ mangleTemplateArgs(TemplateName(), &TA, 1);
if (T->isUnsigned())
Out << "j";
else
@@ -3720,33 +3894,8 @@ void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) {
mangleExpression(InitList->getInit(i));
}
-void CXXNameMangler::mangleDeclRefExpr(const NamedDecl *D) {
- switch (D->getKind()) {
- default:
- // <expr-primary> ::= L <mangled-name> E # external name
- Out << 'L';
- mangle(D);
- Out << 'E';
- break;
-
- case Decl::ParmVar:
- mangleFunctionParam(cast<ParmVarDecl>(D));
- break;
-
- case Decl::EnumConstant: {
- const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
- mangleIntegerLiteral(ED->getType(), ED->getInitVal());
- break;
- }
-
- case Decl::NonTypeTemplateParm:
- const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
- mangleTemplateParameter(PD->getDepth(), PD->getIndex());
- break;
- }
-}
-
-void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
+void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
+ bool AsTemplateArg) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <trinary operator-name> <expression> <expression> <expression>
@@ -3760,18 +3909,64 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// ::= at <type> # alignof (a type)
// ::= <template-param>
// ::= <function-param>
+ // ::= fpT # 'this' expression (part of <function-param>)
// ::= sr <type> <unqualified-name> # dependent name
// ::= sr <type> <unqualified-name> <template-args> # dependent template-id
// ::= ds <expression> <expression> # expr.*expr
// ::= sZ <template-param> # size of a parameter pack
// ::= sZ <function-param> # size of a function parameter pack
+ // ::= u <source-name> <template-arg>* E # vendor extended expression
// ::= <expr-primary>
// <expr-primary> ::= L <type> <value number> E # integer literal
- // ::= L <type <value float> E # floating literal
+ // ::= L <type> <value float> E # floating literal
+ // ::= L <type> <string type> E # string literal
+ // ::= L <nullptr type> E # nullptr literal "LDnE"
+ // ::= L <pointer type> 0 E # null pointer template argument
+ // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C99); not used by clang
// ::= L <mangled-name> E # external name
- // ::= fpT # 'this' expression
QualType ImplicitlyConvertedToType;
+ // A top-level expression that's not <expr-primary> needs to be wrapped in
+ // X...E in a template arg.
+ bool IsPrimaryExpr = true;
+ auto NotPrimaryExpr = [&] {
+ if (AsTemplateArg && IsPrimaryExpr)
+ Out << 'X';
+ IsPrimaryExpr = false;
+ };
+
+ auto MangleDeclRefExpr = [&](const NamedDecl *D) {
+ switch (D->getKind()) {
+ default:
+ // <expr-primary> ::= L <mangled-name> E # external name
+ Out << 'L';
+ mangle(D);
+ Out << 'E';
+ break;
+
+ case Decl::ParmVar:
+ NotPrimaryExpr();
+ mangleFunctionParam(cast<ParmVarDecl>(D));
+ break;
+
+ case Decl::EnumConstant: {
+ // <expr-primary>
+ const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
+ mangleIntegerLiteral(ED->getType(), ED->getInitVal());
+ break;
+ }
+
+ case Decl::NonTypeTemplateParm:
+ NotPrimaryExpr();
+ const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
+ mangleTemplateParameter(PD->getDepth(), PD->getIndex());
+ break;
+ }
+ };
+
+ // 'goto recurse' is used when handling a simple "unwrapping" node which
+ // produces no output, where ImplicitlyConvertedToType and AsTemplateArg need
+ // to be preserved.
recurse:
switch (E->getStmtClass()) {
case Expr::NoStmtClass:
@@ -3841,9 +4036,9 @@ recurse:
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
case Expr::SourceLocExprClass:
- case Expr::FixedPointLiteralClass:
case Expr::BuiltinBitCastExprClass:
{
+ NotPrimaryExpr();
if (!NullOut) {
// As bad as this diagnostic is, it's better than crashing.
DiagnosticsEngine &Diags = Context.getDiags();
@@ -3851,33 +4046,48 @@ recurse:
"cannot yet mangle expression type %0");
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
+ return;
}
break;
}
case Expr::CXXUuidofExprClass: {
+ NotPrimaryExpr();
const CXXUuidofExpr *UE = cast<CXXUuidofExpr>(E);
- if (UE->isTypeOperand()) {
- QualType UuidT = UE->getTypeOperand(Context.getASTContext());
- Out << "u8__uuidoft";
- mangleType(UuidT);
+ // As of clang 12, uuidof uses the vendor extended expression
+ // mangling. Previously, it used a special-cased nonstandard extension.
+ if (Context.getASTContext().getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver11) {
+ Out << "u8__uuidof";
+ if (UE->isTypeOperand())
+ mangleType(UE->getTypeOperand(Context.getASTContext()));
+ else
+ mangleTemplateArgExpr(UE->getExprOperand());
+ Out << 'E';
} else {
- Expr *UuidExp = UE->getExprOperand();
- Out << "u8__uuidofz";
- mangleExpression(UuidExp, Arity);
+ if (UE->isTypeOperand()) {
+ QualType UuidT = UE->getTypeOperand(Context.getASTContext());
+ Out << "u8__uuidoft";
+ mangleType(UuidT);
+ } else {
+ Expr *UuidExp = UE->getExprOperand();
+ Out << "u8__uuidofz";
+ mangleExpression(UuidExp);
+ }
}
break;
}
// Even gcc-4.5 doesn't mangle this.
case Expr::BinaryConditionalOperatorClass: {
+ NotPrimaryExpr();
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID =
Diags.getCustomDiagID(DiagnosticsEngine::Error,
"?: operator with omitted middle operand cannot be mangled");
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
- break;
+ return;
}
// These are used for internal purposes and cannot be meaningfully mangled.
@@ -3885,6 +4095,7 @@ recurse:
llvm_unreachable("cannot mangle opaque value; mangling wrong thing?");
case Expr::InitListExprClass: {
+ NotPrimaryExpr();
Out << "il";
mangleInitListElements(cast<InitListExpr>(E));
Out << "E";
@@ -3892,6 +4103,7 @@ recurse:
}
case Expr::DesignatedInitExprClass: {
+ NotPrimaryExpr();
auto *DIE = cast<DesignatedInitExpr>(E);
for (const auto &Designator : DIE->designators()) {
if (Designator.isFieldDesignator()) {
@@ -3913,27 +4125,27 @@ recurse:
}
case Expr::CXXDefaultArgExprClass:
- mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
- break;
+ E = cast<CXXDefaultArgExpr>(E)->getExpr();
+ goto recurse;
case Expr::CXXDefaultInitExprClass:
- mangleExpression(cast<CXXDefaultInitExpr>(E)->getExpr(), Arity);
- break;
+ E = cast<CXXDefaultInitExpr>(E)->getExpr();
+ goto recurse;
case Expr::CXXStdInitializerListExprClass:
- mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity);
- break;
+ E = cast<CXXStdInitializerListExpr>(E)->getSubExpr();
+ goto recurse;
case Expr::SubstNonTypeTemplateParmExprClass:
- mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
- Arity);
- break;
+ E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
+ goto recurse;
case Expr::UserDefinedLiteralClass:
// We follow g++'s approach of mangling a UDL as a call to the literal
// operator.
case Expr::CXXMemberCallExprClass: // fallthrough
case Expr::CallExprClass: {
+ NotPrimaryExpr();
const CallExpr *CE = cast<CallExpr>(E);
// <expression> ::= cp <simple-id> <expression>* E
@@ -3964,6 +4176,7 @@ recurse:
}
case Expr::CXXNewExprClass: {
+ NotPrimaryExpr();
const CXXNewExpr *New = cast<CXXNewExpr>(E);
if (New->isGlobalNew()) Out << "gs";
Out << (New->isArray() ? "na" : "nw");
@@ -3999,6 +4212,7 @@ recurse:
}
case Expr::CXXPseudoDestructorExprClass: {
+ NotPrimaryExpr();
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
@@ -4025,6 +4239,7 @@ recurse:
}
case Expr::MemberExprClass: {
+ NotPrimaryExpr();
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
@@ -4035,6 +4250,7 @@ recurse:
}
case Expr::UnresolvedMemberExprClass: {
+ NotPrimaryExpr();
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
@@ -4045,6 +4261,7 @@ recurse:
}
case Expr::CXXDependentScopeMemberExprClass: {
+ NotPrimaryExpr();
const CXXDependentScopeMemberExpr *ME
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
@@ -4057,6 +4274,7 @@ recurse:
}
case Expr::UnresolvedLookupExprClass: {
+ NotPrimaryExpr();
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(),
ULE->getTemplateArgs(), ULE->getNumTemplateArgs(),
@@ -4065,8 +4283,9 @@ recurse:
}
case Expr::CXXUnresolvedConstructExprClass: {
+ NotPrimaryExpr();
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
- unsigned N = CE->arg_size();
+ unsigned N = CE->getNumArgs();
if (CE->isListInitialization()) {
assert(N == 1 && "unexpected form for list initialization");
@@ -4075,7 +4294,7 @@ recurse:
mangleType(CE->getType());
mangleInitListElements(IL);
Out << "E";
- return;
+ break;
}
Out << "cv";
@@ -4087,14 +4306,17 @@ recurse:
}
case Expr::CXXConstructExprClass: {
+ // An implicit cast is silent, thus may contain <expr-primary>.
const auto *CE = cast<CXXConstructExpr>(E);
if (!CE->isListInitialization() || CE->isStdInitListInitialization()) {
assert(
CE->getNumArgs() >= 1 &&
(CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) &&
"implicit CXXConstructExpr must have one argument");
- return mangleExpression(cast<CXXConstructExpr>(E)->getArg(0));
+ E = cast<CXXConstructExpr>(E)->getArg(0);
+ goto recurse;
}
+ NotPrimaryExpr();
Out << "il";
for (auto *E : CE->arguments())
mangleExpression(E);
@@ -4103,6 +4325,7 @@ recurse:
}
case Expr::CXXTemporaryObjectExprClass: {
+ NotPrimaryExpr();
const auto *CE = cast<CXXTemporaryObjectExpr>(E);
unsigned N = CE->getNumArgs();
bool List = CE->isListInitialization();
@@ -4132,17 +4355,20 @@ recurse:
}
case Expr::CXXScalarValueInitExprClass:
+ NotPrimaryExpr();
Out << "cv";
mangleType(E->getType());
Out << "_E";
break;
case Expr::CXXNoexceptExprClass:
+ NotPrimaryExpr();
Out << "nx";
mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
break;
case Expr::UnaryExprOrTypeTraitExprClass: {
+ // Non-instantiation-dependent traits are an <expr-primary> integer literal.
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
if (!SAE->isInstantiationDependent()) {
@@ -4162,13 +4388,41 @@ recurse:
break;
}
+ NotPrimaryExpr(); // But otherwise, they are not.
+
+ auto MangleAlignofSizeofArg = [&] {
+ if (SAE->isArgumentType()) {
+ Out << 't';
+ mangleType(SAE->getArgumentType());
+ } else {
+ Out << 'z';
+ mangleExpression(SAE->getArgumentExpr());
+ }
+ };
+
switch(SAE->getKind()) {
case UETT_SizeOf:
Out << 's';
+ MangleAlignofSizeofArg();
break;
case UETT_PreferredAlignOf:
+ // As of clang 12, we mangle __alignof__ differently than alignof. (They
+ // have acted differently since Clang 8, but were previously mangled the
+ // same.)
+ if (Context.getASTContext().getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver11) {
+ Out << "u11__alignof__";
+ if (SAE->isArgumentType())
+ mangleType(SAE->getArgumentType());
+ else
+ mangleTemplateArgExpr(SAE->getArgumentExpr());
+ Out << 'E';
+ break;
+ }
+ LLVM_FALLTHROUGH;
case UETT_AlignOf:
Out << 'a';
+ MangleAlignofSizeofArg();
break;
case UETT_VecStep: {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -4186,17 +4440,11 @@ recurse:
return;
}
}
- if (SAE->isArgumentType()) {
- Out << 't';
- mangleType(SAE->getArgumentType());
- } else {
- Out << 'z';
- mangleExpression(SAE->getArgumentExpr());
- }
break;
}
case Expr::CXXThrowExprClass: {
+ NotPrimaryExpr();
const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);
// <expression> ::= tw <expression> # throw expression
// ::= tr # rethrow
@@ -4210,6 +4458,7 @@ recurse:
}
case Expr::CXXTypeidExprClass: {
+ NotPrimaryExpr();
const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);
// <expression> ::= ti <type> # typeid (type)
// ::= te <expression> # typeid (expression)
@@ -4224,6 +4473,7 @@ recurse:
}
case Expr::CXXDeleteExprClass: {
+ NotPrimaryExpr();
const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);
// <expression> ::= [gs] dl <expression> # [::] delete expr
// ::= [gs] da <expression> # [::] delete [] expr
@@ -4234,6 +4484,7 @@ recurse:
}
case Expr::UnaryOperatorClass: {
+ NotPrimaryExpr();
const UnaryOperator *UO = cast<UnaryOperator>(E);
mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
/*Arity=*/1);
@@ -4242,6 +4493,7 @@ recurse:
}
case Expr::ArraySubscriptExprClass: {
+ NotPrimaryExpr();
const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(E);
// Array subscript is treated as a syntactically weird form of
@@ -4253,6 +4505,7 @@ recurse:
}
case Expr::MatrixSubscriptExprClass: {
+ NotPrimaryExpr();
const MatrixSubscriptExpr *ME = cast<MatrixSubscriptExpr>(E);
Out << "ixix";
mangleExpression(ME->getBase());
@@ -4263,6 +4516,7 @@ recurse:
case Expr::CompoundAssignOperatorClass: // fallthrough
case Expr::BinaryOperatorClass: {
+ NotPrimaryExpr();
const BinaryOperator *BO = cast<BinaryOperator>(E);
if (BO->getOpcode() == BO_PtrMemD)
Out << "ds";
@@ -4275,6 +4529,7 @@ recurse:
}
case Expr::CXXRewrittenBinaryOperatorClass: {
+ NotPrimaryExpr();
// The mangled form represents the original syntax.
CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
cast<CXXRewrittenBinaryOperator>(E)->getDecomposedForm();
@@ -4286,6 +4541,7 @@ recurse:
}
case Expr::ConditionalOperatorClass: {
+ NotPrimaryExpr();
const ConditionalOperator *CO = cast<ConditionalOperator>(E);
mangleOperatorName(OO_Conditional, /*Arity=*/3);
mangleExpression(CO->getCond());
@@ -4301,19 +4557,22 @@ recurse:
}
case Expr::ObjCBridgedCastExprClass: {
+ NotPrimaryExpr();
// Mangle ownership casts as a vendor extended operator __bridge,
// __bridge_transfer, or __bridge_retain.
StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
Out << "v1U" << Kind.size() << Kind;
+ mangleCastExpression(E, "cv");
+ break;
}
- // Fall through to mangle the cast itself.
- LLVM_FALLTHROUGH;
case Expr::CStyleCastExprClass:
+ NotPrimaryExpr();
mangleCastExpression(E, "cv");
break;
case Expr::CXXFunctionalCastExprClass: {
+ NotPrimaryExpr();
auto *Sub = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreImplicit();
// FIXME: Add isImplicit to CXXConstructExpr.
if (auto *CCE = dyn_cast<CXXConstructExpr>(Sub))
@@ -4333,22 +4592,28 @@ recurse:
}
case Expr::CXXStaticCastExprClass:
+ NotPrimaryExpr();
mangleCastExpression(E, "sc");
break;
case Expr::CXXDynamicCastExprClass:
+ NotPrimaryExpr();
mangleCastExpression(E, "dc");
break;
case Expr::CXXReinterpretCastExprClass:
+ NotPrimaryExpr();
mangleCastExpression(E, "rc");
break;
case Expr::CXXConstCastExprClass:
+ NotPrimaryExpr();
mangleCastExpression(E, "cc");
break;
case Expr::CXXAddrspaceCastExprClass:
+ NotPrimaryExpr();
mangleCastExpression(E, "ac");
break;
case Expr::CXXOperatorCallExprClass: {
+ NotPrimaryExpr();
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
unsigned NumArgs = CE->getNumArgs();
// A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax
@@ -4362,9 +4627,8 @@ recurse:
}
case Expr::ParenExprClass:
- mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);
- break;
-
+ E = cast<ParenExpr>(E)->getSubExpr();
+ goto recurse;
case Expr::ConceptSpecializationExprClass: {
// <expr-primary> ::= L <mangled-name> E # external name
@@ -4378,10 +4642,12 @@ recurse:
}
case Expr::DeclRefExprClass:
- mangleDeclRefExpr(cast<DeclRefExpr>(E)->getDecl());
+ // MangleDeclRefExpr helper handles primary-vs-nonprimary
+ MangleDeclRefExpr(cast<DeclRefExpr>(E)->getDecl());
break;
case Expr::SubstNonTypeTemplateParmPackExprClass:
+ NotPrimaryExpr();
// FIXME: not clear how to mangle this!
// template <unsigned N...> class A {
// template <class U...> void foo(U (&x)[N]...);
@@ -4390,14 +4656,16 @@ recurse:
break;
case Expr::FunctionParmPackExprClass: {
+ NotPrimaryExpr();
// FIXME: not clear how to mangle this!
const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
Out << "v110_SUBSTPACK";
- mangleDeclRefExpr(FPPE->getParameterPack());
+ MangleDeclRefExpr(FPPE->getParameterPack());
break;
}
case Expr::DependentScopeDeclRefExprClass: {
+ NotPrimaryExpr();
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(),
DRE->getTemplateArgs(), DRE->getNumTemplateArgs(),
@@ -4406,23 +4674,27 @@ recurse:
}
case Expr::CXXBindTemporaryExprClass:
- mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());
- break;
+ E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
+ goto recurse;
case Expr::ExprWithCleanupsClass:
- mangleExpression(cast<ExprWithCleanups>(E)->getSubExpr(), Arity);
- break;
+ E = cast<ExprWithCleanups>(E)->getSubExpr();
+ goto recurse;
case Expr::FloatingLiteralClass: {
+ // <expr-primary>
const FloatingLiteral *FL = cast<FloatingLiteral>(E);
- Out << 'L';
- mangleType(FL->getType());
- mangleFloat(FL->getValue());
- Out << 'E';
+ mangleFloatLiteral(FL->getType(), FL->getValue());
break;
}
+ case Expr::FixedPointLiteralClass:
+ // Currently unimplemented -- might be <expr-primary> in future?
+ mangleFixedPointLiteral();
+ break;
+
case Expr::CharacterLiteralClass:
+ // <expr-primary>
Out << 'L';
mangleType(E->getType());
Out << cast<CharacterLiteral>(E)->getValue();
@@ -4431,18 +4703,21 @@ recurse:
// FIXME. __objc_yes/__objc_no are mangled same as true/false
case Expr::ObjCBoolLiteralExprClass:
+ // <expr-primary>
Out << "Lb";
Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
case Expr::CXXBoolLiteralExprClass:
+ // <expr-primary>
Out << "Lb";
Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
case Expr::IntegerLiteralClass: {
+ // <expr-primary>
llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());
if (E->getType()->isSignedIntegerType())
Value.setIsSigned(true);
@@ -4451,6 +4726,7 @@ recurse:
}
case Expr::ImaginaryLiteralClass: {
+ // <expr-primary>
const ImaginaryLiteral *IE = cast<ImaginaryLiteral>(E);
// Mangle as if a complex literal.
// Proposal from David Vandevoorde, 2010.06.30.
@@ -4474,6 +4750,7 @@ recurse:
}
case Expr::StringLiteralClass: {
+ // <expr-primary>
// Revised proposal from David Vandervoorde, 2010.07.15.
Out << 'L';
assert(isa<ConstantArrayType>(E->getType()));
@@ -4483,28 +4760,30 @@ recurse:
}
case Expr::GNUNullExprClass:
+ // <expr-primary>
// Mangle as if an integer literal 0.
- Out << 'L';
- mangleType(E->getType());
- Out << "0E";
+ mangleIntegerLiteral(E->getType(), llvm::APSInt(32));
break;
case Expr::CXXNullPtrLiteralExprClass: {
+ // <expr-primary>
Out << "LDnE";
break;
}
case Expr::PackExpansionExprClass:
+ NotPrimaryExpr();
Out << "sp";
mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
break;
case Expr::SizeOfPackExprClass: {
+ NotPrimaryExpr();
auto *SPE = cast<SizeOfPackExpr>(E);
if (SPE->isPartiallySubstituted()) {
Out << "sP";
for (const auto &A : SPE->getPartialArguments())
- mangleTemplateArg(A);
+ mangleTemplateArg(A, false);
Out << "E";
break;
}
@@ -4524,12 +4803,12 @@ recurse:
break;
}
- case Expr::MaterializeTemporaryExprClass: {
- mangleExpression(cast<MaterializeTemporaryExpr>(E)->getSubExpr());
- break;
- }
+ case Expr::MaterializeTemporaryExprClass:
+ E = cast<MaterializeTemporaryExpr>(E)->getSubExpr();
+ goto recurse;
case Expr::CXXFoldExprClass: {
+ NotPrimaryExpr();
auto *FE = cast<CXXFoldExpr>(E);
if (FE->isLeftFold())
Out << (FE->getInit() ? "fL" : "fl");
@@ -4551,27 +4830,34 @@ recurse:
}
case Expr::CXXThisExprClass:
+ NotPrimaryExpr();
Out << "fpT";
break;
case Expr::CoawaitExprClass:
// FIXME: Propose a non-vendor mangling.
+ NotPrimaryExpr();
Out << "v18co_await";
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
break;
case Expr::DependentCoawaitExprClass:
// FIXME: Propose a non-vendor mangling.
+ NotPrimaryExpr();
Out << "v18co_await";
mangleExpression(cast<DependentCoawaitExpr>(E)->getOperand());
break;
case Expr::CoyieldExprClass:
// FIXME: Propose a non-vendor mangling.
+ NotPrimaryExpr();
Out << "v18co_yield";
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
break;
}
+
+ if (AsTemplateArg && !IsPrimaryExpr)
+ Out << 'E';
}
/// Mangle an expression which refers to a parameter variable.
@@ -4692,33 +4978,112 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
}
}
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
+namespace {
+// Helper to provide ancillary information on a template used to mangle its
+// arguments.
+struct TemplateArgManglingInfo {
+ TemplateDecl *ResolvedTemplate = nullptr;
+ bool SeenPackExpansionIntoNonPack = false;
+ const NamedDecl *UnresolvedExpandedPack = nullptr;
+
+ TemplateArgManglingInfo(TemplateName TN) {
+ if (TemplateDecl *TD = TN.getAsTemplateDecl())
+ ResolvedTemplate = TD;
+ }
+
+ /// Do we need to mangle template arguments with exactly correct types?
+ ///
+ /// This should be called exactly once for each parameter / argument pair, in
+ /// order.
+ bool needExactType(unsigned ParamIdx, const TemplateArgument &Arg) {
+ // We need correct types when the template-name is unresolved or when it
+ // names a template that is able to be overloaded.
+ if (!ResolvedTemplate || SeenPackExpansionIntoNonPack)
+ return true;
+
+ // Move to the next parameter.
+ const NamedDecl *Param = UnresolvedExpandedPack;
+ if (!Param) {
+ assert(ParamIdx < ResolvedTemplate->getTemplateParameters()->size() &&
+ "no parameter for argument");
+ Param = ResolvedTemplate->getTemplateParameters()->getParam(ParamIdx);
+
+ // If we reach an expanded parameter pack whose argument isn't in pack
+ // form, that means Sema couldn't figure out which arguments belonged to
+ // it, because it contains a pack expansion. Track the expanded pack for
+ // all further template arguments until we hit that pack expansion.
+ if (Param->isParameterPack() && Arg.getKind() != TemplateArgument::Pack) {
+ assert(getExpandedPackSize(Param) &&
+ "failed to form pack argument for parameter pack");
+ UnresolvedExpandedPack = Param;
+ }
+ }
+
+ // If we encounter a pack argument that is expanded into a non-pack
+ // parameter, we can no longer track parameter / argument correspondence,
+ // and need to use exact types from this point onwards.
+ if (Arg.isPackExpansion() &&
+ (!Param->isParameterPack() || UnresolvedExpandedPack)) {
+ SeenPackExpansionIntoNonPack = true;
+ return true;
+ }
+
+ // We need exact types for function template arguments because they might be
+ // overloaded on template parameter type. As a special case, a member
+ // function template of a generic lambda is not overloadable.
+ if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ResolvedTemplate)) {
+ auto *RD = dyn_cast<CXXRecordDecl>(FTD->getDeclContext());
+ if (!RD || !RD->isGenericLambda())
+ return true;
+ }
+
+ // Otherwise, we only need a correct type if the parameter has a deduced
+ // type.
+ //
+ // Note: for an expanded parameter pack, getType() returns the type prior
+ // to expansion. We could ask for the expanded type with getExpansionType(),
+ // but it doesn't matter because substitution and expansion don't affect
+ // whether a deduced type appears in the type.
+ auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param);
+ return NTTP && NTTP->getType()->getContainedDeducedType();
+ }
+};
+}
+
+void CXXNameMangler::mangleTemplateArgs(TemplateName TN,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
+ TemplateArgManglingInfo Info(TN);
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- mangleTemplateArg(TemplateArgs[i].getArgument());
+ mangleTemplateArg(TemplateArgs[i].getArgument(),
+ Info.needExactType(i, TemplateArgs[i].getArgument()));
Out << 'E';
}
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
+void CXXNameMangler::mangleTemplateArgs(TemplateName TN,
+ const TemplateArgumentList &AL) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
+ TemplateArgManglingInfo Info(TN);
for (unsigned i = 0, e = AL.size(); i != e; ++i)
- mangleTemplateArg(AL[i]);
+ mangleTemplateArg(AL[i], Info.needExactType(i, AL[i]));
Out << 'E';
}
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
+void CXXNameMangler::mangleTemplateArgs(TemplateName TN,
+ const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
+ TemplateArgManglingInfo Info(TN);
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- mangleTemplateArg(TemplateArgs[i]);
+ mangleTemplateArg(TemplateArgs[i], Info.needExactType(i, TemplateArgs[i]));
Out << 'E';
}
-void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
+void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
// <template-arg> ::= <type> # type or template
// ::= X <expression> E # expression
// ::= <expr-primary> # simple expressions
@@ -4742,67 +5107,557 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
Out << "Dp";
mangleType(A.getAsTemplateOrTemplatePattern());
break;
- case TemplateArgument::Expression: {
- // It's possible to end up with a DeclRefExpr here in certain
- // dependent cases, in which case we should mangle as a
- // declaration.
- const Expr *E = A.getAsExpr()->IgnoreParenImpCasts();
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- const ValueDecl *D = DRE->getDecl();
- if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
- Out << 'L';
- mangle(D);
- Out << 'E';
- break;
- }
- }
-
- Out << 'X';
- mangleExpression(E);
- Out << 'E';
+ case TemplateArgument::Expression:
+ mangleTemplateArgExpr(A.getAsExpr());
break;
- }
case TemplateArgument::Integral:
mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
break;
case TemplateArgument::Declaration: {
// <expr-primary> ::= L <mangled-name> E # external name
- // Clang produces AST's where pointer-to-member-function expressions
- // and pointer-to-function expressions are represented as a declaration not
- // an expression. We compensate for it here to produce the correct mangling.
ValueDecl *D = A.getAsDecl();
- bool compensateMangling = !A.getParamTypeForDecl()->isReferenceType();
- if (compensateMangling) {
- Out << 'X';
- mangleOperatorName(OO_Amp, 1);
- }
- Out << 'L';
- // References to external entities use the mangled name; if the name would
- // not normally be mangled then mangle it as unqualified.
- mangle(D);
- Out << 'E';
-
- if (compensateMangling)
- Out << 'E';
+ // Template parameter objects are modeled by reproducing a source form
+ // produced as if by aggregate initialization.
+ if (A.getParamTypeForDecl()->isRecordType()) {
+ auto *TPO = cast<TemplateParamObjectDecl>(D);
+ mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(),
+ TPO->getValue(), /*TopLevel=*/true,
+ NeedExactType);
+ break;
+ }
+ ASTContext &Ctx = Context.getASTContext();
+ APValue Value;
+ if (D->isCXXInstanceMember())
+ // Simple pointer-to-member with no conversion.
+ Value = APValue(D, /*IsDerivedMember=*/false, /*Path=*/{});
+ else if (D->getType()->isArrayType() &&
+ Ctx.hasSimilarType(Ctx.getDecayedType(D->getType()),
+ A.getParamTypeForDecl()) &&
+ Ctx.getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver11)
+ // Build a value corresponding to this implicit array-to-pointer decay.
+ Value = APValue(APValue::LValueBase(D), CharUnits::Zero(),
+ {APValue::LValuePathEntry::ArrayIndex(0)},
+ /*OnePastTheEnd=*/false);
+ else
+ // Regular pointer or reference to a declaration.
+ Value = APValue(APValue::LValueBase(D), CharUnits::Zero(),
+ ArrayRef<APValue::LValuePathEntry>(),
+ /*OnePastTheEnd=*/false);
+ mangleValueInTemplateArg(A.getParamTypeForDecl(), Value, /*TopLevel=*/true,
+ NeedExactType);
break;
}
case TemplateArgument::NullPtr: {
- // <expr-primary> ::= L <type> 0 E
- Out << 'L';
- mangleType(A.getNullPtrType());
- Out << "0E";
+ mangleNullPointer(A.getNullPtrType());
break;
}
case TemplateArgument::Pack: {
// <template-arg> ::= J <template-arg>* E
Out << 'J';
for (const auto &P : A.pack_elements())
- mangleTemplateArg(P);
+ mangleTemplateArg(P, NeedExactType);
+ Out << 'E';
+ }
+ }
+}
+
+void CXXNameMangler::mangleTemplateArgExpr(const Expr *E) {
+ ASTContext &Ctx = Context.getASTContext();
+ if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver11) {
+ mangleExpression(E, UnknownArity, /*AsTemplateArg=*/true);
+ return;
+ }
+
+ // Prior to Clang 12, we didn't omit the X .. E around <expr-primary>
+ // correctly in cases where the template argument was
+ // constructed from an expression rather than an already-evaluated
+ // literal. In such a case, we would then e.g. emit 'XLi0EE' instead of
+ // 'Li0E'.
+ //
+ // We did special-case DeclRefExpr to attempt to DTRT for that one
+ // expression-kind, but while doing so, unfortunately handled ParmVarDecl
+ // (subtype of VarDecl) _incorrectly_, and emitted 'L_Z .. E' instead of
+ // the proper 'Xfp_E'.
+ E = E->IgnoreParenImpCasts();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ const ValueDecl *D = DRE->getDecl();
+ if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
+ Out << 'L';
+ mangle(D);
+ Out << 'E';
+ return;
+ }
+ }
+ Out << 'X';
+ mangleExpression(E);
+ Out << 'E';
+}
+
+/// Determine whether a given value is equivalent to zero-initialization for
+/// the purpose of discarding a trailing portion of a 'tl' mangling.
+///
+/// Note that this is not in general equivalent to determining whether the
+/// value has an all-zeroes bit pattern.
+static bool isZeroInitialized(QualType T, const APValue &V) {
+ // FIXME: mangleValueInTemplateArg has quadratic time complexity in
+ // pathological cases due to using this, but it's a little awkward
+ // to do this in linear time in general.
+ switch (V.getKind()) {
+ case APValue::None:
+ case APValue::Indeterminate:
+ case APValue::AddrLabelDiff:
+ return false;
+
+ case APValue::Struct: {
+ const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+ assert(RD && "unexpected type for record value");
+ unsigned I = 0;
+ for (const CXXBaseSpecifier &BS : RD->bases()) {
+ if (!isZeroInitialized(BS.getType(), V.getStructBase(I)))
+ return false;
+ ++I;
+ }
+ I = 0;
+ for (const FieldDecl *FD : RD->fields()) {
+ if (!FD->isUnnamedBitfield() &&
+ !isZeroInitialized(FD->getType(), V.getStructField(I)))
+ return false;
+ ++I;
+ }
+ return true;
+ }
+
+ case APValue::Union: {
+ const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+ assert(RD && "unexpected type for union value");
+ // Zero-initialization zeroes the first non-unnamed-bitfield field, if any.
+ for (const FieldDecl *FD : RD->fields()) {
+ if (!FD->isUnnamedBitfield())
+ return V.getUnionField() && declaresSameEntity(FD, V.getUnionField()) &&
+ isZeroInitialized(FD->getType(), V.getUnionValue());
+ }
+ // If there are no fields (other than unnamed bitfields), the value is
+ // necessarily zero-initialized.
+ return true;
+ }
+
+ case APValue::Array: {
+ QualType ElemT(T->getArrayElementTypeNoTypeQual(), 0);
+ for (unsigned I = 0, N = V.getArrayInitializedElts(); I != N; ++I)
+ if (!isZeroInitialized(ElemT, V.getArrayInitializedElt(I)))
+ return false;
+ return !V.hasArrayFiller() || isZeroInitialized(ElemT, V.getArrayFiller());
+ }
+
+ case APValue::Vector: {
+ const VectorType *VT = T->castAs<VectorType>();
+ for (unsigned I = 0, N = V.getVectorLength(); I != N; ++I)
+ if (!isZeroInitialized(VT->getElementType(), V.getVectorElt(I)))
+ return false;
+ return true;
+ }
+
+ case APValue::Int:
+ return !V.getInt();
+
+ case APValue::Float:
+ return V.getFloat().isPosZero();
+
+ case APValue::FixedPoint:
+ return !V.getFixedPoint().getValue();
+
+ case APValue::ComplexFloat:
+ return V.getComplexFloatReal().isPosZero() &&
+ V.getComplexFloatImag().isPosZero();
+
+ case APValue::ComplexInt:
+ return !V.getComplexIntReal() && !V.getComplexIntImag();
+
+ case APValue::LValue:
+ return V.isNullPointer();
+
+ case APValue::MemberPointer:
+ return !V.getMemberPointerDecl();
+ }
+
+ llvm_unreachable("Unhandled APValue::ValueKind enum");
+}
+
+static QualType getLValueType(ASTContext &Ctx, const APValue &LV) {
+ QualType T = LV.getLValueBase().getType();
+ for (APValue::LValuePathEntry E : LV.getLValuePath()) {
+ if (const ArrayType *AT = Ctx.getAsArrayType(T))
+ T = AT->getElementType();
+ else if (const FieldDecl *FD =
+ dyn_cast<FieldDecl>(E.getAsBaseOrMember().getPointer()))
+ T = FD->getType();
+ else
+ T = Ctx.getRecordType(
+ cast<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()));
+ }
+ return T;
+}
+
+void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
+ bool TopLevel,
+ bool NeedExactType) {
+ // Ignore all top-level cv-qualifiers, to match GCC.
+ Qualifiers Quals;
+ T = getASTContext().getUnqualifiedArrayType(T, Quals);
+
+ // A top-level expression that's not a primary expression is wrapped in X...E.
+ bool IsPrimaryExpr = true;
+ auto NotPrimaryExpr = [&] {
+ if (TopLevel && IsPrimaryExpr)
+ Out << 'X';
+ IsPrimaryExpr = false;
+ };
+
+ // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63.
+ switch (V.getKind()) {
+ case APValue::None:
+ case APValue::Indeterminate:
+ Out << 'L';
+ mangleType(T);
+ Out << 'E';
+ break;
+
+ case APValue::AddrLabelDiff:
+ llvm_unreachable("unexpected value kind in template argument");
+
+ case APValue::Struct: {
+ const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+ assert(RD && "unexpected type for record value");
+
+ // Drop trailing zero-initialized elements.
+ llvm::SmallVector<const FieldDecl *, 16> Fields(RD->field_begin(),
+ RD->field_end());
+ while (
+ !Fields.empty() &&
+ (Fields.back()->isUnnamedBitfield() ||
+ isZeroInitialized(Fields.back()->getType(),
+ V.getStructField(Fields.back()->getFieldIndex())))) {
+ Fields.pop_back();
+ }
+ llvm::ArrayRef<CXXBaseSpecifier> Bases(RD->bases_begin(), RD->bases_end());
+ if (Fields.empty()) {
+ while (!Bases.empty() &&
+ isZeroInitialized(Bases.back().getType(),
+ V.getStructBase(Bases.size() - 1)))
+ Bases = Bases.drop_back();
+ }
+
+ // <expression> ::= tl <type> <braced-expression>* E
+ NotPrimaryExpr();
+ Out << "tl";
+ mangleType(T);
+ for (unsigned I = 0, N = Bases.size(); I != N; ++I)
+ mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I), false);
+ for (unsigned I = 0, N = Fields.size(); I != N; ++I) {
+ if (Fields[I]->isUnnamedBitfield())
+ continue;
+ mangleValueInTemplateArg(Fields[I]->getType(),
+ V.getStructField(Fields[I]->getFieldIndex()),
+ false);
+ }
+ Out << 'E';
+ break;
+ }
+
+ case APValue::Union: {
+ assert(T->getAsCXXRecordDecl() && "unexpected type for union value");
+ const FieldDecl *FD = V.getUnionField();
+
+ if (!FD) {
+ Out << 'L';
+ mangleType(T);
+ Out << 'E';
+ break;
+ }
+
+ // <braced-expression> ::= di <field source-name> <braced-expression>
+ NotPrimaryExpr();
+ Out << "tl";
+ mangleType(T);
+ if (!isZeroInitialized(T, V)) {
+ Out << "di";
+ mangleSourceName(FD->getIdentifier());
+ mangleValueInTemplateArg(FD->getType(), V.getUnionValue(), false);
+ }
+ Out << 'E';
+ break;
+ }
+
+ case APValue::Array: {
+ QualType ElemT(T->getArrayElementTypeNoTypeQual(), 0);
+
+ NotPrimaryExpr();
+ Out << "tl";
+ mangleType(T);
+
+ // Drop trailing zero-initialized elements.
+ unsigned N = V.getArraySize();
+ if (!V.hasArrayFiller() || isZeroInitialized(ElemT, V.getArrayFiller())) {
+ N = V.getArrayInitializedElts();
+ while (N && isZeroInitialized(ElemT, V.getArrayInitializedElt(N - 1)))
+ --N;
+ }
+
+ for (unsigned I = 0; I != N; ++I) {
+ const APValue &Elem = I < V.getArrayInitializedElts()
+ ? V.getArrayInitializedElt(I)
+ : V.getArrayFiller();
+ mangleValueInTemplateArg(ElemT, Elem, false);
+ }
Out << 'E';
+ break;
}
+
+ case APValue::Vector: {
+ const VectorType *VT = T->castAs<VectorType>();
+
+ NotPrimaryExpr();
+ Out << "tl";
+ mangleType(T);
+ unsigned N = V.getVectorLength();
+ while (N && isZeroInitialized(VT->getElementType(), V.getVectorElt(N - 1)))
+ --N;
+ for (unsigned I = 0; I != N; ++I)
+ mangleValueInTemplateArg(VT->getElementType(), V.getVectorElt(I), false);
+ Out << 'E';
+ break;
}
+
+ case APValue::Int:
+ mangleIntegerLiteral(T, V.getInt());
+ break;
+
+ case APValue::Float:
+ mangleFloatLiteral(T, V.getFloat());
+ break;
+
+ case APValue::FixedPoint:
+ mangleFixedPointLiteral();
+ break;
+
+ case APValue::ComplexFloat: {
+ const ComplexType *CT = T->castAs<ComplexType>();
+ NotPrimaryExpr();
+ Out << "tl";
+ mangleType(T);
+ if (!V.getComplexFloatReal().isPosZero() ||
+ !V.getComplexFloatImag().isPosZero())
+ mangleFloatLiteral(CT->getElementType(), V.getComplexFloatReal());
+ if (!V.getComplexFloatImag().isPosZero())
+ mangleFloatLiteral(CT->getElementType(), V.getComplexFloatImag());
+ Out << 'E';
+ break;
+ }
+
+ case APValue::ComplexInt: {
+ const ComplexType *CT = T->castAs<ComplexType>();
+ NotPrimaryExpr();
+ Out << "tl";
+ mangleType(T);
+ if (V.getComplexIntReal().getBoolValue() ||
+ V.getComplexIntImag().getBoolValue())
+ mangleIntegerLiteral(CT->getElementType(), V.getComplexIntReal());
+ if (V.getComplexIntImag().getBoolValue())
+ mangleIntegerLiteral(CT->getElementType(), V.getComplexIntImag());
+ Out << 'E';
+ break;
+ }
+
+ case APValue::LValue: {
+ // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47.
+ assert((T->isPointerType() || T->isReferenceType()) &&
+ "unexpected type for LValue template arg");
+
+ if (V.isNullPointer()) {
+ mangleNullPointer(T);
+ break;
+ }
+
+ APValue::LValueBase B = V.getLValueBase();
+ if (!B) {
+ // Non-standard mangling for integer cast to a pointer; this can only
+ // occur as an extension.
+ CharUnits Offset = V.getLValueOffset();
+ if (Offset.isZero()) {
+ // This is reinterpret_cast<T*>(0), not a null pointer. Mangle this as
+ // a cast, because L <type> 0 E means something else.
+ NotPrimaryExpr();
+ Out << "rc";
+ mangleType(T);
+ Out << "Li0E";
+ if (TopLevel)
+ Out << 'E';
+ } else {
+ Out << "L";
+ mangleType(T);
+ Out << Offset.getQuantity() << 'E';
+ }
+ break;
+ }
+
+ ASTContext &Ctx = Context.getASTContext();
+
+ enum { Base, Offset, Path } Kind;
+ if (!V.hasLValuePath()) {
+ // Mangle as (T*)((char*)&base + N).
+ if (T->isReferenceType()) {
+ NotPrimaryExpr();
+ Out << "decvP";
+ mangleType(T->getPointeeType());
+ } else {
+ NotPrimaryExpr();
+ Out << "cv";
+ mangleType(T);
+ }
+ Out << "plcvPcad";
+ Kind = Offset;
+ } else {
+ if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
+ NotPrimaryExpr();
+ // A final conversion to the template parameter's type is usually
+ // folded into the 'so' mangling, but we can't do that for 'void*'
+ // parameters without introducing collisions.
+ if (NeedExactType && T->isVoidPointerType()) {
+ Out << "cv";
+ mangleType(T);
+ }
+ if (T->isPointerType())
+ Out << "ad";
+ Out << "so";
+ mangleType(T->isVoidPointerType()
+ ? getLValueType(Ctx, V).getUnqualifiedType()
+ : T->getPointeeType());
+ Kind = Path;
+ } else {
+ if (NeedExactType &&
+ !Ctx.hasSameType(T->getPointeeType(), getLValueType(Ctx, V)) &&
+ Ctx.getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver11) {
+ NotPrimaryExpr();
+ Out << "cv";
+ mangleType(T);
+ }
+ if (T->isPointerType()) {
+ NotPrimaryExpr();
+ Out << "ad";
+ }
+ Kind = Base;
+ }
+ }
+
+ QualType TypeSoFar = B.getType();
+ if (auto *VD = B.dyn_cast<const ValueDecl*>()) {
+ Out << 'L';
+ mangle(VD);
+ Out << 'E';
+ } else if (auto *E = B.dyn_cast<const Expr*>()) {
+ NotPrimaryExpr();
+ mangleExpression(E);
+ } else if (auto TI = B.dyn_cast<TypeInfoLValue>()) {
+ NotPrimaryExpr();
+ Out << "ti";
+ mangleType(QualType(TI.getType(), 0));
+ } else {
+ // We should never see dynamic allocations here.
+ llvm_unreachable("unexpected lvalue base kind in template argument");
+ }
+
+ switch (Kind) {
+ case Base:
+ break;
+
+ case Offset:
+ Out << 'L';
+ mangleType(Ctx.getPointerDiffType());
+ mangleNumber(V.getLValueOffset().getQuantity());
+ Out << 'E';
+ break;
+
+ case Path:
+ // <expression> ::= so <referent type> <expr> [<offset number>]
+ // <union-selector>* [p] E
+ if (!V.getLValueOffset().isZero())
+ mangleNumber(V.getLValueOffset().getQuantity());
+
+ // We model a past-the-end array pointer as array indexing with index N,
+ // not with the "past the end" flag. Compensate for that.
+ bool OnePastTheEnd = V.isLValueOnePastTheEnd();
+
+ for (APValue::LValuePathEntry E : V.getLValuePath()) {
+ if (auto *AT = TypeSoFar->getAsArrayTypeUnsafe()) {
+ if (auto *CAT = dyn_cast<ConstantArrayType>(AT))
+ OnePastTheEnd |= CAT->getSize() == E.getAsArrayIndex();
+ TypeSoFar = AT->getElementType();
+ } else {
+ const Decl *D = E.getAsBaseOrMember().getPointer();
+ if (auto *FD = dyn_cast<FieldDecl>(D)) {
+ // <union-selector> ::= _ <number>
+ if (FD->getParent()->isUnion()) {
+ Out << '_';
+ if (FD->getFieldIndex())
+ Out << (FD->getFieldIndex() - 1);
+ }
+ TypeSoFar = FD->getType();
+ } else {
+ TypeSoFar = Ctx.getRecordType(cast<CXXRecordDecl>(D));
+ }
+ }
+ }
+
+ if (OnePastTheEnd)
+ Out << 'p';
+ Out << 'E';
+ break;
+ }
+
+ break;
+ }
+
+ case APValue::MemberPointer:
+ // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47.
+ if (!V.getMemberPointerDecl()) {
+ mangleNullPointer(T);
+ break;
+ }
+
+ ASTContext &Ctx = Context.getASTContext();
+
+ NotPrimaryExpr();
+ if (!V.getMemberPointerPath().empty()) {
+ Out << "mc";
+ mangleType(T);
+ } else if (NeedExactType &&
+ !Ctx.hasSameType(
+ T->castAs<MemberPointerType>()->getPointeeType(),
+ V.getMemberPointerDecl()->getType()) &&
+ Ctx.getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver11) {
+ Out << "cv";
+ mangleType(T);
+ }
+ Out << "adL";
+ mangle(V.getMemberPointerDecl());
+ Out << 'E';
+ if (!V.getMemberPointerPath().empty()) {
+ CharUnits Offset =
+ Context.getASTContext().getMemberPointerPathAdjustment(V);
+ if (!Offset.isZero())
+ mangleNumber(Offset.getQuantity());
+ Out << 'E';
+ }
+ break;
+ }
+
+ if (TopLevel && !IsPrimaryExpr)
+ Out << 'E';
}
void CXXNameMangler::mangleTemplateParameter(unsigned Depth, unsigned Index) {
@@ -5121,8 +5976,8 @@ bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C,
void ItaniumMangleContextImpl::mangleCXXName(GlobalDecl GD,
raw_ostream &Out) {
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
- "Invalid mangleName() call, argument is not a variable or function!");
+ assert((isa<FunctionDecl, VarDecl, TemplateParamObjectDecl>(D)) &&
+ "Invalid mangleName() call, argument is not a variable or function!");
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
getASTContext().getSourceManager(),
@@ -5351,8 +6206,7 @@ void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda,
Mangler.mangleLambdaSig(Lambda);
}
-ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
- DiagnosticsEngine &Diags,
- bool IsUniqueNameMangler) {
- return new ItaniumMangleContextImpl(Context, Diags, IsUniqueNameMangler);
+ItaniumMangleContext *
+ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
+ return new ItaniumMangleContextImpl(Context, Diags);
}