Author: Florian Hahn
Date: 2021-05-28T13:00:28+01:00
New Revision: 5bccdde070d29fb83aec69c498285b4c8914f8d1

URL: 
https://github.com/llvm/llvm-project/commit/5bccdde070d29fb83aec69c498285b4c8914f8d1
DIFF: 
https://github.com/llvm/llvm-project/commit/5bccdde070d29fb83aec69c498285b4c8914f8d1.diff

LOG: [Matrix] Move C++ matrix cast checks to TryStaticCast.

At the moment, the matrix support in CheckCXXCStyleCast (added in
D101696) breaks function-style constructor calls that take a
single matrix value, because it is treated as matrix cast.

Instead, unify the C++ matrix cast handling by moving the logic to
TryStaticCast and only handle the case where both types are matrix
types. Otherwise, fall back to the generic mis-match detection.

Suggested by @rjmccall

Reviewed By: SaurabhJha

Differential Revision: https://reviews.llvm.org/D103163

Added: 
    

Modified: 
    clang/lib/Sema/SemaCast.cpp
    clang/test/CodeGenCXX/matrix-casts.cpp
    clang/test/SemaCXX/matrix-casts.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 439b128e90ea4..943880c22376b 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1179,13 +1179,6 @@ void CastOperation::CheckStaticCast() {
       return;
   }
 
-  if (DestType->getAs<MatrixType>() ||
-      SrcExpr.get()->getType()->getAs<MatrixType>()) {
-    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".
@@ -1452,6 +1445,14 @@ static TryCastResult TryStaticCast(Sema &Self, 
ExprResult &SrcExpr,
           DestPointer->getPointeeType()->getAs<RecordType>())
        msg = diag::err_bad_cxx_cast_unrelated_class;
 
+  if (SrcType->isMatrixType() && DestType->isMatrixType()) {
+    if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind)) {
+      SrcExpr = ExprError();
+      return TC_Failed;
+    }
+    return TC_Success;
+  }
+
   // We tried everything. Everything! Nothing works! :-(
   return TC_NotApplicable;
 }
@@ -2665,13 +2666,6 @@ void CastOperation::CheckCXXCStyleCast(bool 
FunctionalStyle,
       return;
   }
 
-  if (DestType->getAs<MatrixType>() ||
-      SrcExpr.get()->getType()->getAs<MatrixType>()) {
-    if (Self.CheckMatrixCast(OpRange, DestType, SrcExpr.get()->getType(), 
Kind))
-      SrcExpr = ExprError();
-    return;
-  }
-
   // AltiVec vector initialization with a single literal.
   if (const VectorType *vecTy = DestType->getAs<VectorType>())
     if (vecTy->getVectorKind() == VectorType::AltiVecVector

diff  --git a/clang/test/CodeGenCXX/matrix-casts.cpp 
b/clang/test/CodeGenCXX/matrix-casts.cpp
index fea585bb0ba29..1bf751ee81b03 100644
--- a/clang/test/CodeGenCXX/matrix-casts.cpp
+++ b/clang/test/CodeGenCXX/matrix-casts.cpp
@@ -341,3 +341,33 @@ void CastIntToUnsignedLongIntStaticCast() {
   matrix_5_5<unsigned long int> u;
   u = static_cast<matrix_5_5<unsigned long int>>(i);
 }
+
+class Foo {
+  int x[10];
+
+public:
+  Foo(matrix_5_5<int> x);
+};
+
+Foo class_constructor_matrix_ty(matrix_5_5<int> 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<float> x);
+};
+
+Bar struct_constructor_matrix_ty(matrix_4_4<float> 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
index 33ba24913bac5..c0f3df1ae8106 100644
--- a/clang/test/SemaCXX/matrix-casts.cpp
+++ b/clang/test/SemaCXX/matrix-casts.cpp
@@ -26,23 +26,16 @@ void f1() {
   m2 = m1; // expected-error {{assigning to 'matrix_4_4<int>' from 
incompatible type 'matrix_4_4<char>'}}
   m3 = (matrix_4_4<short>)m2;
   (matrix_5_5<int>)m3; // expected-error {{conversion between matrix types 
