forked from OSchip/llvm-project
[msabi] Mangle a template argument referring to array-to-pointer decay
applied to an array the same as the array itself. This follows MS ABI, and corrects a regression from the implementation of generalized non-type template parameters, where we "forgot" how to mangle this case.
This commit is contained in:
parent
e75a4b6ea9
commit
18e093faf7
|
@ -1466,6 +1466,21 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
|
|||
}
|
||||
}
|
||||
|
||||
/// If value V (with type T) represents a decayed pointer to the first element
|
||||
/// of an array, return that array.
|
||||
static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) {
|
||||
// Must be a pointer...
|
||||
if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() ||
|
||||
!V.getLValueBase())
|
||||
return nullptr;
|
||||
// ... to element 0 of an array.
|
||||
QualType BaseT = V.getLValueBase().getType();
|
||||
if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 ||
|
||||
V.getLValuePath()[0].getAsArrayIndex() != 0)
|
||||
return nullptr;
|
||||
return const_cast<ValueDecl*>(V.getLValueBase().dyn_cast<const ValueDecl*>());
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
|
||||
const TemplateArgument &TA,
|
||||
const NamedDecl *Parm) {
|
||||
|
@ -1576,6 +1591,14 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
|
|||
break;
|
||||
}
|
||||
case TemplateArgument::UncommonValue:
|
||||
if (ValueDecl *D = getAsArrayToPointerDecayedDecl(
|
||||
TA.getUncommonValueType(), TA.getAsUncommonValue())) {
|
||||
// Mangle the result of array-to-pointer decay as if it were a reference
|
||||
// to the original declaration, to match MSVC's behavior. This can result
|
||||
// in mangling collisions in some cases!
|
||||
return mangleTemplateArg(
|
||||
TD, TemplateArgument(D, TA.getUncommonValueType()), Parm);
|
||||
}
|
||||
Out << "$";
|
||||
if (cast<NonTypeTemplateParmDecl>(Parm)
|
||||
->getType()
|
||||
|
|
|
@ -4,6 +4,20 @@
|
|||
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix CXX20-X64 %s
|
||||
|
||||
// Check that array-to-pointer decay is mangled as the underlying declaration.
|
||||
extern const char arr[4] = "foo";
|
||||
template<const char*> struct Decay1 {};
|
||||
// CHECK: "?decay1@@3U?$Decay1@$1?arr@@3QBDB@@A"
|
||||
Decay1<arr> decay1;
|
||||
#if __cplusplus >= 201702L
|
||||
// Note that this mangling approach can lead to collisions.
|
||||
template<const void*> struct Decay2 {};
|
||||
// CXX20-X64: "?decay2a@@3U?$Decay2@$1?arr@@3QBDB@@A"
|
||||
Decay2<(const void*)arr> decay2a;
|
||||
// CXX20-X64: "?decay2b@@3U?$Decay2@$1?arr@@3QBDB@@A"
|
||||
Decay2<(const void*)&arr> decay2b;
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
class Class {
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue