[clang] f976ba6 - [PowerPC] Add Sema checks for MMA types

Baptiste Saleil via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 4 15:02:06 PST 2020


Author: Baptiste Saleil
Date: 2020-11-04T17:01:47-06:00
New Revision: f976ba61395811732b4605b6fb9b6ba5cd489372

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

LOG: [PowerPC] Add Sema checks for MMA types

The use of the new types introduced for PowerPC MMA instructions needs to be restricted.
We add a PowerPC function checking that the given type is valid in a context in which we don't allow MMA types.
This function is called from various places in Sema where we want to prevent the use of these types.

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

Added: 
    clang/test/Sema/ppc-mma-types.c
    clang/test/SemaCXX/ppc-mma-types.cpp

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaChecking.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExprCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 83d968d3ae95..b9b76e8a9fb3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9503,6 +9503,8 @@ def err_mips_builtin_requires_msa : Error<
   "this builtin requires 'msa' ASE, please use -mmsa">;
 def err_ppc_builtin_only_on_pwr7 : Error<
   "this builtin is only valid on POWER7 or later CPUs">;
+def err_ppc_invalid_use_mma_type : Error<
+  "invalid use of PPC MMA type">;
 def err_x86_builtin_invalid_rounding : Error<
   "invalid rounding argument">;
 def err_x86_builtin_invalid_scale : Error<

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c42bc740ffa9..83d2a3122110 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12350,6 +12350,8 @@ class Sema final {
   bool SemaBuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
   bool SemaBuiltinPPCMMACall(CallExpr *TheCall, const char *TypeDesc);
 
+  bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
+
   // Matrix builtin handling.
   ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
                                         ExprResult CallResult);

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 004028810d6e..eacf00c93015 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3307,6 +3307,23 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
   return SemaBuiltinConstantArgRange(TheCall, i, l, u);
 }
 
+// Check if the given type is a non-pointer PPC MMA type. This function is used
+// in Sema to prevent invalid uses of restricted PPC MMA types.
+bool Sema::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
+  if (Type->isPointerType() || Type->isArrayType())
+    return false;
+
+  QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
+#define PPC_MMA_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
+  if (false
+#include "clang/Basic/PPCTypes.def"
+     ) {
+    Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);
+    return true;
+  }
+  return false;
+}
+
 bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
                                           CallExpr *TheCall) {
   // position of memory order and scope arguments in the builtin
@@ -10315,6 +10332,11 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
           << FD << getLangOpts().CPlusPlus11;
     }
   }
+
+  // PPC MMA non-pointer types are not allowed as return type. Checking the type
+  // here prevent the user from using a PPC MMA type as trailing return type.
+  if (Context.getTargetInfo().getTriple().isPPC64())
+    CheckPPCMMAType(RetValExp->getType(), ReturnLoc);
 }
 
 //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6af2c188ba50..1afb4dcc7ff7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8037,6 +8037,14 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
     NewVD->setInvalidDecl();
     return;
   }
+
+  // PPC MMA non-pointer types are not allowed as non-local variable types.
+  if (Context.getTargetInfo().getTriple().isPPC64() &&
+      !NewVD->isLocalVarDecl() &&
+      CheckPPCMMAType(T, NewVD->getLocation())) {
+    NewVD->setInvalidDecl();
+    return;
+  }
 }
 
 /// Perform semantic checking on a newly-created variable
@@ -10681,6 +10689,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
                                 MergeTypeWithPrevious, Previous))
     return Redeclaration;
 
+  // PPC MMA non-pointer types are not allowed as function return types.
+  if (Context.getTargetInfo().getTriple().isPPC64() &&
+      CheckPPCMMAType(NewFD->getReturnType(), NewFD->getLocation())) {
+    NewFD->setInvalidDecl();
+  }
+
   // C++11 [dcl.constexpr]p8:
   //   A constexpr specifier for a non-static member function that is not
   //   a constructor declares that member function to be const.
@@ -13707,6 +13721,12 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
     New->setInvalidDecl();
   }
 
+  // PPC MMA non-pointer types are not allowed as function argument types.
+  if (Context.getTargetInfo().getTriple().isPPC64() &&
+      CheckPPCMMAType(New->getOriginalType(), New->getLocation())) {
+    New->setInvalidDecl();
+  }
+
   return New;
 }
 
@@ -16756,6 +16776,11 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
   if (T.isObjCGCWeak())
     Diag(Loc, diag::warn_attribute_weak_on_field);
 
+  // PPC MMA non-pointer types are not allowed as field types.
+  if (Context.getTargetInfo().getTriple().isPPC64() &&
+      CheckPPCMMAType(T, NewFD->getLocation()))
+    NewFD->setInvalidDecl();
+
   NewFD->setAccess(AS);
   return NewFD;
 }

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 80b1e90faa0e..e36d9adfbaba 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -884,6 +884,10 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
     Ex = Res.get();
   }
 
+  // PPC MMA non-pointer types are not allowed as throw expr types.
+  if (Ex && Context.getTargetInfo().getTriple().isPPC64())
+    CheckPPCMMAType(Ex->getType(), Ex->getBeginLoc());
+
   return new (Context)
       CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope);
 }

diff  --git a/clang/test/Sema/ppc-mma-types.c b/clang/test/Sema/ppc-mma-types.c
new file mode 100644
index 000000000000..96644a4d9bbd
--- /dev/null
+++ b/clang/test/Sema/ppc-mma-types.c
@@ -0,0 +1,321 @@
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -fsyntax-only \
+// RUN:   -target-cpu future %s -verify
+
+// The use of PPC MMA types is strongly restricted. Non-pointer MMA variables
+// can only be declared in functions and a limited number of operations are
+// supported on these types. This test case checks that invalid uses of MMA
+// types are correctly prevented.
+
+// vector quad
+
+// typedef
+typedef __vector_quad vq_t;
+void testVQTypedef(int *inp, int *outp) {
+  vq_t *vqin = (vq_t *)inp;
+  vq_t *vqout = (vq_t *)outp;
+  *vqout = *vqin;
+}
+
+// function argument
+void testVQArg1(__vector_quad vq, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = vq;
+}
+
+void testVQArg2(const __vector_quad vq, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = vq;
+}
+
+void testVQArg3(__vector_quad *vq, int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = *vq;
+}
+
+void testVQArg4(const __vector_quad *const vq, int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = *vq;
+}
+
+void testVQArg5(__vector_quad vqa[], int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = vqa[0];
+}
+
+void testVQArg6(const vq_t vq, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = vq;
+}
+
+void testVQArg7(const vq_t *vq, int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  *vqp = *vq;
+}
+
+// function return
+__vector_quad testVQRet1(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  return *vqp; // expected-error {{invalid use of PPC MMA type}}
+}
+
+__vector_quad *testVQRet2(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  return vqp + 2;
+}
+
+const __vector_quad *testVQRet3(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  return vqp + 2;
+}
+
+const vq_t testVQRet4(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  return *vqp; // expected-error {{invalid use of PPC MMA type}}
+}
+
+const vq_t *testVQRet5(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  return vqp + 2;
+}
+
+// global
+__vector_quad globalvq;        // expected-error {{invalid use of PPC MMA type}}
+const __vector_quad globalvq2; // expected-error {{invalid use of PPC MMA type}}
+__vector_quad *globalvqp;
+const __vector_quad *const globalvqp2;
+vq_t globalvq_t; // expected-error {{invalid use of PPC MMA type}}
+
+// local
+void testVQLocal(int *ptr, vector unsigned char vc) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  __vector_quad vq1 = *vqp;
+  __vector_quad vq2;
+  __builtin_mma_xxsetaccz(&vq2);
+  __vector_quad vq3;
+  __builtin_mma_xvi4ger8(&vq3, vc, vc);
+  *vqp = vq3;
+}
+
+// struct field
+struct TestVQStruct {
+  int a;
+  float b;
+  __vector_quad c; // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vq;
+};
+
+// sizeof / alignof
+int testVQSizeofAlignof(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  __vector_quad vq = *vqp;
+  unsigned sizet = sizeof(__vector_quad);
+  unsigned alignt = __alignof__(__vector_quad);
+  unsigned sizev = sizeof(vq);
+  unsigned alignv = __alignof__(vq);
+  return sizet + alignt + sizev + alignv;
+}
+
+// operators
+int testVQOperators1(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  __vector_quad vq1 = *(vqp + 0);
+  __vector_quad vq2 = *(vqp + 1);
+  __vector_quad vq3 = *(vqp + 2);
+  if (vq1) // expected-error {{statement requires expression of scalar type ('__vector_quad' invalid)}}
+    *(vqp + 10) = vq1;
+  if (!vq2) // expected-error {{invalid argument type '__vector_quad' to unary expression}}
+    *(vqp + 11) = vq3;
+  int c1 = vq1 && vq2; // expected-error {{invalid operands to binary expression ('__vector_quad' and '__vector_quad')}}
+  int c2 = vq2 == vq3; // expected-error {{invalid operands to binary expression ('__vector_quad' and '__vector_quad')}}
+  int c3 = vq2 < vq1;  // expected-error {{invalid operands to binary expression ('__vector_quad' and '__vector_quad')}}
+  return c1 || c2 || c3;
+}
+
+void testVQOperators2(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  __vector_quad vq1 = *(vqp + 0);
+  __vector_quad vq2 = *(vqp + 1);
+  __vector_quad vq3 = *(vqp + 2);
+  vq1 = -vq1;      // expected-error {{invalid argument type '__vector_quad' to unary expression}}
+  vq2 = vq1 + vq3; // expected-error {{invalid operands to binary expression ('__vector_quad' and '__vector_quad')}}
+  vq2 = vq2 * vq3; // expected-error {{invalid operands to binary expression ('__vector_quad' and '__vector_quad')}}
+  vq3 = vq3 | vq3; // expected-error {{invalid operands to binary expression ('__vector_quad' and '__vector_quad')}}
+  vq3 = vq3 << 2;  // expected-error {{invalid operands to binary expression ('__vector_quad' and 'int')}}
+  *(vqp + 10) = vq1;
+  *(vqp + 11) = vq2;
+  *(vqp + 12) = vq3;
+}
+
+vector unsigned char testVQOperators3(int *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  __vector_quad vq1 = *(vqp + 0);
+  __vector_quad vq2 = *(vqp + 1);
+  __vector_quad vq3 = *(vqp + 2);
+  vq1 ? *(vqp + 10) = vq2 : *(vqp + 11) = vq3; // expected-error {{used type '__vector_quad' where arithmetic or pointer type is required}}
+  vq2 = vq3;
+  return vq2[1]; // expected-error {{subscripted value is not an array, pointer, or vector}}
+}
+
+void testVQOperators4(int v, void *ptr) {
+  __vector_quad *vqp = (__vector_quad *)ptr;
+  __vector_quad vq1 = (__vector_quad)v;   // expected-error {{used type '__vector_quad' where arithmetic or pointer type is required}}
+  __vector_quad vq2 = (__vector_quad)vqp; // expected-error {{used type '__vector_quad' where arithmetic or pointer type is required}}
+}
+
+// vector pair
+
+// typedef
+typedef __vector_pair vp_t;
+void testVPTypedef(int *inp, int *outp) {
+  vp_t *vpin = (vp_t *)inp;
+  vp_t *vpout = (vp_t *)outp;
+  *vpout = *vpin;
+}
+
+// function argument
+void testVPArg1(__vector_pair vp, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = vp;
+}
+
+void testVPArg2(const __vector_pair vp, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = vp;
+}
+
+void testVPArg3(__vector_pair *vp, int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = *vp;
+}
+
+void testVPArg4(const __vector_pair *const vp, int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = *vp;
+}
+
+void testVPArg5(__vector_pair vpa[], int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = vpa[0];
+}
+
+void testVPArg6(const vp_t vp, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = vp;
+}
+
+void testVPArg7(const vp_t *vp, int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  *vpp = *vp;
+}
+
+// function return
+__vector_pair testVPRet1(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  return *vpp; // expected-error {{invalid use of PPC MMA type}}
+}
+
+__vector_pair *testVPRet2(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  return vpp + 2;
+}
+
+const __vector_pair *testVPRet3(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  return vpp + 2;
+}
+
+const vp_t testVPRet4(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  return *vpp; // expected-error {{invalid use of PPC MMA type}}
+}
+
+const vp_t *testVPRet5(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  return vpp + 2;
+}
+
+// global
+__vector_pair globalvp;        // expected-error {{invalid use of PPC MMA type}}
+const __vector_pair globalvp2; // expected-error {{invalid use of PPC MMA type}}
+__vector_pair *globalvpp;
+const __vector_pair *const globalvpp2;
+vp_t globalvp_t; // expected-error {{invalid use of PPC MMA type}}
+
+// local
+void testVPLocal(int *ptr, vector unsigned char vc) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  __vector_pair vp1 = *vpp;
+  __vector_pair vp2;
+  __builtin_mma_assemble_pair(&vp2, vc, vc);
+  __vector_pair vp3;
+  __vector_quad vq;
+  __builtin_mma_xvf64ger(&vq, vp3, vc);
+  *vpp = vp3;
+}
+
+// struct field
+struct TestVPStruct {
+  int a;
+  float b;
+  __vector_pair c; // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vp;
+};
+
+// sizeof / alignof
+int testVPSizeofAlignof(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  __vector_pair vp = *vpp;
+  unsigned sizet = sizeof(__vector_pair);
+  unsigned alignt = __alignof__(__vector_pair);
+  unsigned sizev = sizeof(vp);
+  unsigned alignv = __alignof__(vp);
+  return sizet + alignt + sizev + alignv;
+}
+
+// operators
+int testVPOperators1(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  __vector_pair vp1 = *(vpp + 0);
+  __vector_pair vp2 = *(vpp + 1);
+  __vector_pair vp3 = *(vpp + 2);
+  if (vp1) // expected-error {{statement requires expression of scalar type ('__vector_pair' invalid)}}
+    *(vpp + 10) = vp1;
+  if (!vp2) // expected-error {{invalid argument type '__vector_pair' to unary expression}}
+    *(vpp + 11) = vp3;
+  int c1 = vp1 && vp2; // expected-error {{invalid operands to binary expression ('__vector_pair' and '__vector_pair')}}
+  int c2 = vp2 == vp3; // expected-error {{invalid operands to binary expression ('__vector_pair' and '__vector_pair')}}
+  int c3 = vp2 < vp1;  // expected-error {{invalid operands to binary expression ('__vector_pair' and '__vector_pair')}}
+  return c1 || c2 || c3;
+}
+
+void testVPOperators2(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  __vector_pair vp1 = *(vpp + 0);
+  __vector_pair vp2 = *(vpp + 1);
+  __vector_pair vp3 = *(vpp + 2);
+  vp1 = -vp1;      // expected-error {{invalid argument type '__vector_pair' to unary expression}}
+  vp2 = vp1 + vp3; // expected-error {{invalid operands to binary expression ('__vector_pair' and '__vector_pair')}}
+  vp2 = vp2 * vp3; // expected-error {{invalid operands to binary expression ('__vector_pair' and '__vector_pair')}}
+  vp3 = vp3 | vp3; // expected-error {{invalid operands to binary expression ('__vector_pair' and '__vector_pair')}}
+  vp3 = vp3 << 2;  // expected-error {{invalid operands to binary expression ('__vector_pair' and 'int')}}
+  *(vpp + 10) = vp1;
+  *(vpp + 11) = vp2;
+  *(vpp + 12) = vp3;
+}
+
+vector unsigned char testVPOperators3(int *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  __vector_pair vp1 = *(vpp + 0);
+  __vector_pair vp2 = *(vpp + 1);
+  __vector_pair vp3 = *(vpp + 2);
+  vp1 ? *(vpp + 10) = vp2 : *(vpp + 11) = vp3; // expected-error {{used type '__vector_pair' where arithmetic or pointer type is required}}
+  vp2 = vp3;
+  return vp2[1]; // expected-error {{subscripted value is not an array, pointer, or vector}}
+}
+
+void testVPOperators4(int v, void *ptr) {
+  __vector_pair *vpp = (__vector_pair *)ptr;
+  __vector_pair vp1 = (__vector_pair)v;   // expected-error {{used type '__vector_pair' where arithmetic or pointer type is required}}
+  __vector_pair vp2 = (__vector_pair)vpp; // expected-error {{used type '__vector_pair' where arithmetic or pointer type is required}}
+}
+