'matrix_5_5<int>' (aka 'int __attribute__\
-((matrix_type(5, 5)))') and 'matrix_4_4<short>' (aka 'short 
__attribute__((matrix_type(4, 4)))') of 
diff erent size is not\
- allowed}}
-
-  (int)m3;            // expected-error {{conversion between matrix type 
'matrix_4_4<short>' (aka 'short __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}}
-  (matrix_4_4<int>)i; // expected-error {{conversion between matrix type 
'matrix_4_4<int>' (aka 'int __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}}
-
-  (vec) m2;            // expected-error {{conversion between matrix type 
'matrix_4_4<int>' (aka 'int __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) 
is not allowed}}
-  (matrix_4_4<char>)v; // expected-error {{conversion between matrix type 
'matrix_4_4<char>' (aka 'char __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) 
is not allowed}}
-
-  (test_struct *)m1;    // expected-error {{conversion between matrix type 
'matrix_4_4<char>' (aka 'char __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'test_struct *' is not allowed}}'
-  (matrix_5_5<float>)s; // expected-error {{conversion between matrix type 
'matrix_5_5<float>' (aka 'float __attribute__\
-((matrix_type(5, 5)))') and incompatible type 'test_struct *' is not allowed}}'
+((matrix_type(5, 5)))') and 'short __attribute__((matrix_type(4, 4)))' of 
diff erent size is not allowed}}
+
+  (int)m3;            // expected-error {{C-style cast from 
'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, 4)))') to 'int' 
is not allowed}}
+  (matrix_4_4<int>)i; // expected-error {{C-style cast from 'int' to 
'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') is not 
allowed}}
+
+  (vec) m2;            // expected-error {{C-style cast from 'matrix_4_4<int>' 
(aka 'int __attribute__((matrix_type(4, 4)))') to 'vec' (vector of 1 'int' 
value) is not allowed}}
+  (matrix_4_4<char>)v; // expected-error {{C-style cast from 'vec' (vector of 
1 'int' value) to 'matrix_4_4<char>' (aka 'char __attribute__((matrix_type(4, 
4)))') is not allowed}}
+
+  (test_struct *)m1;    // expected-error {{cannot cast from type 
'matrix_4_4<char>' (aka 'char __attribute__((matrix_type(4, 4)))') to pointer 
type 'test_struct *'}}
+  (matrix_5_5<float>)s; // expected-error {{C-style cast from 'test_struct *' 
to 'matrix_5_5<float>' (aka 'float __attribute__((matrix_type(5, 5)))') is not 
allowed}}
 }
 
 void f2() {
@@ -57,23 +50,16 @@ void f2() {
   m2 = static_cast<matrix_4_4<int>>(m1);
   m3 = static_cast<matrix_4_4<short>>(m2);
   static_cast<matrix_5_5<int>>(m3); // expected-error {{conversion between 
matrix types 'matrix_5_5<int>' (aka 'int __attribute__\
-((matrix_type(5, 5)))') and 'matrix_4_4<short>' (aka 'short 
__attribute__((matrix_type(4, 4)))') of 
diff erent size is not\
- allowed}}
-
-  static_cast<int>(m3);            // expected-error {{conversion between 
matrix type 'matrix_4_4<short>' (aka 'short __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}}
-  static_cast<matrix_4_4<int>>(i); // expected-error {{conversion between 
matrix type 'matrix_4_4<int>' (aka 'int __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'int' is not allowed}}
-
-  static_cast<vec>(m2);             // expected-error {{conversion between 
matrix type 'matrix_4_4<int>' (aka 'int __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) 
is not allowed}}
-  static_cast<matrix_4_4<char>>(v); // expected-error {{conversion between 
matrix type 'matrix_4_4<char>' (aka 'char __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'vec' (vector of 1 'int' value) 
is not allowed}}
-
-  static_cast<test_struct *>(m1);    // expected-error {{conversion between 
matrix type 'matrix_4_4<char>' (aka 'char __attribute__\
-((matrix_type(4, 4)))') and incompatible type 'test_struct *' is not allowed}}'
-  static_cast<matrix_5_5<float>>(s); // expected-error {{conversion between 
matrix type 'matrix_5_5<float>' (aka 'float __attribute__\
-((matrix_type(5, 5)))') and incompatible type 'test_struct *' is not allowed}}'
+((matrix_type(5, 5)))') and 'short __attribute__((matrix_type(4, 4)))' of 
diff erent size is not allowed}}
+
+  static_cast<int>(m3);            // expected-error {{static_cast from 
'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, 4)))') to 'int' 
is not allowed}}
+  static_cast<matrix_4_4<int>>(i); // expected-error {{static_cast from 'int' 
to 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') is not 
allowed}}
+
+  static_cast<vec>(m2);             // expected-error {{static_cast from 
'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') to 'vec' 
(vector of 1 'int' value) is not allowed}}
+  static_cast<matrix_4_4<char>>(v); // expected-error {{static_cast from 'vec' 
(vector of 1 'int' value) to 'matrix_4_4<char>' (aka 'char 
__attribute__((matrix_type(4, 4)))') is not allowed}}
+
+  static_cast<test_struct *>(m1);    // expected-error {{cannot cast from type 
'matrix_4_4<char>' (aka 'char __attribute__((matrix_type(4, 4)))') to pointer 
type 'test_struct *'}}
+  static_cast<matrix_5_5<float>>(s); // expected-error {{static_cast from 
'test_struct *' to 'matrix_5_5<float>' (aka 'float 
__attribute__((matrix_type(5, 5)))') is not allowed}}
 }
 
 void f3() {
@@ -87,7 +73,7 @@ void f3() {
 
   m2 = (matrix_4_4<double>)m1;
   (matrix_5_5<double>)m1; // expected-error {{conversion between matrix types 
'matrix_5_5<double>' (aka 'double __\
-attribute__((matrix_type(5, 5)))') and 'matrix_4_4<float>' (aka 'float 
__attribute__((matrix_type(4, 4)))') of 
diff erent\
+attribute__((matrix_type(5, 5)))') and 'float __attribute__((matrix_type(4, 
4)))' of 
diff erent\
  size is not allowed}}
   m4 = (matrix_5_5<signed int>)m3;
   m5 = (matrix_5_5<unsigned int>)m4; // expected-error {{assigning to 
'matrix_4_4<unsigned int>' (aka 'unsigned int \
@@ -108,8 +94,8 @@ void f4() {
 
   m2 = static_cast<matrix_4_4<double>>(m1);
   static_cast<matrix_5_5<double>>(m1); // expected-error {{conversion between 
matrix types 'matrix_5_5<double>' (aka 'double __\
-attribute__((matrix_type(5, 5)))') and 'matrix_4_4<float>' (aka 'float 
__attribute__((matrix_type(4, 4)))') of 
diff erent\
- size is not allowed}}
+attribute__((matrix_type(5, 5)))') and 'float __attribute__((matrix_type(4, 
4)))' of 
diff erent size is not allowed}}
+
   m4 = static_cast<matrix_5_5<signed int>>(m3);
   m5 = static_cast<matrix_5_5<unsigned int>>(m4); // expected-error 
{{assigning to 'matrix_4_4<unsigned int>' (aka 'unsigned int \
 __attribute__((matrix_type(4, 4)))') from incompatible type 
'matrix_5_5<unsigned int>' (aka 'unsigned int __attribute__\
@@ -117,3 +103,33 @@ __attribute__((matrix_type(4, 4)))') from incompatible 
type 'matrix_5_5<unsigned
   m6 = static_cast<matrix_5_5<unsigned int>>(m4);
   m4 = static_cast<matrix_5_5<signed int>>(m6);
 }
+
+class Foo {
+  // expected-note@-1 {{candidate constructor (the implicit copy constructor) 
not viable: no known conversion from 'matrix_4_4<float>' (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<float>' (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<int> x);
+  // expected-note@-1 {{candidate constructor not viable: no known conversion 
from 'matrix_4_4<float>' (aka 'float __attribute__((matrix_type(4, 4)))') to 
'matrix_5_5<int>' (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<unsigned int>' (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<unsigned int>' (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<float> m1;
+  matrix_4_4<unsigned int> m5;
+
+  Foo F = Foo(m1);
+  // expected-error@-1 {{no matching conversion for functional-style cast from 
'matrix_4_4<float>' (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<unsigned int>' (aka 'unsigned int __attribute__((matrix_type(4, 
4)))') to 'Bar'}}
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to