330 changes: 234 additions & 96 deletions clang/lib/AST/ItaniumMangle.cpp

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions clang/test/CodeGen/enable_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,36 @@ void bar(int m) __attribute__((overloadable, enable_if(m > 0, "")));
void bar(int m) __attribute__((overloadable, enable_if(1, "")));
// CHECK-LABEL: define{{.*}} void @test2
void test2() {
// CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi
void (*p)(int) = bar;
// CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi
void (*p2)(int) = &bar;
// CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi
p = bar;
// CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi
p = &bar;

// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*)
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*)
void *vp1 = (void*)&bar;
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*)
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*)
void *vp2 = (void*)bar;
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*)
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*)
vp1 = (void*)&bar;
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*)
// CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*)
vp1 = (void*)bar;
}

void baz(int m) __attribute__((overloadable, enable_if(1, "")));
void baz(int m) __attribute__((overloadable));
// CHECK-LABEL: define{{.*}} void @test3
void test3() {
// CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi
void (*p)(int) = baz;
// CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi
void (*p2)(int) = &baz;
// CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi
p = baz;
// CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi
// CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi
p = &baz;
}

Expand All @@ -71,13 +71,13 @@ void qux(int m) __attribute__((overloadable, enable_if(1, ""),
void qux(int m) __attribute__((overloadable, enable_if(1, "")));
// CHECK-LABEL: define{{.*}} void @test4
void test4() {
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
// CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi
void (*p)(int) = qux;
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
// CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi
void (*p2)(int) = &qux;
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
// CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi
p = qux;
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
// CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi
p = &qux;
}

Expand All @@ -90,6 +90,6 @@ void test5() {
int foo(char *i __attribute__((pass_object_size(0))))
__attribute__((enable_if(1, ""), overloadable));

// CHECK: call i32 @_Z3fooUa9enable_ifIXLi1EEEPcU17pass_object_size0
// CHECK: call i32 @_Z3fooUa9enable_ifILi1EEPcU17pass_object_size0
foo((void*)0);
}
99 changes: 90 additions & 9 deletions clang/test/CodeGenCXX/clang-abi-compat.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s
// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s
// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17 %s
// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - -Wno-c++11-extensions \
// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.8 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.9 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=4.0 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=5 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s
// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE12-CXX20 %s
// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - -Wno-c++11-extensions \
// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s
// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - \
// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20 %s

typedef __attribute__((vector_size(8))) long long v1xi64;
void clang39(v1xi64) {}
Expand Down Expand Up @@ -55,3 +66,73 @@ template void clang12_b<arr>();
// CHECK: @_Z9clang12_cIXadL_Z3arrEEEvv
template<const char (*)[6]> void clang12_c() {}
template void clang12_c<&arr>();


/// Tests for <template-arg> <expr-primary> changes in clang12:
namespace expr_primary {
struct A {
template<int N> struct Int {};
template<int& N> struct Ref {};
};

/// Check various DeclRefExpr manglings

// PRE12: @_ZN12expr_primary5test1INS_1AEEEvNT_3IntIXLi1EEEE
// V12: @_ZN12expr_primary5test1INS_1AEEEvNT_3IntILi1EEE
template <typename T> void test1(typename T::template Int<1> a) {}
template void test1<A>(typename A::template Int<1> a);

enum Enum { EnumVal = 4 };
int Global;

// PRE12: @_ZN12expr_primary5test2INS_1AEEEvNT_3IntIXLNS_4EnumE4EEEE
// V12: @_ZN12expr_primary5test2INS_1AEEEvNT_3IntILNS_4EnumE4EEE
template <typename T> void test2(typename T::template Int<EnumVal> a) {}
template void test2<A>(typename A::template Int<4> a);

// CHECK: @_ZN12expr_primary5test3ILi3EEEvNS_1A3IntIXT_EEE
template <int X> void test3(typename A::template Int<X> a) {}
template void test3<3>(A::Int<3> a);

#if __cplusplus >= 202002L
// CHECK-CXX20: @_ZN12expr_primary5test4INS_1AEEEvNT_3RefIL_ZNS_6GlobalEEEE
template <typename T> void test4(typename T::template Ref<(Global)> a) {}
template void test4<A>(typename A::template Ref<Global> a);

struct B {
struct X {
constexpr X(double) {}
constexpr X(int&) {}
};
template<X> struct Y {};
};

// PRE12-CXX20: _ZN12expr_primary5test5INS_1BEEEvNT_1YIXLd3ff0000000000000EEEE
// V12-CXX20: _ZN12expr_primary5test5INS_1BEEEvNT_1YILd3ff0000000000000EEE
template<typename T> void test5(typename T::template Y<1.0>) { }
template void test5<B>(typename B::Y<1.0>);

// PRE12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIL_ZZNS_5test6EiE1bEEEi
// V12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIXfp_EEEi
template<typename T> auto test6(int b) -> typename T::template Y<b> { return {}; }
template auto test6<B>(int b) -> B::Y<b>;
#endif

/// Verify non-dependent type-traits within a dependent template arg.

// PRE12: @_ZN12expr_primary5test7INS_1AEEEvNT_3IntIXLm1EEEE
// V12: @_ZN12expr_primary5test7INS_1AEEEvNT_3IntILm1EEE
template <class T> void test7(typename T::template Int<sizeof(char)> a) {}
template void test7<A>(A::Int<1>);

// PRE12: @_ZN12expr_primary5test8ILi2EEEvu11matrix_typeIXLi1EEXT_EiE
// V12: @_ZN12expr_primary5test8ILi2EEEvu11matrix_typeILi1EXT_EiE
template<int N> using matrix1xN = int __attribute__((matrix_type(1, N)));
template<int N> void test8(matrix1xN<N> a) {}
template void test8<2>(matrix1xN<2> a);

// PRE12: @_ZN12expr_primary5test9EUa9enable_ifIXLi1EEEv
// V12: @_ZN12expr_primary5test9EUa9enable_ifILi1EEv
void test9(void) __attribute__((enable_if(1, ""))) {}

}
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/enable_if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ int test5(int);
template <typename T>
T test5(T) __attribute__((enable_if(1, "better than non-template")));

// CHECK: @_Z5test5IiEUa9enable_ifIXLi1EEET_S0_
// CHECK: @_Z5test5IiEUa9enable_ifILi1EET_S0_
int (*Ptr)(int) = &test5;

// Test itanium mangling for attribute enable_if
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/mangle-abi-tag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ namespace pr30440 {
template<class F> void g(F);
template<class ...A> auto h(A ...a)->decltype (g (0, g < a > (a) ...)) {
}
// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIL_ZZNS_1hEDpT_E1aEEfp_EEES2_(
// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIXfp_EEfp_EEEDpT_(

void pr30440_test () {
h();
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CodeGenCXX/mangle-alignof.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -std=c++11 -Wno-gnu-alignof-expression -emit-llvm %s -o - -triple=%itanium_abi_triple | FileCheck %s --check-prefix=CHECK-NEW
// RUN: %clang_cc1 -std=c++11 -Wno-gnu-alignof-expression -emit-llvm %s -o - -triple=%itanium_abi_triple -fclang-abi-compat=11 | FileCheck %s --check-prefix=CHECK-OLD

// Verify the difference in mangling for alignof and __alignof__ in a new ABI
// compat mode.

template <class T> void f1(decltype(alignof(T))) {}
template void f1<int>(__SIZE_TYPE__);
// CHECK-OLD: void @_Z2f1IiEvDTatT_E
// CHECK-NEW: void @_Z2f1IiEvDTatT_E

template <class T> void f2(decltype(__alignof__(T))) {}
template void f2<int>(__SIZE_TYPE__);
// CHECK-OLD: void @_Z2f2IiEvDTatT_E
// CHECK-NEW: void @_Z2f2IiEvDTu11__alignof__T_E

template <class T> void f3(decltype(alignof(T(0)))) {}
template void f3<int>(__SIZE_TYPE__);
// CHECK-OLD: void @_Z2f3IiEvDTazcvT_Li0EE
// CHECK-NEW: void @_Z2f3IiEvDTazcvT_Li0EE

template <class T> void f4(decltype(__alignof__(T(0)))) {}
template void f4<int>(__SIZE_TYPE__);
// CHECK-OLD: void @_Z2f4IiEvDTazcvT_Li0EE
// CHECK-NEW: void @_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/mangle-concept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ template <bool> struct S {};
template <typename> concept C = true;
template <typename T = int> S<C<T>> f0() { return S<C<T>>{}; }
template S<C<int>> f0<>();
// CHECK: @_ZN5test12f0IiEENS_1SIXL_ZNS_1CIT_EEEEEEv(
// CHECK: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv(
}

template <bool> struct S {};
template <typename> concept C = true;
template <typename T = int> S<C<T>> f0() { return S<C<T>>{}; }
template S<C<int>> f0<>();
// CHECK: @_Z2f0IiE1SIXL_Z1CIT_EEEEv(
// CHECK: @_Z2f0IiE1SIL_Z1CIT_EEEv(
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/mangle-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ namespace test17 {
// Note: there is no J...E here, because we can't form a pack argument, and
// the 5u and 6u are mangled with the original type 'j' (unsigned int) not
// with the resolved type 'i' (signed int).
// CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_EXLj5EEXT_EXLj6EEEE
// CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_ELj5EXT_ELj6EEE
template<int D, int ...C> void h(X<C..., 5u, D, 6u>) {}
void i() { h<4, 1, 2, 3>({}); }

Expand Down Expand Up @@ -323,7 +323,7 @@ namespace partially_dependent_template_args {
// callee is unresolved, the rest mangle the converted argument Lj0E
// because the callee is resolved.
void h() {
// CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fIXLi0EEEcvT__EEE
// CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fILi0EEcvT__EEE
g1<X>({});
// CHECK: @_ZN33partially_dependent_template_args5test22g2IiEEvDTplclL_ZNS0_1fILj0EEEiNS0_1XEEilEEcvT__EE
g2<int>({});
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ namespace test56 {
namespace test57 {
struct X { template <int N> int f(); } x;
template<int N> void f(decltype(x.f<0>() + N)) {}
// CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fIXLi0EEEET_E
// CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E
template void f<0>(int);
}

Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGenCXX/matrix-type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,14 @@ void test_template_deduction() {
// CHECK-NEXT: %m4 = alloca [144 x float], align 4
// CHECK-NEXT: %v = alloca %struct.selector.3, align 1
// CHECK-NEXT: %undef.agg.tmp4 = alloca %struct.selector.3, align 1
// CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeIXLm10EEXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m0)
// CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m0)
// CHECK-NEXT: call void @_Z10use_matrixIiE8selectorILi2EERu11matrix_typeILm10ELm10ET_E([100 x i32]* nonnull align 4 dereferenceable(400) %m1)
// CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_EXLm10EET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m2)
// CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m2)
// CHECK-NEXT: call void @_Z10use_matrixIiLm12ELm12EE8selectorILi0EERu11matrix_typeIXT0_EXT1_ET_E([144 x i32]* nonnull align 4 dereferenceable(576) %m3)
// CHECK-NEXT: call void @_Z10use_matrixILm12ELm12EE8selectorILi4EERu11matrix_typeIXT_EXT0_EfE([144 x float]* nonnull align 4 dereferenceable(576) %m4)
// CHECK-NEXT: ret void

// CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeIXLm10EEXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m)
// CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m)
// CHECK-NEXT: entry:
// CHECK-NEXT: %m.addr = alloca [120 x i32]*, align 8
// CHECK-NEXT: store [120 x i32]* %m, [120 x i32]** %m.addr, align 8
Expand All @@ -236,7 +236,7 @@ void test_template_deduction() {
// CHECK-NEXT: call void @llvm.trap()
// CHECK-NEXT: unreachable

// CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_EXLm10EET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m)
// CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m)
// CHECK-NEXT: entry:
// CHECK-NEXT: %m.addr = alloca [120 x i32]*, align 8
// CHECK-NEXT: store [120 x i32]* %m, [120 x i32]** %m.addr, align 8
Expand Down Expand Up @@ -277,10 +277,10 @@ void test_auto_t() {
// CHECK-LABEL: define{{.*}} void @_Z11test_auto_tv()
// CHECK-NEXT: entry:
// CHECK-NEXT: %m = alloca [130 x i32], align 4
// CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_EXLm10EEiE([130 x i32]* nonnull align 4 dereferenceable(520) %m)
// CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE([130 x i32]* nonnull align 4 dereferenceable(520) %m)
// CHECK-NEXT: ret void

// CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_EXLm10EEiE([130 x i32]* nonnull align 4 dereferenceable(520) %m)
// CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE([130 x i32]* nonnull align 4 dereferenceable(520) %m)
// CHECK-NEXT: entry:
// CHECK-NEXT: %m.addr = alloca [130 x i32]*, align 8
// CHECK-NEXT: store [130 x i32]* %m, [130 x i32]** %m.addr, align 8
Expand Down Expand Up @@ -326,7 +326,7 @@ void test_use_matrix_2() {
// CHECK-NEXT: store <40 x float> %call, <40 x float>* %0, align 4
// CHECK-NEXT: call void @_Z12use_matrix_2ILm2ELm12EE8selectorILi0EERu11matrix_typeIXplT_Li2EEXdvT0_Li2EEiERu11matrix_typeIXT_EXT0_EfE([24 x i32]* nonnull align 4 dereferenceable(96) %m1, [24 x float]* nonnull align 4 dereferenceable(96) %m2)
// CHECK-NEXT: call void @_Z12use_matrix_2ILm5ELm8EE8selectorILi1EERu11matrix_typeIXplT_T0_EXT0_EiERu11matrix_typeIXT_EXmiT0_T_EfE([104 x i32]* nonnull align 4 dereferenceable(416) %m3, [15 x float]* nonnull align 4 dereferenceable(60) %m4)
// CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_EXLm10EEiE([50 x i32]* nonnull align 4 dereferenceable(200) %m5)
// CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE([50 x i32]* nonnull align 4 dereferenceable(200) %m5)
// CHECK-NEXT: %1 = bitcast [20 x float]* %r4 to <20 x float>*
// CHECK-NEXT: store <20 x float> %call2, <20 x float>* %1, align 4
// CHECK-NEXT: call void @_Z12use_matrix_3ILm6EE8selectorILi2EERu11matrix_typeIXmiT_Li2EEXT_EiE([24 x i32]* nonnull align 4 dereferenceable(96) %m1)
Expand Down Expand Up @@ -357,7 +357,7 @@ void test_use_matrix_2() {
// CHECK-NEXT: call void @llvm.trap()
// CHECK-NEXT: unreachable

// CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_EXLm10EEiE([50 x i32]* nonnull align 4 dereferenceable(200) %m1)
// CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE([50 x i32]* nonnull align 4 dereferenceable(200) %m1)
// CHECK-NEXT: entry:
// CHECK-NEXT: %m1.addr = alloca [50 x i32]*, align 8
// CHECK-NEXT: store [50 x i32]* %m1, [50 x i32]** %m1.addr, align 8
Expand Down
42 changes: 28 additions & 14 deletions clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s
// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s --check-prefixes=CHECK,CHECK-V12
// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions -fclang-abi-compat=11 | FileCheck %s --check-prefixes=CHECK,CHECK-V11
// rdar://17784718

typedef struct _GUID
Expand All @@ -24,11 +25,16 @@ struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) TestStruct

struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) OtherStruct {};

template <class T> void test_uuidofType(void *arg[sizeof(__uuidof(T))] = 0) {}
template <class T> void test_uuidofType(decltype(__uuidof(T)) arg) {}

template <class T> void test_uuidofExpr(void *arg[sizeof(__uuidof(typename T::member))] = 0) {}
template <class T> void test_uuidofExpr(decltype(__uuidof(T::member)) arg) {}

struct HasMember { typedef TestStruct member; };
struct HasMember {
TestStruct member;
};

// Ensure that mangling an "expr-primary" argument is handled properly.
template <class T> void test_uuidofExpr2(decltype(T{}, __uuidof(HasMember::member)) arg) {}

template<const GUID&> struct UUIDTestTwo { UUIDTestTwo(); };

Expand All @@ -39,19 +45,27 @@ int main(int argc, const char * argv[])
// type had better not mention TestStruct or OtherStruct!
UUIDTestTwo<__uuidof(TestStruct)> uuidof_test2;
UUIDTestTwo<__uuidof(OtherStruct)> uuidof_test3;
test_uuidofType<TestStruct>();
test_uuidofExpr<HasMember>();
test_uuidofType<TestStruct>(GUID{});
test_uuidofExpr<HasMember>(GUID{});
test_uuidofExpr2<TestStruct>(GUID{});
return 0;
}

// CHECK: define{{.*}} i32 @main
// CHECK: call void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev
// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev
// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev
// CHECK: call void @_Z15test_uuidofTypeI10TestStructEvPPv(i8** null)
// CHECK: call void @_Z15test_uuidofExprI9HasMemberEvPPv(i8** null)

// CHECK: call void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev(
// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev(
// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev(
// CHECK-V11: call void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E(
// CHECK-V12: call void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE(
// CHECK-V11: call void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofzsrT_6memberE(
// CHECK-V12: call void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE(
// CHECK-V11: call void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofzL_ZN9HasMember6memberEEE(
// CHECK-V12: call void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofL_ZN9HasMember6memberEEEE(
// CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev
// CHECK: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvPPv
// CHECK: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvPPv
// CHECK-V11: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E(
// CHECK-V12: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE(
// CHECK-V11: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofzsrT_6memberE(
// CHECK-V12: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE(
// CHECK-V11: define linkonce_odr void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofzL_ZN9HasMember6memberEEE(
// CHECK-V12: define linkonce_odr void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofL_ZN9HasMember6memberEEEE(
// CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC2Ev
68 changes: 37 additions & 31 deletions libcxxabi/src/demangle/ItaniumDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@
X(InitListExpr) \
X(FoldExpr) \
X(ThrowExpr) \
X(UUIDOfExpr) \
X(BoolExpr) \
X(StringLiteral) \
X(LambdaExpr) \
Expand Down Expand Up @@ -2035,21 +2034,6 @@ class ThrowExpr : public Node {
}
};

// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
class UUIDOfExpr : public Node {
Node *Operand;
public:
UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}

template<typename Fn> void match(Fn F) const { F(Operand); }

void printLeft(OutputStream &S) const override {
S << "__uuidof(";
Operand->print(S);
S << ")";
}
};

class BoolExpr : public Node {
bool Value;

Expand Down Expand Up @@ -5013,6 +4997,43 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
}
}
return nullptr;
case 'u': {
++First;
Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
if (!Name)
return nullptr;
// Special case legacy __uuidof mangling. The 't' and 'z' appear where the
// standard encoding expects a <template-arg>, and would be otherwise be
// interpreted as <type> node 'short' or 'ellipsis'. However, neither
// __uuidof(short) nor __uuidof(...) can actually appear, so there is no
// actual conflict here.
if (Name->getBaseName() == "__uuidof") {
if (numLeft() < 2)
return nullptr;
if (*First == 't') {
++First;
Node *Ty = getDerived().parseType();
if (!Ty)
return nullptr;
return make<CallExpr>(Name, makeNodeArray(&Ty, &Ty + 1));
}
if (*First == 'z') {
++First;
Node *Ex = getDerived().parseExpr();
if (!Ex)
return nullptr;
return make<CallExpr>(Name, makeNodeArray(&Ex, &Ex + 1));
}
}
size_t ExprsBegin = Names.size();
while (!consumeIf('E')) {
Node *E = getDerived().parseTemplateArg();
if (E == nullptr)
return E;
Names.push_back(E);
}
return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));
}
case '1':
case '2':
case '3':
Expand All @@ -5024,21 +5045,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
case '9':
return getDerived().parseUnresolvedName();
}

if (consumeIf("u8__uuidoft")) {
Node *Ty = getDerived().parseType();
if (!Ty)
return nullptr;
return make<UUIDOfExpr>(Ty);
}

if (consumeIf("u8__uuidofz")) {
Node *Ex = getDerived().parseExpr();
if (!Ex)
return nullptr;
return make<UUIDOfExpr>(Ex);
}

return nullptr;
}

Expand Down
14 changes: 12 additions & 2 deletions libcxxabi/test/test_demangle.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29776,8 +29776,18 @@ const char* cases[][2] =
// Vendor extension types are substitution candidates.
{"_Z1fu3fooS_", "f(foo, foo)"},

{"_ZN3FooIXu8__uuidofzdeL_Z3sucEEEC1Ev", "Foo<__uuidof(*(suc))>::Foo()"},
{"_ZN3FooIXu8__uuidoft13SomeUUIDClassEEC1Ev", "Foo<__uuidof(SomeUUIDClass)>::Foo()"},
// alignof with type and expression, and __alignof__ with the same.
{"_Z2f1IiEvDTatT_E", "void f1<int>(decltype(alignof (int)))"},
{"_Z2f3IiEvDTazcvT_Li0EE", "void f3<int>(decltype(alignof ((int)(0))))"},
{"_Z2f2IiEvDTu11__alignof__T_EE", "void f2<int>(decltype(__alignof__(int)))"},
{"_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE", "void f4<int>(decltype(__alignof__((int)(0))))"},

// Legacy nonstandard mangling for __uuidof.
{"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E", "void test_uuidofType<TestStruct>(decltype(__uuidof(TestStruct)))"},
{"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr<HasMember>(decltype(__uuidof(HasMember::member)))"},
// Current __uuidof mangling using vendor extended expression.
{"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE", "void test_uuidofType<TestStruct>(decltype(__uuidof(TestStruct)))"},
{"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr<HasMember>(decltype(__uuidof(HasMember::member)))"},

// C++2a char8_t:
{"_ZTSPDu", "typeinfo name for char8_t*"},
Expand Down
68 changes: 37 additions & 31 deletions llvm/include/llvm/Demangle/ItaniumDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@
X(InitListExpr) \
X(FoldExpr) \
X(ThrowExpr) \
X(UUIDOfExpr) \
X(BoolExpr) \
X(StringLiteral) \
X(LambdaExpr) \
Expand Down Expand Up @@ -2035,21 +2034,6 @@ class ThrowExpr : public Node {
}
};

// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
class UUIDOfExpr : public Node {
Node *Operand;
public:
UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}

template<typename Fn> void match(Fn F) const { F(Operand); }

void printLeft(OutputStream &S) const override {
S << "__uuidof(";
Operand->print(S);
S << ")";
}
};

