cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
378 lines
13 KiB
C++
378 lines
13 KiB
C++
// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
|
|
// RUN: %clang_cc1 -std=c++11 -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++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
|
|
// 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:
|
|
Class() {}
|
|
};
|
|
|
|
class Typename { };
|
|
|
|
template<typename T>
|
|
class Nested { };
|
|
|
|
template<bool flag>
|
|
class BoolTemplate {
|
|
public:
|
|
BoolTemplate() {}
|
|
};
|
|
|
|
template<int param>
|
|
class IntTemplate {
|
|
public:
|
|
IntTemplate() {}
|
|
};
|
|
|
|
template<unsigned param>
|
|
class UnsignedIntTemplate {
|
|
public:
|
|
UnsignedIntTemplate() {}
|
|
};
|
|
|
|
template<long long param>
|
|
class LongLongTemplate {
|
|
public:
|
|
LongLongTemplate() {}
|
|
};
|
|
|
|
template<unsigned long long param>
|
|
class UnsignedLongLongTemplate {
|
|
public:
|
|
UnsignedLongLongTemplate() {}
|
|
};
|
|
|
|
template<>
|
|
class BoolTemplate<true> {
|
|
public:
|
|
BoolTemplate() {}
|
|
template<class T> void Foo(T arg) {}
|
|
};
|
|
|
|
void template_mangling() {
|
|
Class<Typename> c1;
|
|
// CHECK: call {{.*}} @"??0?$Class@VTypename@@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@VTypename@@@@QEAA@XZ"
|
|
|
|
Class<const Typename> c1_const;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$CBVTypename@@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$CBVTypename@@@@QEAA@XZ"
|
|
Class<volatile Typename> c1_volatile;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$CCVTypename@@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$CCVTypename@@@@QEAA@XZ"
|
|
Class<const volatile Typename> c1_cv;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$CDVTypename@@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$CDVTypename@@@@QEAA@XZ"
|
|
|
|
Class<Nested<Typename> > c2;
|
|
// CHECK: call {{.*}} @"??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
|
|
|
|
Class<int * const> c_intpc;
|
|
// CHECK: call {{.*}} @"??0?$Class@QAH@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@QEAH@@QEAA@XZ"
|
|
Class<int()> c_ft;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$A6AHXZ@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$A6AHXZ@@QEAA@XZ"
|
|
Class<int[]> c_inti;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$BY0A@H@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$BY0A@H@@QEAA@XZ"
|
|
Class<int[5]> c_int5;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$BY04H@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$BY04H@@QEAA@XZ"
|
|
Class<const int[5]> c_intc5;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$BY04$$CBH@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$BY04$$CBH@@QEAA@XZ"
|
|
Class<int * const[5]> c_intpc5;
|
|
// CHECK: call {{.*}} @"??0?$Class@$$BY04QAH@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$Class@$$BY04QEAH@@QEAA@XZ"
|
|
|
|
BoolTemplate<false> _false;
|
|
// CHECK: call {{.*}} @"??0?$BoolTemplate@$0A@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$BoolTemplate@$0A@@@QEAA@XZ"
|
|
|
|
BoolTemplate<true> _true;
|
|
// PR13158
|
|
_true.Foo(1);
|
|
// CHECK: call {{.*}} @"??0?$BoolTemplate@$00@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$BoolTemplate@$00@@QEAA@XZ"
|
|
// CHECK: call {{.*}} @"??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
|
|
// X64: call {{.*}} @"??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
|
|
|
|
IntTemplate<0> zero;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0A@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0A@@@QEAA@XZ"
|
|
|
|
IntTemplate<5> five;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$04@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$04@@QEAA@XZ"
|
|
|
|
IntTemplate<11> eleven;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0L@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0L@@@QEAA@XZ"
|
|
|
|
IntTemplate<256> _256;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0BAA@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0BAA@@@QEAA@XZ"
|
|
|
|
IntTemplate<513> _513;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0CAB@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0CAB@@@QEAA@XZ"
|
|
|
|
IntTemplate<1026> _1026;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0EAC@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0EAC@@@QEAA@XZ"
|
|
|
|
IntTemplate<65535> ffff;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0PPPP@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
|
|
|
|
IntTemplate<-1> neg_1;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0?0@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0?0@@QEAA@XZ"
|
|
IntTemplate<-9> neg_9;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0?8@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0?8@@QEAA@XZ"
|
|
IntTemplate<-10> neg_10;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0?9@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0?9@@QEAA@XZ"
|
|
IntTemplate<-11> neg_11;
|
|
// CHECK: call {{.*}} @"??0?$IntTemplate@$0?L@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$IntTemplate@$0?L@@@QEAA@XZ"
|
|
|
|
UnsignedIntTemplate<4294967295> ffffffff;
|
|
// CHECK: call {{.*}} @"??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ"
|
|
|
|
LongLongTemplate<-9223372036854775807LL-1LL> int64_min;
|
|
// CHECK: call {{.*}} @"??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ"
|
|
LongLongTemplate<9223372036854775807LL> int64_max;
|
|
// CHECK: call {{.*}} @"??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
|
|
UnsignedLongLongTemplate<18446744073709551615ULL> uint64_max;
|
|
// CHECK: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
|
|
UnsignedLongLongTemplate<(unsigned long long)-1> uint64_neg_1;
|
|
// CHECK: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
|
|
// X64: call {{.*}} @"??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
|
|
}
|
|
|
|
namespace space {
|
|
template<class T> const T& foo(const T& l) { return l; }
|
|
}
|
|
// CHECK: "??$foo@H@space@@YAABHABH@Z"
|
|
// X64: "??$foo@H@space@@YAAEBHAEBH@Z"
|
|
|
|
void use() {
|
|
space::foo(42);
|
|
}
|
|
|
|
// PR13455
|
|
typedef void (*FunctionPointer)(void);
|
|
|
|
template <FunctionPointer function>
|
|
void FunctionPointerTemplate() {
|
|
function();
|
|
}
|
|
|
|
void spam() {
|
|
FunctionPointerTemplate<spam>();
|
|
// CHECK: "??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
|
|
// X64: "??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
|
|
}
|
|
|
|
// Unlike Itanium, there is no character code to indicate an argument pack.
|
|
// Tested with MSVC 2013, the first version which supports variadic templates.
|
|
|
|
template <typename ...Ts> void variadic_fn_template(const Ts &...args);
|
|
template <typename... Ts, typename... Us>
|
|
void multi_variadic_fn(Ts... ts, Us... us);
|
|
template <typename... Ts, typename C, typename... Us>
|
|
void multi_variadic_mixed(Ts... ts, C c, Us... us);
|
|
void variadic_fn_instantiate() {
|
|
variadic_fn_template(0, 1, 3, 4);
|
|
variadic_fn_template(0, 1, 'a', "b");
|
|
|
|
// Directlly consecutive packs are separated by $$Z...
|
|
multi_variadic_fn<int, int>(1, 2, 3, 4, 5);
|
|
multi_variadic_fn<int, int, int>(1, 2, 3, 4, 5);
|
|
|
|
// ...but not if another template parameter is between them.
|
|
multi_variadic_mixed<int, int>(1, 2, 3);
|
|
multi_variadic_mixed<int, int>(1, 2, 3, 4);
|
|
}
|
|
// CHECK: "??$variadic_fn_template@HHHH@@YAXABH000@Z"
|
|
// X64: "??$variadic_fn_template@HHHH@@YAXAEBH000@Z"
|
|
// CHECK: "??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
|
|
// X64: "??$variadic_fn_template@HHD$$BY01D@@YAXAEBH0AEBDAEAY01$$CBD@Z"
|
|
// CHECK: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z"
|
|
// X64: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z"
|
|
// CHECK: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z"
|
|
// X64: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z"
|
|
// CHECK: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z"
|
|
// X64: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z"
|
|
// CHECK: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z"
|
|
// X64: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z"
|
|
|
|
template <typename ...Ts>
|
|
struct VariadicClass {
|
|
VariadicClass() { }
|
|
int x;
|
|
};
|
|
void variadic_class_instantiate() {
|
|
VariadicClass<int, char, bool> a;
|
|
VariadicClass<bool, char, int> b;
|
|
}
|
|
// CHECK: call {{.*}} @"??0?$VariadicClass@HD_N@@QAE@XZ"
|
|
// CHECK: call {{.*}} @"??0?$VariadicClass@_NDH@@QAE@XZ"
|
|
|
|
template <typename T>
|
|
struct Second {};
|
|
|
|
template <typename T, template <class> class>
|
|
struct Type {};
|
|
|
|
template <template <class> class T>
|
|
struct Type2 {};
|
|
|
|
template <template <class> class T, bool B>
|
|
struct Thing;
|
|
|
|
template <template <class> class T>
|
|
struct Thing<T, false> { };
|
|
|
|
template <template <class> class T>
|
|
struct Thing<T, true> { };
|
|
|
|
void template_template_fun(Type<Thing<Second, true>, Second>) { }
|
|
// CHECK: "?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z"
|
|
|
|
template <typename T>
|
|
void template_template_specialization();
|
|
|
|
template <>
|
|
void template_template_specialization<void (Type<Thing<Second, true>, Second>)>() {
|
|
}
|
|
// CHECK: "??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ"
|
|
|
|
// PR16788
|
|
template <decltype(nullptr)> struct S1 {};
|
|
void f(S1<nullptr>) {}
|
|
// CHECK: "?f@@YAXU?$S1@$0A@@@@Z"
|
|
|
|
struct record {
|
|
int first;
|
|
int second;
|
|
};
|
|
template <const record &>
|
|
struct type1 {
|
|
};
|
|
extern const record inst;
|
|
void recref(type1<inst>) {}
|
|
// CHECK: "?recref@@YAXU?$type1@$1?inst@@3Urecord@@B@@@Z"
|
|
|
|
struct _GUID {};
|
|
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
|
|
|
|
template <typename T, const _GUID *G = &__uuidof(T)>
|
|
struct UUIDType1 {};
|
|
|
|
template <typename T, const _GUID &G = __uuidof(T)>
|
|
struct UUIDType2 {};
|
|
|
|
void fun(UUIDType1<uuid> a) {}
|
|
// CHECK: "?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
|
|
void fun(UUIDType2<uuid> b) {}
|
|
// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
|
|
|
|
template <typename T> struct TypeWithFriendDefinition {
|
|
friend void FunctionDefinedWithInjectedName(TypeWithFriendDefinition<T>) {}
|
|
};
|
|
// CHECK: call {{.*}} @"?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
|
|
void CallFunctionDefinedWithInjectedName() {
|
|
FunctionDefinedWithInjectedName(TypeWithFriendDefinition<int>());
|
|
}
|
|
// CHECK: @"?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
|
|
|
|
// We need to be able to feed GUIDs through a couple rounds of template
|
|
// substitution.
|
|
template <const _GUID *G>
|
|
struct UUIDType3 {
|
|
void foo() {}
|
|
};
|
|
template <const _GUID *G>
|
|
struct UUIDType4 : UUIDType3<G> {
|
|
void bar() { UUIDType4::foo(); }
|
|
};
|
|
template struct UUIDType4<&__uuidof(uuid)>;
|
|
// CHECK: "?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
|
|
// CHECK: "?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
|
|
|
|
#ifdef _WIN64
|
|
template<__int128 N> struct Int128 {};
|
|
template<unsigned __int128 N> struct UInt128 {};
|
|
// X64: define {{.*}} @"?fun_int128@@YAXU?$Int128@$0A@@@@Z"(
|
|
void fun_int128(Int128<0>) {}
|
|
// X64: define {{.*}} @"?fun_int128@@YAXU?$Int128@$0?0@@@Z"(
|
|
void fun_int128(Int128<-1>) {}
|
|
// X64: define {{.*}} @"?fun_int128@@YAXU?$Int128@$0DPPPPPPPPPPPPPPPAAAAAAAAAAAAAAAB@@@@Z"(
|
|
void fun_int128(Int128<(__int128)9223372036854775807 * (__int128)9223372036854775807>) {}
|
|
// X64: define {{.*}} @"?fun_uint128@@YAXU?$UInt128@$0A@@@@Z"(
|
|
void fun_uint128(UInt128<0>) {}
|
|
// X64: define {{.*}} @"?fun_uint128@@YAXU?$UInt128@$0?0@@@Z"(
|
|
void fun_uint128(UInt128<(unsigned __int128)-1>) {}
|
|
// X64: define {{.*}} @"?fun_uint128@@YAXU?$UInt128@$0DPPPPPPPPPPPPPPPAAAAAAAAAAAAAAAB@@@@Z"(
|
|
void fun_uint128(UInt128<(unsigned __int128)9223372036854775807 * (unsigned __int128)9223372036854775807>) {}
|
|
#endif
|
|
|
|
#if __cplusplus >= 202002L
|
|
|
|
template<float> struct Float {};
|
|
// CXX20-X64: define {{.*}} @"?f@@YAXU?$Float@$ADPIAAAAA@@@@Z"(
|
|
void f(Float<1.0f>) {}
|
|
template<auto> struct Auto {};
|
|
// CXX20-X64: define {{.*}} @"?f@@YAXU?$Auto@$MMADPIAAAAA@@@@Z"(
|
|
void f(Auto<1.0f>) {}
|
|
|
|
struct S2 {
|
|
int arr[2][3];
|
|
int i;
|
|
void fn();
|
|
} s2;
|
|
|
|
template<int&> struct TplSubobjectRef {};
|
|
// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplSubobjectRef@$CC61?s2@@3US2@@Aarr@@00@01@@@@Z"(
|
|
void f(TplSubobjectRef<s2.arr[1][2]>) {}
|
|
template<int*> struct TplSubobjectPtr {};
|
|
// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplSubobjectPtr@$CC61?s2@@3US2@@Aarr@@00@01@@@@Z"(
|
|
void f(TplSubobjectPtr<&s2.arr[1][2]>) {}
|
|
|
|
struct Derived : S2 {};
|
|
|
|
template <int Derived::*> struct TplMemberPtr {};
|
|
// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplMemberPtr@$0BI@@@@Z"(
|
|
void f(TplMemberPtr<(int Derived::*)&S2::i>) {}
|
|
template <void (Derived::*)()> struct TplMemberFnPtr {};
|
|
// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplMemberFnPtr@$1?fn@S2@@QEAAXXZ@@@Z"(
|
|
void f(TplMemberFnPtr<(void (Derived::*)())&S2::fn>) {}
|
|
|
|
#endif
|