[clang] fa20b5d - [OpenACC] 'if' and 'self' clause implementation for Combined Constructs
via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 13 12:43:04 PST 2024
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 at +1{{OpenACC clause 'self' not yet implemented, clause ignored}}
#pragma acc serial loop self
for(int i = 0; i < 5;++i) {}
- // expected-warning at +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 at +2{{expected identifier}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented, clause ignored}}
+ // expected-error at +1{{expected identifier}}
#pragma acc serial loop self)
for(int i = 0; i < 5;++i) {}
- // expected-error at +2{{expected identifier}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented, clause ignored}}
+ // expected-error at +1{{expected identifier}}
#pragma acc serial loop self) seq
for(int i = 0; i < 5;++i) {}
- // expected-error at +2{{expected identifier}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented, clause ignored}}
+ // expected-error at +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 at +1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop auto default(none)
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop auto if(1)
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
#pragma acc parallel loop auto self
for(unsigned i = 0; i < 5; ++i);
// TODOexpected-error at +1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}}
@@ -234,12 +230,8 @@ void uses() {
// expected-warning at +1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop default(none) auto
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop if(1) auto
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
#pragma acc parallel loop self auto
for(unsigned i = 0; i < 5; ++i);
// TODOexpected-error at +1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}}
@@ -409,12 +401,8 @@ void uses() {
// expected-warning at +1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop independent default(none)
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop independent if(1)
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
#pragma acc parallel loop independent self
for(unsigned i = 0; i < 5; ++i);
// TODOexpected-error at +1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}}
@@ -583,12 +571,8 @@ void uses() {
// expected-warning at +1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop default(none) independent
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop if(1) independent
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
#pragma acc parallel loop self independent
for(unsigned i = 0; i < 5; ++i);
// TODOexpected-error at +1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}}
@@ -764,12 +748,8 @@ void uses() {
// expected-warning at +1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop seq default(none)
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop seq if(1)
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
#pragma acc parallel loop seq self
for(unsigned i = 0; i < 5; ++i);
// TODOexpected-error at +1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}}
@@ -944,12 +924,8 @@ void uses() {
// expected-warning at +1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop default(none) seq
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'if' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop if(1) seq
for(unsigned i = 0; i < 5; ++i);
- // TODOexpected-error at +1{{OpenACC 'self' clause is not valid on 'parallel loop' directive}}
- // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
#pragma acc parallel loop self seq
for(unsigned i = 0; i < 5; ++i);
// TODOexpected-error at +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 at +1{{expected expression}}
+#pragma acc parallel loop if (struct C f())
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{unexpected type name 'SomeStruct': expected expression}}
+#pragma acc serial loop if (SomeStruct)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{unexpected type name 'SomeStruct': expected expression}}
+#pragma acc serial loop if (SomeStruct())
+ for (unsigned i = 0; i < 5; ++i);
+
+ SomeStruct S;
+ // expected-error at +1{{statement requires expression of scalar type ('SomeStruct' invalid)}}
+#pragma acc serial loop if (S)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +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 at +4{{incompatible pointer types assigning to 'int *' from 'float *'}}
+ // expected-warning at +3{{using the result of an assignment as a condition without parentheses}}
+ // expected-note at +2{{place parentheses around the assignment to silence this warning}}
+ // expected-note at +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 at +2{{OpenACC construct 'data' not yet implemented}}
+ // expected-warning at +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 at +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 at +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 at +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 at +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 at +1{{expected expression}}
+#pragma acc parallel loop self (struct C f())
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{unexpected type name 'SomeStruct': expected expression}}
+#pragma acc serial loop self (SomeStruct)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{unexpected type name 'SomeStruct': expected expression}}
+#pragma acc kernels loop self (SomeStruct())
+ for (unsigned i = 0; i < 5; ++i);
+
+ SomeStruct S;
+ // expected-error at +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 at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc parallel loop self if(val1)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc serial loop self(val1) if(val1)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc kernels loop if(val1) self
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +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 at +1{{use of undeclared identifier 'invalid'}}
+#pragma acc serial loop self if(invalid)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{use of undeclared identifier 'invalid'}}
+#pragma acc kernels loop self(invalid) if(val1)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +2{{expected expression}}
+ // expected-error at +1{{use of undeclared identifier 'invalid'}}
+#pragma acc parallel loop self() if(invalid)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{use of undeclared identifier 'invalid'}}
+#pragma acc serial loop if(invalid) self
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{use of undeclared identifier 'invalid'}}
+#pragma acc kernels loop if(val2) self(invalid)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +1{{use of undeclared identifier 'invalid'}}
+#pragma acc parallel loop if(invalid) self(val1)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +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 at +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 at +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 at +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 at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc parallel loop self if(T::B)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc kernels loop self(T::B) if(T::B)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc serial loop if(T::B) self
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +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 at +4{{no member named 'Invalid' in 'HasBool'}}
+ // expected-note@#NOT_USED_INST{{in instantiation of function template specialization 'WarnMaybeNotUsed<HasBool>' requested here}}
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc parallel loop self if(T::Invalid)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +3{{no member named 'Invalid' in 'HasBool'}}
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc serial loop self(T::Invalid) if(T::B)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +3{{no member named 'Invalid' in 'HasBool'}}
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc kernels loop self(T::B) if(T::Invalid)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +3{{no member named 'Invalid' in 'HasBool'}}
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc parallel loop if(T::Invalid) self
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +3{{no member named 'Invalid' in 'HasBool'}}
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc parallel loop if(T::Invalid) self(T::B)
+ for (unsigned i = 0; i < 5; ++i);
+
+ // expected-error at +3{{no member named 'Invalid' in 'HasBool'}}
+ // expected-warning at +2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
+ // expected-note at +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 at +5{{OpenACC clause 'self' not yet implemented}}
// expected-warning at +4{{OpenACC clause 'default' not yet implemented}}
// expected-warning at +3{{OpenACC clause 'private' not yet implemented}}
// expected-warning at +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 at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
// expected-error at +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 at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc data if (*I < *F)
while(0);
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc parallel loop if (*I < *F)
for(int i = 0; i < 5; ++i);
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc serial loop if (*I < *F)
for(int i = 0; i < 5; ++i);
- // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
#pragma acc kernels loop if (*I < *F)
for(int i = 0; i < 5; ++i);
More information about the cfe-commits
mailing list