diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1179,6 +1179,13 @@ return; } + if (DestType->getAs() || + SrcExpr.get()->getType()->getAs()) { + if (Self.CheckMatrixCast(OpRange, DestType, SrcExpr.get()->getType(), Kind)) + SrcExpr = ExprError(); + return; + } + // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". diff --git a/clang/test/CodeGenCXX/matrix-casts.cpp b/clang/test/CodeGenCXX/matrix-casts.cpp --- a/clang/test/CodeGenCXX/matrix-casts.cpp +++ b/clang/test/CodeGenCXX/matrix-casts.cpp @@ -6,8 +6,8 @@ template using matrix_5_5 = Y __attribute__((matrix_type(5, 5))); -// CHECK-LABEL: define{{.*}} void @_Z19CastCharMatrixToIntv -void CastCharMatrixToInt() { +// CHECK-LABEL: define{{.*}} void @_Z25CastCharMatrixToIntCStylev() +void CastCharMatrixToIntCStyle() { // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* @@ -18,8 +18,20 @@ i = (matrix_5_5)c; } -// CHECK-LABEL: define{{.*}} void @_Z27CastCharMatrixToUnsignedIntv -void CastCharMatrixToUnsignedInt() { +// CHECK-LABEL: define{{.*}} void @_Z29CastCharMatrixToIntStaticCastv() +void CastCharMatrixToIntStaticCast() { + // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 + // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* [[CONV1]], align 4 + + matrix_5_5 c; + matrix_5_5 i; + i = static_cast>(c); +} + +// CHECK-LABEL: define{{.*}} void @_Z33CastCharMatrixToUnsignedIntCStylev +void CastCharMatrixToUnsignedIntCStyle() { // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* @@ -31,8 +43,21 @@ u = (matrix_5_5)c; } -// CHECK-LABEL: define{{.*}} void @_Z32CastUnsignedLongIntMatrixToShortv -void CastUnsignedLongIntMatrixToShort() { +// CHECK-LABEL: define{{.*}} void @_Z37CastCharMatrixToUnsignedIntStaticCastv +void CastCharMatrixToUnsignedIntStaticCast() { + // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 + // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 c; + matrix_5_5 u; + u = static_cast>(c); +} + +// CHECK-LABEL: define{{.*}} void @_Z38CastUnsignedLongIntMatrixToShortCStylev +void CastUnsignedLongIntMatrixToShortCStyle() { // CHECK: [[U:%.*]] = load <25 x i64>, <25 x i64>* {{.*}}, align 8 // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> {{.*}} to <25 x i16> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* @@ -44,8 +69,21 @@ s = (matrix_5_5)u; } -// CHECK-LABEL: define{{.*}} void @_Z20CastIntMatrixToShortv() -void CastIntMatrixToShort() { +// CHECK-LABEL: define{{.*}} void @_Z42CastUnsignedLongIntMatrixToShortStaticCastv +void CastUnsignedLongIntMatrixToShortStaticCast() { + // CHECK: [[U:%.*]] = load <25 x i64>, <25 x i64>* {{.*}}, align 8 + // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> {{.*}} to <25 x i16> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 u; + matrix_5_5 s; + s = static_cast>(u); +} + +// CHECK-LABEL: define{{.*}} void @_Z26CastIntMatrixToShortCStylev() +void CastIntMatrixToShortCStyle() { // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i32> [[I]] to <25 x i16> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* @@ -57,8 +95,21 @@ s = (matrix_5_5)i; } -// CHECK-LABEL: define{{.*}} void @_Z20CastIntMatrixToFloatv() -void CastIntMatrixToFloat() { +// CHECK-LABEL: define{{.*}} void @_Z30CastIntMatrixToShortStaticCastv() +void CastIntMatrixToShortStaticCast() { + // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i32> [[I]] to <25 x i16> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 i; + matrix_5_5 s; + s = static_cast>(i); +} + +// CHECK-LABEL: define{{.*}} void @_Z26CastIntMatrixToFloatCStylev() +void CastIntMatrixToFloatCStyle() { // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 // CHECK-NEXT: [[CONV]] = sitofp <25 x i32> {{.*}} to <25 x float> // CHECK-NEXT: [[CONV1]] = bitcast [25 x float]* {{.*}} to <25 x float>* @@ -70,8 +121,21 @@ f = (matrix_5_5)i; } -// CHECK-LABEL: define{{.*}} void @_Z28CastUnsignedIntMatrixToFloatv() -void CastUnsignedIntMatrixToFloat() { +// CHECK-LABEL: define{{.*}} void @_Z30CastIntMatrixToFloatStaticCastv() +void CastIntMatrixToFloatStaticCast() { + // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV]] = sitofp <25 x i32> {{.*}} to <25 x float> + // CHECK-NEXT: [[CONV1]] = bitcast [25 x float]* {{.*}} to <25 x float>* + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 i; + matrix_5_5 f; + f = static_cast>(i); +} + +// CHECK-LABEL: define{{.*}} void @_Z34CastUnsignedIntMatrixToFloatCStylev() +void CastUnsignedIntMatrixToFloatCStyle() { // CHECK: [[U:%.*]] = load <25 x i16>, <25 x i16>* {{.*}}, align 2 // CHECK-NEXT: [[CONV:%.*]] = uitofp <25 x i16> [[U]] to <25 x float> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x float]* {{.*}} to <25 x float>* @@ -83,8 +147,21 @@ f = (matrix_5_5)u; } -// CHECK-LABEL: define{{.*}} void @_Z21CastDoubleMatrixToIntv() -void CastDoubleMatrixToInt() { +// CHECK-LABEL: define{{.*}} void @_Z38CastUnsignedIntMatrixToFloatStaticCastv() +void CastUnsignedIntMatrixToFloatStaticCast() { + // CHECK: [[U:%.*]] = load <25 x i16>, <25 x i16>* {{.*}}, align 2 + // CHECK-NEXT: [[CONV:%.*]] = uitofp <25 x i16> [[U]] to <25 x float> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x float]* {{.*}} to <25 x float>* + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + matrix_5_5 u; + matrix_5_5 f; + f = static_cast>(u); +} + +// CHECK-LABEL: define{{.*}} void @_Z27CastDoubleMatrixToIntCStylev() +void CastDoubleMatrixToIntCStyle() { // CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 // CHECK-NEXT: [[CONV:%.*]] = fptosi <25 x double> [[D]] to <25 x i32> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* %i to <25 x i32>* @@ -96,8 +173,21 @@ i = (matrix_5_5)d; } -// CHECK-LABEL: define{{.*}} void @_Z33CastFloatMatrixToUnsignedShortIntv() -void CastFloatMatrixToUnsignedShortInt() { +// CHECK-LABEL: define{{.*}} void @_Z31CastDoubleMatrixToIntStaticCastv() +void CastDoubleMatrixToIntStaticCast() { + // CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK-NEXT: [[CONV:%.*]] = fptosi <25 x double> [[D]] to <25 x i32> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* %i to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + matrix_5_5 d; + matrix_5_5 i; + i = static_cast>(d); +} + +// CHECK-LABEL: define{{.*}} void @_Z39CastFloatMatrixToUnsignedShortIntCStylev() +void CastFloatMatrixToUnsignedShortIntCStyle() { // CHECK: [[F:%.*]] = load <25 x float>, <25 x float>* {{.*}}, align 4 // CHECK-NEXT: [[CONV:%.*]] = fptoui <25 x float> [[F]] to <25 x i16> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* @@ -109,8 +199,21 @@ i = (matrix_5_5)f; } -// CHECK-LABEL: define{{.*}} void @_Z23CastDoubleMatrixToFloatv() -void CastDoubleMatrixToFloat() { +// CHECK-LABEL: define{{.*}} void @_Z43CastFloatMatrixToUnsignedShortIntStaticCastv() +void CastFloatMatrixToUnsignedShortIntStaticCast() { + // CHECK: [[F:%.*]] = load <25 x float>, <25 x float>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV:%.*]] = fptoui <25 x float> [[F]] to <25 x i16> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 f; + matrix_5_5 i; + i = static_cast>(f); +} + +// CHECK-LABEL: define{{.*}} void @_Z29CastDoubleMatrixToFloatCStylev() +void CastDoubleMatrixToFloatCStyle() { // CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 // CHECK-NEXT: [[CONV:%.*]] = fptrunc <25 x double> [[D]] to <25 x float> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x float]* {{.*}} to <25 x float>* @@ -122,8 +225,21 @@ f = (matrix_5_5)d; } -// CHECK-LABEL: define{{.*}} void @_Z33CastUnsignedShortIntToUnsignedIntv() -void CastUnsignedShortIntToUnsignedInt() { +// CHECK-LABEL: define{{.*}} void @_Z33CastDoubleMatrixToFloatStaticCastv() +void CastDoubleMatrixToFloatStaticCast() { + // CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK-NEXT: [[CONV:%.*]] = fptrunc <25 x double> [[D]] to <25 x float> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x float]* {{.*}} to <25 x float>* + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 d; + matrix_5_5 f; + f = static_cast>(d); +} + +// CHECK-LABEL: define{{.*}} void @_Z39CastUnsignedShortIntToUnsignedIntCStylev() +void CastUnsignedShortIntToUnsignedIntCStyle() { // CHECK: [[S:%.*]] = load <25 x i16>, <25 x i16>* {{.*}}, align 2 // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i16> [[S]] to <25 x i32> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* @@ -135,8 +251,21 @@ i = (matrix_5_5)s; } -// CHECK-LABEL: define{{.*}} void @_Z37CastUnsignedLongIntToUnsignedShortIntv() -void CastUnsignedLongIntToUnsignedShortInt() { +// CHECK-LABEL: define{{.*}} void @_Z43CastUnsignedShortIntToUnsignedIntStaticCastv() +void CastUnsignedShortIntToUnsignedIntStaticCast() { + // CHECK: [[S:%.*]] = load <25 x i16>, <25 x i16>* {{.*}}, align 2 + // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i16> [[S]] to <25 x i32> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* [[CONV1]], align 4 + // CHECK-NEXT: ret void + + matrix_5_5 s; + matrix_5_5 i; + i = static_cast>(s); +} + +// CHECK-LABEL: define{{.*}} void @_Z43CastUnsignedLongIntToUnsignedShortIntCStylev() +void CastUnsignedLongIntToUnsignedShortIntCStyle() { // CHECK: [[L:%.*]] = load <25 x i64>, <25 x i64>* %0, align 8 // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> [[L]] to <25 x i16> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* @@ -148,8 +277,21 @@ s = (matrix_5_5)l; } -// CHECK-LABEL: define{{.*}} void @_Z25CastUnsignedShortIntToIntv() -void CastUnsignedShortIntToInt() { +// CHECK-LABEL: define{{.*}} void @_Z47CastUnsignedLongIntToUnsignedShortIntStaticCastv() +void CastUnsignedLongIntToUnsignedShortIntStaticCast() { + // CHECK: [[L:%.*]] = load <25 x i64>, <25 x i64>* %0, align 8 + // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> [[L]] to <25 x i16> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i16]* {{.*}} to <25 x i16>* + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* [[CONV1]], align 2 + // CHECK-NEXT: ret void + + matrix_5_5 l; + matrix_5_5 s; + s = static_cast>(l); +} + +// CHECK-LABEL: define{{.*}} void @_Z31CastUnsignedShortIntToIntCStylev() +void CastUnsignedShortIntToIntCStyle() { // CHECK: [[U:%.*]] = load <25 x i16>, <25 x i16>* %0, align 2 // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i16> [[U]] to <25 x i32> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* @@ -161,8 +303,21 @@ i = (matrix_5_5)u; } -// CHECK-LABEL: define{{.*}} void @_Z24CastIntToUnsignedLongIntv() -void CastIntToUnsignedLongInt() { +// CHECK-LABEL: define{{.*}} void @_Z35CastUnsignedShortIntToIntStaticCastv() +void CastUnsignedShortIntToIntStaticCast() { + // CHECK: [[U:%.*]] = load <25 x i16>, <25 x i16>* %0, align 2 + // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i16> [[U]] to <25 x i32> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i32]* {{.*}} to <25 x i32>* + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + matrix_5_5 u; + matrix_5_5 i; + i = static_cast>(u); +} + +// CHECK-LABEL: define{{.*}} void @_Z30CastIntToUnsignedLongIntCStylev() +void CastIntToUnsignedLongIntCStyle() { // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* %0, align 4 // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i32> [[I]] to <25 x i64> // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i64]* {{.*}} to <25 x i64>* @@ -173,3 +328,16 @@ matrix_5_5 u; u = (matrix_5_5)i; } + +// CHECK-LABEL: define{{.*}} void @_Z34CastIntToUnsignedLongIntStaticCastv() +void CastIntToUnsignedLongIntStaticCast() { + // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* %0, align 4 + // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i32> [[I]] to <25 x i64> + // CHECK-NEXT: [[CONV1:%.*]] = bitcast [25 x i64]* {{.*}} to <25 x i64>* + // CHECK-NEXT: store <25 x i64> [[CONV]], <25 x i64>* {{.*}}, align 8 + // CHECK-NEXT: ret void + + matrix_5_5 i; + matrix_5_5 u; + u = static_cast>(i); +} diff --git a/clang/test/SemaCXX/matrix-casts.cpp b/clang/test/SemaCXX/matrix-casts.cpp --- a/clang/test/SemaCXX/matrix-casts.cpp +++ b/clang/test/SemaCXX/matrix-casts.cpp @@ -46,6 +46,37 @@ } void f2() { + matrix_4_4 m1; + matrix_4_4 m2; + matrix_4_4 m3; + matrix_5_5 m4; + int i; + vec v; + test_struct *s; + + m2 = static_cast>(m1); + m3 = static_cast>(m2); + static_cast>(m3); // expected-error {{conversion between matrix types 'matrix_5_5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and 'matrix_4_4' (aka 'short __attribute__((matrix_type(4, 4)))') of different size is not\ + allowed}} + + static_cast(m3); // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'short __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}} + static_cast>(i); // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'int __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}} + + static_cast(m2); // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'int __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) is not allowed}} + static_cast>(v); // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'char __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) is not allowed}} + + static_cast(m1); // expected-error {{conversion between matrix type 'matrix_4_4' (aka 'char __attribute__\ +((matrix_type(4, 4)))') and incompatible type 'test_struct *' is not allowed}}' + static_cast>(s); // expected-error {{conversion between matrix type 'matrix_5_5' (aka 'float __attribute__\ +((matrix_type(5, 5)))') and incompatible type 'test_struct *' is not allowed}}' +} + +void f3() { matrix_4_4 m1; matrix_4_4 m2; matrix_5_5 m3; @@ -65,3 +96,24 @@ m6 = (matrix_5_5)m4; m4 = (matrix_5_5)m6; } + +void f4() { + matrix_4_4 m1; + matrix_4_4 m2; + matrix_5_5 m3; + matrix_5_5 m4; + matrix_4_4 m5; + matrix_5_5 m6; + float f; + + m2 = static_cast>(m1); + static_cast>(m1); // expected-error {{conversion between matrix types 'matrix_5_5' (aka 'double __\ +attribute__((matrix_type(5, 5)))') and 'matrix_4_4' (aka 'float __attribute__((matrix_type(4, 4)))') of different\ + size is not allowed}} + m4 = static_cast>(m3); + m5 = static_cast>(m4); // expected-error {{assigning to 'matrix_4_4' (aka 'unsigned int \ +__attribute__((matrix_type(4, 4)))') from incompatible type 'matrix_5_5' (aka 'unsigned int __attribute__\ +((matrix_type(5, 5)))')}} + m6 = static_cast>(m4); + m4 = static_cast>(m6); +}