[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
This commit is contained in:
Baptiste Saleil 2020-11-04 17:00:48 -06:00
parent 418de7d5d8
commit f976ba6139
7 changed files with 760 additions and 0 deletions

View File

@ -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<

View File

@ -12350,6 +12350,8 @@ private:
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);

View File

@ -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) ---------------===//

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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}}
}

View File

@ -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}}
}