Skip to content

Commit 18e093f

Browse files
committed
[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.
1 parent e75a4b6 commit 18e093f

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,6 +1466,21 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
14661466
}
14671467
}
14681468

1469+
/// If value V (with type T) represents a decayed pointer to the first element
1470+
/// of an array, return that array.
1471+
static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) {
1472+
// Must be a pointer...
1473+
if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() ||
1474+
!V.getLValueBase())
1475+
return nullptr;
1476+
// ... to element 0 of an array.
1477+
QualType BaseT = V.getLValueBase().getType();
1478+
if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 ||
1479+
V.getLValuePath()[0].getAsArrayIndex() != 0)
1480+
return nullptr;
1481+
return const_cast<ValueDecl*>(V.getLValueBase().dyn_cast<const ValueDecl*>());
1482+
}
1483+
14691484
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
14701485
const TemplateArgument &TA,
14711486
const NamedDecl *Parm) {
@@ -1576,6 +1591,14 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
15761591
break;
15771592
}
15781593
case TemplateArgument::UncommonValue:
1594+
if (ValueDecl *D = getAsArrayToPointerDecayedDecl(
1595+
TA.getUncommonValueType(), TA.getAsUncommonValue())) {
1596+
// Mangle the result of array-to-pointer decay as if it were a reference
1597+
// to the original declaration, to match MSVC's behavior. This can result
1598+
// in mangling collisions in some cases!
1599+
return mangleTemplateArg(
1600+
TD, TemplateArgument(D, TA.getUncommonValueType()), Parm);
1601+
}
15791602
Out << "$";
15801603
if (cast<NonTypeTemplateParmDecl>(Parm)
15811604
->getType()

clang/test/CodeGenCXX/mangle-ms-templates.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44
// 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
55
// 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
66

7+
// Check that array-to-pointer decay is mangled as the underlying declaration.
8+
extern const char arr[4] = "foo";
9+
template<const char*> struct Decay1 {};
10+
// CHECK: "?decay1@@3U?$Decay1@$1?arr@@3QBDB@@A"
11+
Decay1<arr> decay1;
12+
#if __cplusplus >= 201702L
13+
// Note that this mangling approach can lead to collisions.
14+
template<const void*> struct Decay2 {};
15+
// CXX20-X64: "?decay2a@@3U?$Decay2@$1?arr@@3QBDB@@A"
16+
Decay2<(const void*)arr> decay2a;
17+
// CXX20-X64: "?decay2b@@3U?$Decay2@$1?arr@@3QBDB@@A"
18+
Decay2<(const void*)&arr> decay2b;
19+
#endif
20+
721
template<typename T>
822
class Class {
923
public:

0 commit comments

Comments
 (0)