diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9503,6 +9503,8 @@ "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 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12350,6 +12350,8 @@ 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 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3307,6 +3307,23 @@ 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 @@ << 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 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8037,6 +8037,14 @@ 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 @@ 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 @@ 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 @@ 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 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -884,6 +884,10 @@ 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 --- /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 --- /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 + 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 +class ClassTemplateVQ1 { + T t; // expected-error {{invalid use of PPC MMA type}} +}; +template +class ClassTemplateVQ2 { + T *t; +}; +template +class ClassTemplateVQ3 { + int foo(T t) { return 10; } +}; +template +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 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 t7; // expected-error {{invalid use of PPC MMA type}} + + ClassTemplateVQ4 t8; // expected-note {{in instantiation of template class 'ClassTemplateVQ4' requested here}} + ClassTemplateVQ4 t9; + + TestClassVQ tc; + __vector_quad vq; + __vector_quad *vqp = &vq; + tc.testVQTemplate(&vq, &vqp); + tc.testVQTemplate(&vq, &vqp); + tc.testVQTemplate(vq, vqp); // expected-error {{no matching member function for call to 'testVQTemplate'}} + tc.testVQTemplate(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(&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 + 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 +class ClassTemplateVP1 { + T t; // expected-error {{invalid use of PPC MMA type}} +}; +template +class ClassTemplateVP2 { + T *t; +}; +template +class ClassTemplateVP3 { + int foo(T t) { return 10; } +}; +template +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 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 t7; // expected-error {{invalid use of PPC MMA type}} + + ClassTemplateVP4 t8; // expected-note {{in instantiation of template class 'ClassTemplateVP4' requested here}} + ClassTemplateVP4 t9; + + TestClassVP tc; + __vector_pair vp; + __vector_pair *vpp = &vp; + tc.testVPTemplate(&vp, &vpp); + tc.testVPTemplate(&vp, &vpp); + tc.testVPTemplate(vp, vpp); // expected-error {{no matching member function for call to 'testVPTemplate'}} + tc.testVPTemplate(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(&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}} +}