class BoolExpr : public Node {
bool Value;

Expand Down Expand Up @@ -5013,6 +4997,43 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
}
}
return nullptr;
case 'u': {
++First;
Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
if (!Name)
return nullptr;
// Special case legacy __uuidof mangling. The 't' and 'z' appear where the
// standard encoding expects a <template-arg>, and would be otherwise be
// interpreted as <type> node 'short' or 'ellipsis'. However, neither
// __uuidof(short) nor __uuidof(...) can actually appear, so there is no
// actual conflict here.
if (Name->getBaseName() == "__uuidof") {
if (numLeft() < 2)
return nullptr;
if (*First == 't') {
++First;
Node *Ty = getDerived().parseType();
if (!Ty)
return nullptr;
return make<CallExpr>(Name, makeNodeArray(&Ty, &Ty + 1));
}
if (*First == 'z') {
++First;
Node *Ex = getDerived().parseExpr();
if (!Ex)
return nullptr;
return make<CallExpr>(Name, makeNodeArray(&Ex, &Ex + 1));
}
}
size_t ExprsBegin = Names.size();
while (!consumeIf('E')) {
Node *E = getDerived().parseTemplateArg();
if (E == nullptr)
return E;
Names.push_back(E);
}
return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));
}
case '1':
case '2':
case '3':
Expand All @@ -5024,21 +5045,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
case '9':
return getDerived().parseUnresolvedName();
}

if (consumeIf("u8__uuidoft")) {
Node *Ty = getDerived().parseType();
if (!Ty)
return nullptr;
return make<UUIDOfExpr>(Ty);
}

if (consumeIf("u8__uuidofz")) {
Node *Ex = getDerived().parseExpr();
if (!Ex)
return nullptr;
return make<UUIDOfExpr>(Ex);
}

return nullptr;
}

Expand Down