diff  --git a/clang/test/SemaCXX/ppc-mma-types.cpp b/clang/test/SemaCXX/ppc-mma-types.cpp
new file mode 100644
index 000000000000..86487586e9b2
--- /dev/null
+++ b/clang/test/SemaCXX/ppc-mma-types.cpp
@@ -0,0 +1,384 @@
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -fsyntax-only \
+// RUN:   -fcxx-exceptions -target-cpu future %s -verify
+
+// vector quad
+
+// alias
+using vq_t = __vector_quad;
+void testVQAlias(int *inp, int *outp) {
+  vq_t *vqin = (vq_t *)inp;
+  vq_t *vqout = (vq_t *)outp;
+  *vqout = *vqin;
+}
+
+class TestClassVQ {
+  // method argument
+public:
+  void testVQArg1(__vector_quad vq, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = vq;
+    *vqp1 = vq;
+  }
+  void testVQArg2(const __vector_quad vq, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = vq;
+    *vqp2 = vq;
+  }
+  void testVQArg3(__vector_quad *vq, int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = *vq;
+    vqp1 = vqp;
+  }
+  void testVQArg4(const __vector_quad *const vq, int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = *vq;
+    vqp2 = vqp;
+  }
+  void testVQArg5(__vector_quad vqa[], int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = vqa[0];
+    *vqp1 = vqa[1];
+  }
+  void testVQArg6(const vq_t vq, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = vq;
+    *vqp2 = vq;
+  }
+  void testVQArg7(const vq_t *vq, int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    *vqp = *vq;
+    vqp1 = vqp;
+  }
+
+  // method return
+  __vector_quad testVQRet1(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    vq1 = *vqp;
+    return *vqp; // expected-error {{invalid use of PPC MMA type}}
+  }
+
+  __vector_quad *testVQRet2(int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    vq2 = *vqp;
+    return vqp + 2;
+  }
+
+  const __vector_quad *testVQRet3(int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    vqp1 = vqp;
+    return vqp + 2;
+  }
+
+  const vq_t testVQRet4(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    vqp2 = vqp;
+    return *vqp; // expected-error {{invalid use of PPC MMA type}}
+  }
+
+  const vq_t *testVQRet5(int *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    vq1 = *vqp;
+    return vqp + 2;
+  }
+
+  // template argument
+  template <typename T = __vector_quad>
+  void testVQTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}} \
+                                         expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}}
+    *(p + 1) = v;
+  }
+
+  // class field
+public:
+  __vector_quad vq1; // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad *vqp1;
+
+private:
+  vq_t vq2; // expected-error {{invalid use of PPC MMA type}}
+  vq_t *vqp2;
+};
+
+// template
+template <typename T>
+class ClassTemplateVQ1 {
+  T t; // expected-error {{invalid use of PPC MMA type}}
+};
+template <typename T>
+class ClassTemplateVQ2 {
+  T *t;
+};
+template <typename T>
+class ClassTemplateVQ3 {
+  int foo(T t) { return 10; }
+};
+template <typename T, typename... Ts>
+class ClassTemplateVQ4 {
+public:
+  T operator()(Ts...) const {} // expected-error {{invalid use of PPC MMA type}}
+};
+void testVQTemplate() {
+  ClassTemplateVQ1<__vector_quad> t1; // expected-note {{in instantiation of template class 'ClassTemplateVQ1<__vector_quad>' requested here}}
+  ClassTemplateVQ1<__vector_quad *> t2;
+  ClassTemplateVQ2<__vector_quad> t3;
+  ClassTemplateVQ2<__vector_quad *> t4;
+
+  ClassTemplateVQ3<int(int, int, int)> t5;
+  // The following case is not prevented but it ok, this function type cannot be
+  // instantiated because we prevent any function from returning an MMA type.
+  ClassTemplateVQ3<__vector_quad(int, int, int)> t6;
+  ClassTemplateVQ3<int(__vector_quad, int, int)> t7; // expected-error {{invalid use of PPC MMA type}}
+
+  ClassTemplateVQ4<int, int, int, __vector_quad> t8; // expected-note {{in instantiation of template class 'ClassTemplateVQ4<int, int, int, __vector_quad>' requested here}}
+  ClassTemplateVQ4<int, int, int, __vector_quad *> t9;
+
+  TestClassVQ tc;
+  __vector_quad vq;
+  __vector_quad *vqp = &vq;
+  tc.testVQTemplate(&vq, &vqp);
+  tc.testVQTemplate<vq_t *>(&vq, &vqp);
+  tc.testVQTemplate(vq, vqp);       // expected-error {{no matching member function for call to 'testVQTemplate'}}
+  tc.testVQTemplate<vq_t>(vq, vqp); // expected-error {{no matching member function for call to 'testVQTemplate'}}
+}
+
+// trailing return type
+auto testVQTrailing1() {
+  __vector_quad vq;
+  return vq; // expected-error {{invalid use of PPC MMA type}}
+}
+auto testVQTrailing2() {
+  __vector_quad *vqp;
+  return vqp;
+}
+auto testVQTrailing3() -> vq_t { // expected-error {{invalid use of PPC MMA type}}
+  __vector_quad vq;
+  return vq; // expected-error {{invalid use of PPC MMA type}}
+}
+auto testVQTrailing4() -> vq_t * {
+  __vector_quad *vqp;
+  return vqp;
+}
+
+// new/delete
+void testVQNewDelete() {
+  __vector_quad *vqp1 = new __vector_quad;
+  __vector_quad *vqp2 = new __vector_quad[100];
+  delete vqp1;
+  delete[] vqp2;
+}
+
+// lambdas expressions
+void TestVQLambda() {
+  auto f1 = [](void *ptr) -> __vector_quad {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    return *vqp; // expected-error {{invalid use of PPC MMA type}}
+  };
+  auto f2 = [](void *ptr) {
+    __vector_quad *vqp = (__vector_quad *)ptr;
+    return *vqp; // expected-error {{invalid use of PPC MMA type}}
+  };
+  auto f3 = [] { __vector_quad vq; __builtin_mma_xxsetaccz(&vq); return vq; }; // expected-error {{invalid use of PPC MMA type}}
+}
+
+// cast
+void TestVQCast() {
+  __vector_quad vq;
+  int *ip = reinterpret_cast<int *>(&vq);
+  __vector_quad *vq2 = reinterpret_cast<__vector_quad *>(ip);
+}
+
+// throw
+void TestVQThrow() {
+  __vector_quad vq;
+  throw vq; // expected-error {{invalid use of PPC MMA type}}
+}
+
+// vector pair
+
+// alias
+using vp_t = __vector_pair;
+void testVPAlias(int *inp, int *outp) {
+  vp_t *vpin = (vp_t *)inp;
+  vp_t *vpout = (vp_t *)outp;
+  *vpout = *vpin;
+}
+
+class TestClassVP {
+  // method argument
+public:
+  void testVPArg1(__vector_pair vp, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = vp;
+    *vpp1 = vp;
+  }
+  void testVPArg2(const __vector_pair vp, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = vp;
+    *vpp2 = vp;
+  }
+  void testVPArg3(__vector_pair *vp, int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = *vp;
+    vpp1 = vpp;
+  }
+  void testVPArg4(const __vector_pair *const vp, int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = *vp;
+    vpp2 = vpp;
+  }
+  void testVPArg5(__vector_pair vpa[], int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = vpa[0];
+    *vpp1 = vpa[1];
+  }
+  void testVPArg6(const vp_t vp, int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = vp;
+    *vpp2 = vp;
+  }
+  void testVPArg7(const vp_t *vp, int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    *vpp = *vp;
+    vpp1 = vpp;
+  }
+
+  // method return
+  __vector_pair testVPRet1(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    vp1 = *vpp;
+    return *vpp; // expected-error {{invalid use of PPC MMA type}}
+  }
+
+  __vector_pair *testVPRet2(int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    vp2 = *vpp;
+    return vpp + 2;
+  }
+
+  const __vector_pair *testVPRet3(int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    vpp1 = vpp;
+    return vpp + 2;
+  }
+
+  const vp_t testVPRet4(int *ptr) { // expected-error {{invalid use of PPC MMA type}}
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    vpp2 = vpp;
+    return *vpp; // expected-error {{invalid use of PPC MMA type}}
+  }
+
+  const vp_t *testVPRet5(int *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    vp1 = *vpp;
+    return vpp + 2;
+  }
+
+  // template argument
+  template <typename T = __vector_pair>
+  void testVPTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}} \
+                                         expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}}
+    *(p + 1) = v;
+  }
+
+  // class field
+public:
+  __vector_pair vp1; // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair *vpp1;
+
+private:
+  vp_t vp2; // expected-error {{invalid use of PPC MMA type}}
+  vp_t *vpp2;
+};
+
+// template
+template <typename T>
+class ClassTemplateVP1 {
+  T t; // expected-error {{invalid use of PPC MMA type}}
+};
+template <typename T>
+class ClassTemplateVP2 {
+  T *t;
+};
+template <typename T>
+class ClassTemplateVP3 {
+  int foo(T t) { return 10; }
+};
+template <typename T, typename... Ts>
+class ClassTemplateVP4 {
+public:
+  T operator()(Ts...) const {} // expected-error {{invalid use of PPC MMA type}}
+};
+void testVPTemplate() {
+  ClassTemplateVP1<__vector_pair> t1; // expected-note {{in instantiation of template class 'ClassTemplateVP1<__vector_pair>' requested here}}
+  ClassTemplateVP1<__vector_pair *> t2;
+  ClassTemplateVP2<__vector_pair> t3;
+  ClassTemplateVP2<__vector_pair *> t4;
+
+  ClassTemplateVP3<int(int, int, int)> t5;
+  // The following case is not prevented but it ok, this function type cannot be
+  // instantiated because we prevent any function from returning an MMA type.
+  ClassTemplateVP3<__vector_pair(int, int, int)> t6;
+  ClassTemplateVP3<int(__vector_pair, int, int)> t7; // expected-error {{invalid use of PPC MMA type}}
+
+  ClassTemplateVP4<int, int, int, __vector_pair> t8; // expected-note {{in instantiation of template class 'ClassTemplateVP4<int, int, int, __vector_pair>' requested here}}
+  ClassTemplateVP4<int, int, int, __vector_pair *> t9;
+
+  TestClassVP tc;
+  __vector_pair vp;
+  __vector_pair *vpp = &vp;
+  tc.testVPTemplate(&vp, &vpp);
+  tc.testVPTemplate<vp_t *>(&vp, &vpp);
+  tc.testVPTemplate(vp, vpp);       // expected-error {{no matching member function for call to 'testVPTemplate'}}
+  tc.testVPTemplate<vp_t>(vp, vpp); // expected-error {{no matching member function for call to 'testVPTemplate'}}
+}
+
+// trailing return type
+auto testVPTrailing1() {
+  __vector_pair vp;
+  return vp; // expected-error {{invalid use of PPC MMA type}}
+}
+auto testVPTrailing2() {
+  __vector_pair *vpp;
+  return vpp;
+}
+auto testVPTrailing3() -> vp_t { // expected-error {{invalid use of PPC MMA type}}
+  __vector_pair vp;
+  return vp; // expected-error {{invalid use of PPC MMA type}}
+}
+auto testVPTrailing4() -> vp_t * {
+  __vector_pair *vpp;
+  return vpp;
+}
+
+// new/delete
+void testVPNewDelete() {
+  __vector_pair *vpp1 = new __vector_pair;
+  __vector_pair *vpp2 = new __vector_pair[100];
+  delete vpp1;
+  delete[] vpp2;
+}
+
+// lambdas expressions
+void TestVPLambda() {
+  auto f1 = [](void *ptr) -> __vector_pair {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    return *vpp; // expected-error {{invalid use of PPC MMA type}}
+  };
+  auto f2 = [](void *ptr) {
+    __vector_pair *vpp = (__vector_pair *)ptr;
+    return *vpp; // expected-error {{invalid use of PPC MMA type}}
+  };
+  auto f3 = [](vector unsigned char vc) { __vector_pair vp; __builtin_mma_assemble_pair(&vp, vc, vc); return vp; }; // expected-error {{invalid use of PPC MMA type}}
+}
+
+// cast
+void TestVPCast() {
+  __vector_pair vp;
+  int *ip = reinterpret_cast<int *>(&vp);
+  __vector_pair *vp2 = reinterpret_cast<__vector_pair *>(ip);
+}
+
+// throw
+void TestVPThrow() {
+  __vector_pair vp;
+  throw vp; // expected-error {{invalid use of PPC MMA type}}
+}


        


More information about the cfe-commits mailing list