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 @@ -2665,8 +2665,13 @@ return; } - if (DestType->getAs() || - SrcExpr.get()->getType()->getAs()) { + // If the destination types is not a class or struct type and either the + // destination or source type is a matrix type, perform & check a matrix cast. + // If the destination type is a class or struct, check against their + // constructors later. + if (!DestType->isStructureOrClassType() && + (DestType->getAs() || + SrcExpr.get()->getType()->getAs())) { if (Self.CheckMatrixCast(OpRange, DestType, SrcExpr.get()->getType(), Kind)) SrcExpr = ExprError(); return; 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 @@ -341,3 +341,33 @@ matrix_5_5 u; u = static_cast>(i); } + +class Foo { + int x[10]; + +public: + Foo(matrix_5_5 x); +}; + +Foo class_constructor_matrix_ty(matrix_5_5 m) { + // CHECK-LABEL: define void @_Z27class_constructor_matrix_tyu11matrix_typeILm5ELm5EiE(%class.Foo* noalias sret(%class.Foo) align 4 %agg.result, <25 x i32> %m) + // CHECK: [[M:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: call void @_ZN3FooC1Eu11matrix_typeILm5ELm5EiE(%class.Foo* nonnull align 4 dereferenceable(40) %agg.result, <25 x i32> [[M]]) + // CHECK-NEXT: ret void + + return Foo(m); +} + +struct Bar { + float x[10]; + Bar(matrix_4_4 x); +}; + +Bar struct_constructor_matrix_ty(matrix_4_4 m) { + // CHECK-LABEL: define void @_Z28struct_constructor_matrix_tyu11matrix_typeILm4ELm4EfE(%struct.Bar* noalias sret(%struct.Bar) align 4 %agg.result, <16 x float> %m) + // CHECK: [[M:%.*]] = load <16 x float>, <16 x float>* {{.*}}, align 4 + // CHECK-NEXT: call void @_ZN3BarC1Eu11matrix_typeILm4ELm4EfE(%struct.Bar* nonnull align 4 dereferenceable(40) %agg.result, <16 x float> [[M]]) + // CHECK-NEXT: ret void + + return Bar(m); +} 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 @@ -117,3 +117,33 @@ m6 = static_cast>(m4); m4 = static_cast>(m6); } + +class Foo { + // expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'matrix_4_4' (aka 'float __attribute__((matrix_type(4, 4)))') to 'const Foo' for 1st argument}} + // expected-note@-2 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'matrix_4_4' (aka 'float __attribute__((matrix_type(4, 4)))') to 'Foo' for 1st argument}} + + int x; + +public: + Foo(); + // expected-note@-1 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}} + Foo(matrix_5_5 x); + // expected-note@-1 {{candidate constructor not viable: no known conversion from 'matrix_4_4' (aka 'float __attribute__((matrix_type(4, 4)))') to 'matrix_5_5' (aka 'int __attribute__((matrix_type(5, 5)))') for 1st argument}} +}; + +struct Bar { + // expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'matrix_4_4' (aka 'unsigned int __attribute__((matrix_type(4, 4)))') to 'const Bar' for 1st argument}} + // expected-note@-2 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'matrix_4_4' (aka 'unsigned int __attribute__((matrix_type(4, 4)))') to 'Bar' for 1st argument}} + // expected-note@-3 {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + float x; +}; + +void f5_constructors() { + matrix_4_4 m1; + matrix_4_4 m5; + + Foo F = Foo(m1); + // expected-error@-1 {{no matching conversion for functional-style cast from 'matrix_4_4' (aka 'float __attribute__((matrix_type(4, 4)))') to 'Foo'}} + Bar B = Bar(m5); + // expected-error@-1 {{no matching conversion for functional-style cast from 'matrix_4_4' (aka 'unsigned int __attribute__((matrix_type(4, 4)))') to 'Bar'}} +}