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@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@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@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( _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits