[llvm-branch-commits] [clang] 7127fd1 - MSABI: Basic mangling for access to member subobjects in a class
Richard Smith via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Dec 9 18:13:47 PST 2020
Author: Richard Smith
Date: 2020-12-09T18:08:49-08:00
New Revision: 7127fd1786e607990ada5ade2bf473e6cad68d9d
URL: https://github.com/llvm/llvm-project/commit/7127fd1786e607990ada5ade2bf473e6cad68d9d
DIFF: https://github.com/llvm/llvm-project/commit/7127fd1786e607990ada5ade2bf473e6cad68d9d.diff
LOG: MSABI: Basic mangling for access to member subobjects in a class
non-type template parameter.
The mangling information used here comes from private communication with
Jon Caves at Microsoft.
Added:
Modified:
clang/lib/AST/MicrosoftMangle.cpp
clang/test/CodeGenCXX/mangle-class-nttp.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 1fba1392d0ed..286000faf2a4 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -394,7 +394,7 @@ class MicrosoftCXXNameMangler {
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
const NamedDecl *Parm);
void mangleTemplateArgValue(QualType T, const APValue &V,
- bool WithScalarType = true);
+ bool WithScalarType = false);
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
void mangleObjCLifetime(const QualType T, Qualifiers Quals,
@@ -1473,11 +1473,34 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
// ::= <integer-literal>
// ::= <member-data-pointer>
// ::= <member-function-pointer>
- // ::= $E? <name> <type-encoding>
- // ::= $1? <name> <type-encoding>
- // ::= $2 <type> <value> # class NTTP
- // ::= $0A@
+ // ::= $ <constant-value>
// ::= <template-args>
+ //
+ // <constant-value> ::= 0 <number> # integer
+ // ::= 1 <mangled-name> # address of D
+ // ::= 2 <type> <typed-constant-value>* @ # struct
+ // ::= 3 <type> <constant-value>* @ # array
+ // ::= 4 ??? # string
+ // ::= 5 <constant-value> @ # address of subobject
+ // ::= 6 <constant-value> <unqualified-name> @ # a.b
+ // ::= 7 <type> [<unqualified-name> <constant-value>] @
+ // # union, with or without an active member
+ // # pointer to member, symbolically
+ // ::= 8 <class> <unqualified-name> @
+ // ::= A <type> <non-negative integer> # float
+ // ::= B <type> <non-negative integer> # double
+ // ::= E <mangled-name> # reference to D
+ // # pointer to member, by component value
+ // ::= F <number> <number>
+ // ::= G <number> <number> <number>
+ // ::= H <mangled-name> <number>
+ // ::= I <mangled-name> <number> <number>
+ // ::= J <mangled-name> <number> <number> <number>
+ //
+ // <typed-constant-value> ::= [<type>] <constant-value>
+ //
+ // The <type> appears to be included in a <typed-constant-value> only in the
+ // '0', '1', '8', 'A', 'B', and 'E' cases.
switch (TA.getKind()) {
case TemplateArgument::Null:
@@ -1622,22 +1645,66 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
- APValue::LValueBase Base = V.getLValueBase();
- if (Base.isNull())
- Out << "0A@";
- else if (auto *VD = Base.dyn_cast<const ValueDecl*>())
- mangle(VD, T->isReferenceType() ? "E?" : "1?");
- else
+ // We don't know how to mangle past-the-end pointers yet.
+ if (V.isLValueOnePastTheEnd())
break;
- // FIXME: MSVC doesn't support template arguments referring to subobjects
- // yet (it either mangles such template arguments as null pointers or
- // small integers or crashes). It's probably the intent to mangle the
- // declaration followed by an offset, but that's not what actually happens.
- // For now just bail.
- if (!V.hasLValuePath() || !V.getLValuePath().empty() ||
- V.isLValueOnePastTheEnd())
- break;
+ APValue::LValueBase Base = V.getLValueBase();
+ if (!V.hasLValuePath() || V.getLValuePath().empty()) {
+ // Taking the address of a complete object has a special-case mangling.
+ if (Base.isNull()) {
+ // MSVC emits 0A@ for null pointers. Generalize this for arbitrary
+ // integers cast to pointers.
+ // FIXME: This mangles 0 cast to a pointer the same as a null pointer,
+ // even in cases where the two are
diff erent values.
+ Out << "0";
+ mangleNumber(V.getLValueOffset().getQuantity());
+ } else if (!V.hasLValuePath()) {
+ // FIXME: This can only happen as an extension. Invent a mangling.
+ break;
+ } else if (auto *VD = Base.dyn_cast<const ValueDecl*>()) {
+ Out << (T->isReferenceType() ? "E" : "1");
+ mangle(VD);
+ } else {
+ break;
+ }
+ } else {
+ unsigned NumAts = 0;
+ if (T->isPointerType()) {
+ Out << "5";
+ ++NumAts;
+ }
+
+ QualType T = Base.getType();
+ for (APValue::LValuePathEntry E : V.getLValuePath()) {
+ // We don't know how to mangle array subscripting yet.
+ if (T->isArrayType())
+ goto mangling_unknown;
+
+ const Decl *D = E.getAsBaseOrMember().getPointer();
+ auto *FD = dyn_cast<FieldDecl>(D);
+ // We don't know how to mangle derived-to-base conversions yet.
+ if (!FD)
+ goto mangling_unknown;
+
+ Out << "6";
+ ++NumAts;
+ T = FD->getType();
+ }
+
+ auto *VD = Base.dyn_cast<const ValueDecl*>();
+ if (!VD)
+ break;
+ Out << "E";
+ mangle(VD);
+
+ for (APValue::LValuePathEntry E : V.getLValuePath()) {
+ const Decl *D = E.getAsBaseOrMember().getPointer();
+ mangleUnqualifiedName(cast<FieldDecl>(D));
+ }
+ for (unsigned I = 0; I != NumAts; ++I)
+ Out << '@';
+ }
return;
}
@@ -1675,7 +1742,8 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
for (const FieldDecl *FD : RD->fields())
if (!FD->isUnnamedBitfield())
mangleTemplateArgValue(FD->getType(),
- V.getStructField(FD->getFieldIndex()));
+ V.getStructField(FD->getFieldIndex()),
+ /*WithScalarType*/ true);
Out << '@';
return;
}
@@ -1685,8 +1753,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleType(T, SourceRange(), QMM_Escape);
if (const FieldDecl *FD = V.getUnionField()) {
mangleUnqualifiedName(FD);
- mangleTemplateArgValue(FD->getType(), V.getUnionValue(),
- /*WithType*/false);
+ mangleTemplateArgValue(FD->getType(), V.getUnionValue());
}
Out << '@';
return;
@@ -1718,7 +1785,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const APValue &ElemV = I < V.getArrayInitializedElts()
? V.getArrayInitializedElt(I)
: V.getArrayFiller();
- mangleTemplateArgValue(ElemT, ElemV, /*WithType*/false);
+ mangleTemplateArgValue(ElemT, ElemV);
Out << '@';
}
Out << '@';
@@ -1735,7 +1802,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleType(ElemT, SourceRange(), QMM_Escape);
for (unsigned I = 0, N = V.getVectorLength(); I != N; ++I) {
const APValue &ElemV = V.getVectorElt(I);
- mangleTemplateArgValue(ElemT, ElemV, /*WithType*/false);
+ mangleTemplateArgValue(ElemT, ElemV);
Out << '@';
}
Out << "@@";
@@ -1747,6 +1814,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
break;
}
+mangling_unknown:
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this template argument yet");
diff --git a/clang/test/CodeGenCXX/mangle-class-nttp.cpp b/clang/test/CodeGenCXX/mangle-class-nttp.cpp
index 579afd0a01be..81107c481504 100644
--- a/clang/test/CodeGenCXX/mangle-class-nttp.cpp
+++ b/clang/test/CodeGenCXX/mangle-class-nttp.cpp
@@ -23,12 +23,13 @@ template void f<B{nullptr, 1}>();
// CHECK: define weak_odr void @_Z1fIXtl1BEEEvv(
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A at H0A@@@@YAXXZ"
template void f<B{nullptr}>();
-#ifndef _WIN32
-// FIXME: MSVC crashes on the first of these and mangles the second the same as
-// the nullptr version. Check the output is correct once we have a reference to
-// compare against.
+// These are extensions, but they seem like the obvious manglings.
// CHECK: define weak_odr void @_Z1fIXtl1BLPKi32EEEEvv(
+// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0CA at H0A@@@@YAXXZ"
template void f<B{fold((int*)32)}>();
+#ifndef _WIN32
+// FIXME: On MS ABI, we mangle this the same as nullptr, despite considering a
+// null pointer and zero bitcast to a pointer to be distinct pointer values.
// CHECK: define weak_odr void @_Z1fIXtl1BrcPKiLi0EEEEvv(
template void f<B{fold(reinterpret_cast<int*>(0))}>();
#endif
@@ -36,12 +37,14 @@ template void f<B{fold(reinterpret_cast<int*>(0))}>();
// Pointers to subobjects.
struct Nested { union { int k; int arr[2]; }; } nested[2];
struct Derived : A, Nested { int z; } extern derived;
+// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z7derivedE16EEEEvv
+// MSABI: define {{.*}} void @"??$f@$2UB@@PEBH56E?derived@@3UDerived@@Az@@@H0A@@@@YAXXZ"
+template void f<B{&derived.z}>();
+// FIXME: We don't know the MS ABI mangling for array subscripting and
+// past-the-end pointers yet.
#ifndef _WIN32
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z6nestedE_EEEEvv
-// FIXME: MSVC generates the garbage mangling ??$f@$2UB@@PEAH0A at H0A@@@@YAXXZ
-// for this.
template void f<B{&nested[0].k}>();
-// FIXME: MSVC crashes on these.
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z6nestedE16_0pEEEEvv
template void f<B{&nested[1].arr[2]}>();
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z7derivedE8pEEEEvv
@@ -53,15 +56,17 @@ template void f<B{fold(&derived.b + 3)}>();
// References to subobjects.
struct BR { const int &r; };
template<BR> void f() {}
+// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z7derivedE16EEEEvv
+// MSABI: define {{.*}} void @"??$f@$2UBR@@AEBH6E?derived@@3UDerived@@Az@@@@@YAXXZ"
+template void f<BR{derived.z}>();
+// FIXME: We don't know the MS ABI mangling for array subscripting yet.
#ifndef _WIN32
-// FIXME: MSVC produces garbage manglings for these.
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z6nestedE_EEEEvv
template void f<BR{nested[0].k}>();
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z6nestedE12_0EEEEvv
template void f<BR{nested[1].arr[1]}>();
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z7derivedE4EEEEvv
template void f<BR{derived.b}>();
-// FIXME: Crashes MSVC.
// CHECK: define weak_odr void @_Z1fIXtl2BRdecvPKiplcvPcadL_Z7derivedELl16EEEEvv
template void f<BR{fold(*(&derived.b + 3))}>();
#endif
@@ -69,8 +74,10 @@ template void f<BR{fold(*(&derived.b + 3))}>();
// Qualification conversions.
struct C { const int *p; };
template<C> void f() {}
+// CHECK: define weak_odr void @_Z1fIXtl1CadsoKiL_Z7derivedE16EEEEvv
+// MSABI: define {{.*}} void @"??$f@$2UC@@PEBH56E?derived@@3UDerived@@Az@@@@@@YAXXZ"
+template void f<C{&derived.z}>();
#ifndef _WIN32
-// FIXME: MSVC produces a garbage mangling for this.
// CHECK: define weak_odr void @_Z1fIXtl1CadsoKiL_Z7derivedE4EEEEvv
template void f<C{&derived.b}>();
#endif
@@ -118,8 +125,6 @@ template<E> void f() {}
// Union members.
// CHECK: define weak_odr void @_Z1fIXL1EEEEvv(
-// FIXME: MSVC rejects this; check this is the mangling MSVC uses when they
-// start accepting.
// MSABI: define {{.*}} @"??$f@$7TE@@@@@YAXXZ"
template void f<E{}>();
// CHECK: define weak_odr void @_Z1fIXtl1EEEEvv(
More information about the llvm-branch-commits
mailing list