Author: erichkeane Date: 2024-11-13T12:42:53-08:00 New Revision: fa20b5d30d38f4bb090acac7c205fbb54a5ca990
URL: https://github.com/llvm/llvm-project/commit/fa20b5d30d38f4bb090acac7c205fbb54a5ca990 DIFF: https://github.com/llvm/llvm-project/commit/fa20b5d30d38f4bb090acac7c205fbb54a5ca990.diff LOG: [OpenACC] 'if' and 'self' clause implementation for Combined Constructs These two are identical to how they work for compute constructs, so this patch enables them and ensures there is sufficient testing. Added: clang/test/SemaOpenACC/combined-construct-if-ast.cpp clang/test/SemaOpenACC/combined-construct-if-clause.c clang/test/SemaOpenACC/combined-construct-if-clause.cpp clang/test/SemaOpenACC/combined-construct-self-ast.cpp clang/test/SemaOpenACC/combined-construct-self-clause.c clang/test/SemaOpenACC/combined-construct-self-clause.cpp Modified: clang/lib/Sema/SemaOpenACC.cpp clang/test/AST/ast-print-openacc-combined-construct.cpp clang/test/ParserOpenACC/parse-clauses.c clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c clang/test/SemaOpenACC/compute-construct-default-clause.c clang/test/SemaOpenACC/compute-construct-if-clause.c Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 78953a89f65e30..dd6558d0afed70 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -626,10 +626,11 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + // Restrictions only properly implemented on 'compute'/'combined' constructs, + // and 'compute'/'combined' constructs are the only construct that can do + // anything with this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // There is no prose in the standard that says duplicates aren't allowed, @@ -662,7 +663,8 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause( // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // TODO OpenACC: When we implement this for 'update', this takes a diff --git a/clang/test/AST/ast-print-openacc-combined-construct.cpp b/clang/test/AST/ast-print-openacc-combined-construct.cpp index d77465c69f4acb..b2a6799deb3fce 100644 --- a/clang/test/AST/ast-print-openacc-combined-construct.cpp +++ b/clang/test/AST/ast-print-openacc-combined-construct.cpp @@ -71,5 +71,19 @@ void foo() { #pragma acc kernels loop dtype(AnotherIdent) for(int i = 0;i<5;++i); + int i; + float array[5]; + +// CHECK: #pragma acc parallel self(i == 3) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop self(i == 3) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc kernels if(i == array[1]) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels if(i == array[1]) + for(int i = 0;i<5;++i); } diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index a0e01ef5a85a62..656b31444a9eed 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -266,11 +266,9 @@ void IfClause() { } void SelfClause() { - // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}} #pragma acc serial loop self for(int i = 0; i < 5;++i) {} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}} #pragma acc serial loop self, seq for(int i = 0; i < 5;++i) {} @@ -293,18 +291,15 @@ void SelfClause() { #pragma acc serial loop self(, seq for(int i = 0; i < 5;++i) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial loop self) for(int i = 0; i < 5;++i) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial loop self) seq for(int i = 0; i < 5;++i) {} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial loop self), seq for(int i = 0; i < 5;++i) {} diff --git a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c index 95cc7a7ed22949..8a062b6ac1d5d6 100644 --- a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c +++ b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c @@ -60,12 +60,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc parallel loop auto default(none) for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop auto if(1) for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} #pragma acc parallel loop auto self for(unsigned i = 0; i < 5; ++i); // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} @@ -234,12 +230,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc parallel loop default(none) auto for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop if(1) auto for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} #pragma acc parallel loop self auto for(unsigned i = 0; i < 5; ++i); // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} @@ -409,12 +401,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc parallel loop independent default(none) for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop independent if(1) for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} #pragma acc parallel loop independent self for(unsigned i = 0; i < 5; ++i); // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} @@ -583,12 +571,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc parallel loop default(none) independent for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop if(1) independent for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} #pragma acc parallel loop self independent for(unsigned i = 0; i < 5; ++i); // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} @@ -764,12 +748,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc parallel loop seq default(none) for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop seq if(1) for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} #pragma acc parallel loop seq self for(unsigned i = 0; i < 5; ++i); // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} @@ -944,12 +924,8 @@ void uses() { // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc parallel loop default(none) seq for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop if(1) seq for(unsigned i = 0; i < 5; ++i); - // TODOexpected-error@+1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}} - // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} #pragma acc parallel loop self seq for(unsigned i = 0; i < 5; ++i); // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} diff --git a/clang/test/SemaOpenACC/combined-construct-if-ast.cpp b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp new file mode 100644 index 00000000000000..f0796409d942d7 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER +void NormalFunc(int j, float f) { + // CHECK: FunctionDecl{{.*}}NormalFunc + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: CompoundStmt +#pragma acc kernels loop if( j < f) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating> + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'int' lvalue ParmVar{{.*}} 'j' 'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'float' lvalue ParmVar{{.*}} 'f' 'float' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} + +template<typename T> +void TemplFunc() { + // CHECK: FunctionTemplateDecl{{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + + // Match the prototype: + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop if(T::SomeFloat < typename T::IntTy{}) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '<dependent type>' '<' + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename T::IntTy' 'typename T::IntTy' + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop if(typename T::IntTy{}) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename T::IntTy' 'typename T::IntTy' + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop if(T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop if(T::BC) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // Match the instantiation: + // CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'InstTy' + // CHECK-NEXT: RecordType{{.*}} 'InstTy' + // CHECK-NEXT: CXXRecord{{.*}} 'InstTy' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating> + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp> + // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean> + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp> + // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'bool' <UserDefinedConversion> + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'bool' + // CHECK-NEXT: MemberExpr{{.*}} .operator bool + // CHECK-NEXT: DeclRefExpr{{.*}} 'const BoolConversion' lvalue Var{{.*}} 'BC' 'const BoolConversion' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} + +struct BoolConversion{ operator bool() const;}; +struct InstTy { + using IntTy = int; + static constexpr float SomeFloat = 5.0; + static constexpr BoolConversion BC; +}; + +void Instantiate() { + TemplFunc<InstTy>(); +} +#endif diff --git a/clang/test/SemaOpenACC/combined-construct-if-clause.c b/clang/test/SemaOpenACC/combined-construct-if-clause.c new file mode 100644 index 00000000000000..563f1cd25377bd --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-if-clause.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void BoolExpr(int *I, float *F) { + + typedef struct {} SomeStruct; + int Array[5]; + + struct C{}; + // expected-error@+1{{expected expression}} +#pragma acc parallel loop if (struct C f()) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial loop if (SomeStruct) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial loop if (SomeStruct()) + for (unsigned i = 0; i < 5; ++i); + + SomeStruct S; + // expected-error@+1{{statement requires expression of scalar type ('SomeStruct' invalid)}} +#pragma acc serial loop if (S) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+1{{address of array 'Array' will always evaluate to 'true'}} +#pragma acc kernels loop if (Array) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+4{{incompatible pointer types assigning to 'int *' from 'float *'}} + // expected-warning@+3{{using the result of an assignment as a condition without parentheses}} + // expected-note@+2{{place parentheses around the assignment to silence this warning}} + // expected-note@+1{{use '==' to turn this assignment into an equality comparison}} +#pragma acc kernels loop if (I = F) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop if (I) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc serial loop if (F) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop if (*I < *F) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'data' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc data if (*I < *F) + for (unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop if (*I < *F) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop if (*I < *F) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop if (*I < *F) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC 'if' clause is not valid on 'loop' directive}} +#pragma acc loop if(I) + for(int i = 5; i < 10;++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-if-clause.cpp b/clang/test/SemaOpenACC/combined-construct-if-clause.cpp new file mode 100644 index 00000000000000..cf1bdadd4c8921 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-if-clause.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NoBoolConversion{}; +struct BoolConversion{ + operator bool(); +}; + +template <typename T, typename U> +void BoolExpr() { + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel loop if (NoBoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+2{{no member named 'NotValid' in 'NoBoolConversion'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc serial loop if (T::NotValid) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop if (BoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc serial loop if (T{}) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop if (U{}) + for (unsigned i = 0; i < 5; ++i); +} + +void Instantiate() { + BoolExpr<NoBoolConversion, BoolConversion>(); // #INST +} diff --git a/clang/test/SemaOpenACC/combined-construct-self-ast.cpp b/clang/test/SemaOpenACC/combined-construct-self-ast.cpp new file mode 100644 index 00000000000000..3a6ba3ca6aea23 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-self-ast.cpp @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER + +template<typename T> +void TemplFunc() { + // CHECK: FunctionTemplateDecl{{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + + // Match the prototype: + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc serial loop self + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop self(T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: self clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop self(T::SomeFloat) if (T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: self clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop if(T::SomeFloat) self(T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: self clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + // + // Match the instantiation: + // CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'InstTy' + // CHECK-NEXT: RecordType{{.*}} 'InstTy' + // CHECK-NEXT: CXXRecord{{.*}} 'InstTy' + // CHECK-NEXT: CompoundStmt + // + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: self clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} + +struct BoolConversion{ operator bool() const;}; +struct InstTy { + using IntTy = int; + static constexpr float SomeFloat = 5.0; + static constexpr BoolConversion BC; +}; + +void Instantiate() { + TemplFunc<InstTy>(); +} +#endif diff --git a/clang/test/SemaOpenACC/combined-construct-self-clause.c b/clang/test/SemaOpenACC/combined-construct-self-clause.c new file mode 100644 index 00000000000000..39ad85eaf2e99c --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-self-clause.c @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void BoolExpr(int *I, float *F) { + typedef struct {} SomeStruct; + struct C{}; + // expected-error@+1{{expected expression}} +#pragma acc parallel loop self (struct C f()) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial loop self (SomeStruct) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc kernels loop self (SomeStruct()) + for (unsigned i = 0; i < 5; ++i); + + SomeStruct S; + // expected-error@+1{{statement requires expression of scalar type ('SomeStruct' invalid)}} +#pragma acc parallel loop self (S) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop self (I) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc serial loop self (F) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop self (*I < *F) + for (unsigned i = 0; i < 5; ++i); +} + +void WarnMaybeNotUsed(int val1, int val2) { + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop self if(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop self(val1) if(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop if(val1) self + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(val1) self(val2) + for (unsigned i = 0; i < 5; ++i); + + // The below don't warn because one side or the other has an error, thus is + // not added to the AST. + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc serial loop self if(invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc kernels loop self(invalid) if(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+2{{expected expression}} + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc parallel loop self() if(invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc serial loop if(invalid) self + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc kernels loop if(val2) self(invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc parallel loop if(invalid) self(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC 'self' clause is not valid on 'loop' directive}} +#pragma acc loop self + for(int i = 5; i < 10;++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-self-clause.cpp b/clang/test/SemaOpenACC/combined-construct-self-clause.cpp new file mode 100644 index 00000000000000..73f5a55d77c31b --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-self-clause.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NoBoolConversion{}; +struct BoolConversion{ + operator bool(); +}; + +template <typename T, typename U> +void BoolExpr() { + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel loop self (NoBoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + // expected-error@+2{{no member named 'NotValid' in 'NoBoolConversion'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc serial loop self (T::NotValid) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop self (BoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel loop self (T{}) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop self (U{}) + for (unsigned i = 0; i < 5; ++i); +} + +struct HasBool { + static constexpr bool B = true; +}; + +template<typename T> +void WarnMaybeNotUsed() { + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop self if(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop self(T::B) if(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop if(T::B) self + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::B) self(T::B) + for (unsigned i = 0; i < 5; ++i); + + // We still warn in the cases of dependent failures, since the diagnostic + // happens immediately rather than during instantiation. + + // expected-error@+4{{no member named 'Invalid' in 'HasBool'}} + // expected-note@#NOT_USED_INST{{in instantiation of function template specialization 'WarnMaybeNotUsed<HasBool>' requested here}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop self if(T::Invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop self(T::Invalid) if(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop self(T::B) if(T::Invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::Invalid) self + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::Invalid) self(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::B) self(T::Invalid) + for (unsigned i = 0; i < 5; ++i); +} + +void Instantiate() { + BoolExpr<NoBoolConversion, BoolConversion>(); // #INST + WarnMaybeNotUsed<HasBool>(); // #NOT_USED_INST +} diff --git a/clang/test/SemaOpenACC/compute-construct-default-clause.c b/clang/test/SemaOpenACC/compute-construct-default-clause.c index 519dbc173a6724..17f1b27a9b5838 100644 --- a/clang/test/SemaOpenACC/compute-construct-default-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-default-clause.c @@ -16,7 +16,6 @@ void SingleOnly() { #pragma acc kernels self default(present) present(i) default(none) copy(i) while(0); - // expected-warning@+5{{OpenACC clause 'self' not yet implemented}} // expected-warning@+4{{OpenACC clause 'default' not yet implemented}} // expected-warning@+3{{OpenACC clause 'private' not yet implemented}} // expected-warning@+2{{OpenACC clause 'default' not yet implemented}} @@ -24,7 +23,6 @@ void SingleOnly() { #pragma acc parallel loop self default(present) private(i) default(none) copy(i) for(int i = 0; i < 5; ++i); - // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} // expected-error@+1{{expected '('}} #pragma acc serial loop self default private(i) default(none) if(i) for(int i = 0; i < 5; ++i); diff --git a/clang/test/SemaOpenACC/compute-construct-if-clause.c b/clang/test/SemaOpenACC/compute-construct-if-clause.c index 877c9c33cbd2ee..7cdc35275acce0 100644 --- a/clang/test/SemaOpenACC/compute-construct-if-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-if-clause.c @@ -47,13 +47,10 @@ void BoolExpr(int *I, float *F) { // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc data if (*I < *F) while(0); - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop if (*I < *F) for(int i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc serial loop if (*I < *F) for(int i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc kernels loop if (*I < *F) for(int i = 0; i < 5; ++i); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits