diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 06a0098bbda4c..27e4e1a12c983 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -51,6 +51,36 @@ class OpenACCClauseWithParams : public OpenACCClause { SourceLocation getLParenLoc() const { return LParenLoc; } }; +/// A 'default' clause, has the optional 'none' or 'present' argument. +class OpenACCDefaultClause : public OpenACCClauseWithParams { + friend class ASTReaderStmt; + friend class ASTWriterStmt; + + OpenACCDefaultClauseKind DefaultClauseKind; + +protected: + OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc, + EndLoc), + DefaultClauseKind(K) { + assert((DefaultClauseKind == OpenACCDefaultClauseKind::None || + DefaultClauseKind == OpenACCDefaultClauseKind::Present) && + "Invalid Clause Kind"); + } + +public: + OpenACCDefaultClauseKind getDefaultClauseKind() const { + return DefaultClauseKind; + } + + static OpenACCDefaultClause *Create(const ASTContext &C, + OpenACCDefaultClauseKind K, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); +}; + template class OpenACCClauseVisitor { Impl &getDerived() { return static_cast(*this); } @@ -66,6 +96,8 @@ template class OpenACCClauseVisitor { switch (C->getClauseKind()) { case OpenACCClauseKind::Default: + VisitOpenACCDefaultClause(*cast(C)); + return; case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -112,6 +144,10 @@ template class OpenACCClauseVisitor { } llvm_unreachable("Invalid Clause kind"); } + + void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause) { + return getDerived().VisitOpenACCDefaultClause(Clause); + } }; class OpenACCClausePrinter final @@ -128,6 +164,8 @@ class OpenACCClausePrinter final } } OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {} + + void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause); }; } // namespace clang diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4fbbc42273ba9..7e18f6f144af4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12254,6 +12254,10 @@ def err_acc_construct_appertainment "be used in a statement context">; def err_acc_clause_appertainment : Error<"OpenACC '%1' clause is not valid on '%0' directive">; +def err_acc_duplicate_clause_disallowed + : Error<"OpenACC '%1' clause cannot appear more than once on a '%0' " + "directive">; +def note_acc_previous_clause_here : Note<"previous clause is here">; def err_acc_branch_in_out_compute_construct : Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 " "OpenACC Compute Construct">; diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index 4456f4afd142d..57dab78e6861f 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -419,6 +419,29 @@ enum class OpenACCDefaultClauseKind { Invalid, }; +template +inline StreamTy &printOpenACCDefaultClauseKind(StreamTy &Out, + OpenACCDefaultClauseKind K) { + switch (K) { + case OpenACCDefaultClauseKind::None: + return Out << "none"; + case OpenACCDefaultClauseKind::Present: + return Out << "present"; + case OpenACCDefaultClauseKind::Invalid: + return Out << ""; + } +} + +inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, + OpenACCDefaultClauseKind K) { + return printOpenACCDefaultClauseKind(Out, K); +} + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out, + OpenACCDefaultClauseKind K) { + return printOpenACCDefaultClauseKind(Out, K); +} + enum class OpenACCReductionOperator { /// '+'. Addition, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 45929e4a9db3f..27aaee164a288 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -19,6 +19,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/SemaBase.h" +#include namespace clang { class OpenACCClause; @@ -35,7 +36,11 @@ class SemaOpenACC : public SemaBase { SourceRange ClauseRange; SourceLocation LParenLoc; - // TODO OpenACC: Add variant here to store details of individual clauses. + struct DefaultDetails { + OpenACCDefaultClauseKind DefaultClauseKind; + }; + + std::variant Details; public: OpenACCParsedClause(OpenACCDirectiveKind DirKind, @@ -52,8 +57,20 @@ class SemaOpenACC : public SemaBase { SourceLocation getEndLoc() const { return ClauseRange.getEnd(); } + OpenACCDefaultClauseKind getDefaultClauseKind() const { + assert(ClauseKind == OpenACCClauseKind::Default && + "Parsed clause is not a default clause"); + return std::get(Details).DefaultClauseKind; + } + void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } + + void setDefaultDetails(OpenACCDefaultClauseKind DefKind) { + assert(ClauseKind == OpenACCClauseKind::Default && + "Parsed clause is not a default clause"); + Details = DefaultDetails{DefKind}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index e1db872f25c32..c83128b60e3ac 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -15,3 +15,22 @@ #include "clang/AST/ASTContext.h" using namespace clang; + +OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C, + OpenACCDefaultClauseKind K, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + void *Mem = + C.Allocate(sizeof(OpenACCDefaultClause), alignof(OpenACCDefaultClause)); + + return new (Mem) OpenACCDefaultClause(K, BeginLoc, LParenLoc, EndLoc); +} + +//===----------------------------------------------------------------------===// +// OpenACC clauses printing methods +//===----------------------------------------------------------------------===// +void OpenACCClausePrinter::VisitOpenACCDefaultClause( + const OpenACCDefaultClause &C) { + OS << "default(" << C.getDefaultClauseKind() << ")"; +} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index bec8bc71f5554..be3dd4b673cf9 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2456,7 +2456,12 @@ class OpenACCClauseProfiler Visit(Clause); } } + void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause); }; + +/// Nothing to do here, there are no sub-statements. +void OpenACCClauseProfiler::VisitOpenACCDefaultClause( + const OpenACCDefaultClause &Clause) {} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 431f5d8bdb2b5..085a7f51ce99a 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -390,6 +390,17 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { { ColorScope Color(OS, ShowColors, AttrColor); OS << C->getClauseKind(); + + // Handle clauses with parens for types that have no children, likely + // because there is no sub expression. + switch (C->getClauseKind()) { + case OpenACCClauseKind::Default: + OS << '(' << cast(C)->getDefaultClauseKind() << ')'; + break; + default: + // Nothing to do here. + break; + } } dumpPointer(C); dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index f434e1542c801..59a4a5f534676 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -831,9 +831,13 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( ConsumeToken(); - if (getOpenACCDefaultClauseKind(DefKindTok) == - OpenACCDefaultClauseKind::Invalid) + OpenACCDefaultClauseKind DefKind = + getOpenACCDefaultClauseKind(DefKindTok); + + if (DefKind == OpenACCDefaultClauseKind::Invalid) Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); + else + ParsedClause.setDefaultDetails(DefKind); break; } diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 2ba1e49b5739d..b6afb80b873e2 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -39,11 +39,27 @@ bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K, bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, OpenACCClauseKind ClauseKind) { - // FIXME: For each clause as we implement them, we can add the - // 'legalization' list here. - - // Do nothing so we can go to the 'unimplemented' diagnostic instead. - return true; + switch (ClauseKind) { + // FIXME: For each clause as we implement them, we can add the + // 'legalization' list here. + case OpenACCClauseKind::Default: + switch (DirectiveKind) { + case OpenACCDirectiveKind::Parallel: + case OpenACCDirectiveKind::Serial: + case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: + case OpenACCDirectiveKind::Data: + return true; + default: + return false; + } + default: + // Do nothing so we can go to the 'unimplemented' diagnostic instead. + return true; + } + llvm_unreachable("Invalid clause kind"); } } // namespace @@ -63,8 +79,43 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, return nullptr; } - // TODO OpenACC: Switch over the clauses we implement here and 'create' - // them. + switch (Clause.getClauseKind()) { + case OpenACCClauseKind::Default: { + // 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 (Clause.getDirectiveKind() != OpenACCDirectiveKind::Parallel && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Serial && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Kernels) + break; + + // Don't add an invalid clause to the AST. + if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid) + return nullptr; + + // OpenACC 3.3, Section 2.5.4: + // At most one 'default' clause may appear, and it must have a value of + // either 'none' or 'present'. + // Second half of the sentence is diagnosed during parsing. + auto Itr = llvm::find_if(ExistingClauses, [](const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::Default; + }); + + if (Itr != ExistingClauses.end()) { + SemaRef.Diag(Clause.getBeginLoc(), + diag::err_acc_duplicate_clause_disallowed) + << Clause.getDirectiveKind() << Clause.getClauseKind(); + SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + return nullptr; + } + + return OpenACCDefaultClause::Create( + getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(), + Clause.getLParenLoc(), Clause.getEndLoc()); + } + default: + break; + } Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented) << Clause.getClauseKind(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 13d7b00430d52..25e011a8ba6d8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4034,6 +4034,11 @@ class TreeTransform { llvm::SmallVector TransformOpenACCClauseList(OpenACCDirectiveKind DirKind, ArrayRef OldClauses); + + OpenACCClause * + TransformOpenACCClause(ArrayRef ExistingClauses, + OpenACCDirectiveKind DirKind, + const OpenACCClause *OldClause); }; template @@ -11074,13 +11079,44 @@ OMPClause *TreeTransform::TransformOMPXBareClause(OMPXBareClause *C) { //===----------------------------------------------------------------------===// // OpenACC transformation //===----------------------------------------------------------------------===// +template +OpenACCClause *TreeTransform::TransformOpenACCClause( + ArrayRef ExistingClauses, + OpenACCDirectiveKind DirKind, const OpenACCClause *OldClause) { + + SemaOpenACC::OpenACCParsedClause ParsedClause( + DirKind, OldClause->getClauseKind(), OldClause->getBeginLoc()); + ParsedClause.setEndLoc(OldClause->getEndLoc()); + + if (const auto *WithParms = dyn_cast(OldClause)) + ParsedClause.setLParenLoc(WithParms->getLParenLoc()); + + switch (OldClause->getClauseKind()) { + case OpenACCClauseKind::Default: + // There is nothing to do here as nothing dependent can appear in this + // clause. So just set the values so Sema can set the right value. + ParsedClause.setDefaultDetails( + cast(OldClause)->getDefaultClauseKind()); + break; + default: + assert(false && "Unhandled OpenACC clause in TreeTransform"); + return nullptr; + } + + return getSema().OpenACC().ActOnClause(ExistingClauses, ParsedClause); +} + template llvm::SmallVector TreeTransform::TransformOpenACCClauseList( OpenACCDirectiveKind DirKind, ArrayRef OldClauses) { - // TODO OpenACC: Ensure we loop through the list and transform the individual - // clauses. - return {}; + llvm::SmallVector TransformedClauses; + for (const auto *Clause : OldClauses) { + if (OpenACCClause *TransformedClause = getDerived().TransformOpenACCClause( + TransformedClauses, DirKind, Clause)) + TransformedClauses.push_back(TransformedClause); + } + return TransformedClauses; } template diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index fa5bb9f2d5435..679302e7a838f 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11763,7 +11763,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { [[maybe_unused]] SourceLocation EndLoc = readSourceLocation(); switch (ClauseKind) { - case OpenACCClauseKind::Default: + case OpenACCClauseKind::Default: { + SourceLocation LParenLoc = readSourceLocation(); + OpenACCDefaultClauseKind DCK = readEnum(); + return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc, + EndLoc); + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index baf03f69d7306..4cd74b1ba9d72 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7406,7 +7406,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeSourceLocation(C->getEndLoc()); switch (C->getClauseKind()) { - case OpenACCClauseKind::Default: + case OpenACCClauseKind::Default: { + const auto *DC = cast(C); + writeSourceLocation(DC->getLParenLoc()); + writeEnum(DC->getDefaultClauseKind()); + return; + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index b58b332ad3245..b363a0cb1362b 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -173,45 +173,37 @@ void DefaultClause() { #pragma acc serial default), seq for(;;){} - // expected-error@+2{{expected identifier}} - // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial default() for(;;){} - // expected-error@+3{{expected identifier}} - // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}} + // expected-error@+2{{expected identifier}} // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial default() seq for(;;){} - // expected-error@+3{{expected identifier}} - // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}} + // expected-error@+2{{expected identifier}} // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial default(), seq for(;;){} - // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}} - // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}} + // expected-error@+1{{invalid value for 'default' clause; expected 'present' or 'none'}} #pragma acc serial default(invalid) for(;;){} - // expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}} - // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}} + // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}} // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial default(auto) seq for(;;){} - // expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}} - // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}} + // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}} // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial default(invalid), seq for(;;){} - // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}} #pragma acc serial default(none) for(;;){} - // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}} // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial default(present), seq for(;;){} diff --git a/clang/test/SemaOpenACC/compute-construct-ast.cpp b/clang/test/SemaOpenACC/compute-construct-ast.cpp index 55c080838a188..e632522f877b5 100644 --- a/clang/test/SemaOpenACC/compute-construct-ast.cpp +++ b/clang/test/SemaOpenACC/compute-construct-ast.cpp @@ -12,14 +12,16 @@ void NormalFunc() { // CHECK-LABEL: NormalFunc // CHECK-NEXT: CompoundStmt // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel + // CHECK-NEXT: default(none) // CHECK-NEXT: CompoundStmt -#pragma acc parallel +#pragma acc parallel default(none) { #pragma acc parallel // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel + // CHECK-NEXT: default(present) // CHECK-NEXT: CompoundStmt -#pragma acc parallel +#pragma acc parallel default(present) {} } // FIXME: Add a test once we have clauses for this. @@ -50,12 +52,12 @@ void NormalFunc() { template void TemplFunc() { -#pragma acc parallel +#pragma acc parallel default(none) { typename T::type I; } -#pragma acc serial +#pragma acc serial default(present) { typename T::type I; } @@ -72,10 +74,12 @@ void TemplFunc() { // CHECK-NEXT: FunctionDecl // CHECK-NEXT: CompoundStmt // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel + // CHECK-NEXT: default(none) // CHECK-NEXT: CompoundStmt // CHECK-NEXT: DeclStmt // CHECK-NEXT: VarDecl{{.*}} I 'typename T::type' // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial + // CHECK-NEXT: default(present) // CHECK-NEXT: CompoundStmt // CHECK-NEXT: DeclStmt // CHECK-NEXT: VarDecl{{.*}} I 'typename T::type' @@ -91,10 +95,12 @@ void TemplFunc() { // CHECK-NEXT: CXXRecord // CHECK-NEXT: CompoundStmt // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel + // CHECK-NEXT: default(none) // CHECK-NEXT: CompoundStmt // CHECK-NEXT: DeclStmt // CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int' // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial + // CHECK-NEXT: default(present) // CHECK-NEXT: CompoundStmt // CHECK-NEXT: DeclStmt // CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int' diff --git a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp new file mode 100644 index 0000000000000..bd80103445028 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp @@ -0,0 +1,74 @@ +// 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() { + // CHECK: FunctionDecl{{.*}}NormalFunc + // CHECK-NEXT: CompoundStmt +#pragma acc parallel default(none) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: default(none) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + +#pragma acc serial default(present) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial + // CHECK-NEXT: default(present) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt +} + +template +void TemplFunc() { + // CHECK: FunctionTemplateDecl{{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + + // Match the prototype: + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels default(none) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: default(none) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + +#pragma acc parallel default(present) + while(true); + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: default(present) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + + // Match the instantiation: + // CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType + // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: default(none) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: default(present) + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: NullStmt +} + +void Instantiate() { + TemplFunc(); +} +#endif diff --git a/clang/test/SemaOpenACC/compute-construct-default-clause.c b/clang/test/SemaOpenACC/compute-construct-default-clause.c new file mode 100644 index 0000000000000..b1235fcca1f6a --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-default-clause.c @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void SingleOnly() { + #pragma acc parallel default(none) + while(0); + + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'serial' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc serial default(present) seq default(none) + while(0); + + // expected-warning@+5{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+4{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'kernels' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc kernels seq default(present) seq default(none) seq + while(0); + + // expected-warning@+6{{OpenACC construct 'parallel loop' not yet implemented}} + // expected-warning@+5{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+4{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'default' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} + #pragma acc parallel loop seq default(present) seq default(none) seq + while(0); + + // expected-warning@+3{{OpenACC construct 'serial loop' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+1{{expected '('}} + #pragma acc serial loop seq default seq default(none) seq + while(0); + + // expected-warning@+2{{OpenACC construct 'kernels loop' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} + #pragma acc kernels loop default(none) + while(0); + + // expected-warning@+2{{OpenACC construct 'data' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} + #pragma acc data default(none) + while(0); + + // expected-warning@+2{{OpenACC construct 'loop' not yet implemented}} + // expected-error@+1{{OpenACC 'default' clause is not valid on 'loop' directive}} + #pragma acc loop default(none) + while(0); + + // expected-warning@+2{{OpenACC construct 'wait' not yet implemented}} + // expected-error@+1{{OpenACC 'default' clause is not valid on 'wait' directive}} + #pragma acc wait default(none) + while(0); +} diff --git a/clang/test/SemaOpenACC/compute-construct-default-clause.cpp b/clang/test/SemaOpenACC/compute-construct-default-clause.cpp new file mode 100644 index 0000000000000..2c3e711ffd085 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-default-clause.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void SingleOnly() { + #pragma acc parallel default(none) + while(false); + + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'parallel' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc parallel default(present) seq default(none) + while(false); + + // expected-warning@+5{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+4{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'serial' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc serial seq default(present) seq default(none) seq + while(false); + + // expected-warning@+5{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+4{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'kernels' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc kernels seq default(present) seq default(none) seq + while(false); + + // expected-warning@+3{{OpenACC clause 'seq' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'seq' not yet implemented}} + // expected-error@+1{{expected '('}} + #pragma acc parallel seq default(none) seq default seq + while(false); +} + +void Instantiate() { + SingleOnly(); +}