[clang] [OpenACC] Implement beginning parts of the 'parallel' Sema impl (PR #81659)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 13 12:07:27 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
This patch Implements AST node creation and appertainment enforcement for 'parallel', as well as changes the 'not implemented' messages to be more specific. It does not deal with clauses/clause legality, nor a few of the other rules from the standard, but this gets us most of the way for a framework for future construct implementation.
---
Patch is 210.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81659.diff
24 Files Affected:
- (modified) clang/include/clang/AST/ASTContext.h (+2)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+11)
- (modified) clang/include/clang/Parse/Parser.h (+15-1)
- (modified) clang/include/clang/Sema/Sema.h (+45)
- (modified) clang/lib/AST/ASTContext.cpp (+6)
- (modified) clang/lib/Parse/ParseOpenACC.cpp (+36-8)
- (modified) clang/lib/Sema/CMakeLists.txt (+1)
- (added) clang/lib/Sema/SemaOpenACC.cpp (+132)
- (modified) clang/lib/Sema/TreeTransform.h (+15-1)
- (modified) clang/test/ParserOpenACC/parse-cache-construct.c (+29-29)
- (modified) clang/test/ParserOpenACC/parse-cache-construct.cpp (+16-16)
- (modified) clang/test/ParserOpenACC/parse-clauses.c (+949-543)
- (modified) clang/test/ParserOpenACC/parse-clauses.cpp (+39-25)
- (modified) clang/test/ParserOpenACC/parse-constructs.c (+63-60)
- (modified) clang/test/ParserOpenACC/parse-constructs.cpp (+14-14)
- (modified) clang/test/ParserOpenACC/parse-wait-clause.c (+72-36)
- (modified) clang/test/ParserOpenACC/parse-wait-construct.c (+36-36)
- (modified) clang/test/ParserOpenACC/unimplemented.c (+6-9)
- (modified) clang/test/ParserOpenACC/unimplemented.cpp (+6-9)
- (added) clang/test/SemaOpenACC/compute-construct-ast.cpp (+56)
- (added) clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp (+18)
- (added) clang/test/SemaOpenACC/parallel-loc-and-stmt.c (+46)
- (added) clang/test/SemaOpenACC/parallel-loc-and-stmt.cpp (+61)
- (added) clang/test/SemaOpenACC/unimplemented-construct.c (+39)
``````````diff
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 12ce9af1e53f63..b8bdb74cfbb865 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3381,6 +3381,8 @@ OPT_LIST(V)
StringRef getCUIDHash() const;
+ void setOpenACCStructuredBlock(OpenACCComputeConstruct *C, Stmt *S);
+
private:
/// All OMPTraitInfo objects live in this collection, one per
/// `pragma omp [begin] declare variant` directive.
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 754733a6c5fffd..622dd78936878c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12184,4 +12184,15 @@ def err_wasm_builtin_arg_must_match_table_element_type : Error <
"%ordinal0 argument must match the element type of the WebAssembly table in the %ordinal1 argument">;
def err_wasm_builtin_arg_must_be_integer_type : Error <
"%ordinal0 argument must be an integer">;
+
+// OpenACC diagnostics.
+def warn_acc_construct_unimplemented
+ : Warning<"OpenACC construct '%0' not yet implemented, pragma ignored">,
+ InGroup<SourceUsesOpenACC>;
+def warn_acc_clause_unimplemented
+ : Warning<"OpenACC clause '%0' not yet implemented, clause ignored">,
+ InGroup<SourceUsesOpenACC>;
+def err_acc_construct_appertainment
+ : Error<"OpenACC construct '%0' cannot be used here; it can only "
+ "be used in a statement context">;
} // end of sema component.
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index da18cf88edcc92..69b9e837fe8bef 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3572,7 +3572,21 @@ class Parser : public CodeCompletionHandler {
StmtResult ParseOpenACCDirectiveStmt();
private:
- void ParseOpenACCDirective();
+ /// A struct to hold the information that got parsed by ParseOpenACCDirective,
+ /// so that the callers of it can use that to construct the appropriate AST
+ /// nodes.
+ struct OpenACCDirectiveParseInfo {
+ OpenACCDirectiveKind DirKind;
+ SourceLocation StartLoc;
+ SourceLocation EndLoc;
+ // TODO OpenACC: Add Clause list here once we have a type for that.
+ // TODO OpenACC: As we implement support for the Atomic, Routine, Cache, and
+ // Wait constructs, we likely want to put that information in here as well.
+ };
+
+ /// Parses the OpenACC directive (the entire pragma) including the clause
+ /// list, but does not produce the main AST node.
+ OpenACCDirectiveParseInfo ParseOpenACCDirective();
/// Helper that parses an ID Expression based on the language options.
ExprResult ParseOpenACCIDExpression();
/// Parses the variable list for the `cache` construct.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ed933f27f8df6b..0bb1484e9b0e96 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -33,6 +33,7 @@
#include "clang/AST/NSAPI.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtOpenACC.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
@@ -41,6 +42,7 @@
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/ExpressionTraits.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/PragmaKinds.h"
@@ -12704,6 +12706,49 @@ class Sema final {
OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc,
SourceLocation EndLoc);
+ //===--------------------------------------------------------------------===//
+ // OpenACC directives and clauses.
+
+ /// Called after parsing an OpenACC Clause so that it can be checked.
+ bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind,
+ SourceLocation StartLoc);
+
+ /// Called after the construct has been parsed, but clauses haven't been
+ /// parsed. This allows us to diagnose not-implemented, as well as set up any
+ /// state required for parsing the clauses.
+ void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc);
+
+ /// Called after the directive, including its clauses, have been parsed and
+ /// parsing has consumed the 'annot_pragma_openacc_end' token, so we are safe
+ /// to allocate all trailing storage. This DOES happen before any associated
+ /// declarations or statements have been parsed. This function is only called
+ /// when we are parsing a 'statement' context.
+ StmtResult ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called after the directive, including its clauses, have been parsed and
+ /// parsing has consumed the 'annot_pragma_openacc_end' token, so we are safe
+ /// to allocate all trailing storage. This DOES happen before any associated
+ /// declarations or statements have been parsed. This function is only called
+ /// when we are parsing a 'Decl' context.
+ void ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called when we encounter an associated statement for our construct, this
+ /// should check legality of the statement as it appertains to this Construct,
+ /// and returns the modified Construct.
+ StmtResult
+ ActOnOpenACCAssociatedStmt(OpenACCAssociatedStmtConstruct *Construct,
+ Stmt *AssocStmt);
+
+ /// Called after the directive has been completely parsed, including the
+ /// declaration group or associated statement.
+ void ActOnEndOpenACCStmtDirective(StmtResult Construct);
+ /// Called after the directive has been completely parsed, including the
+ /// declaration group or associated statement.
+ void ActOnEndOpenACCDeclDirective();
+
/// The kind of conversion being performed.
enum CheckedConversionKind {
/// An implicit conversion.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 78a04b4c694267..e0ec956564b006 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -41,6 +41,7 @@
#include "clang/AST/RawCommentList.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtOpenACC.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -13662,3 +13663,8 @@ StringRef ASTContext::getCUIDHash() const {
CUIDHash = llvm::utohexstr(llvm::MD5Hash(LangOpts.CUID), /*LowerCase=*/true);
return CUIDHash;
}
+
+void ASTContext::setOpenACCStructuredBlock(OpenACCComputeConstruct *C,
+ Stmt *S) {
+ C->setStructuredBlock(S);
+}
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index e099d077198d09..f71c8570897901 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -745,9 +745,14 @@ bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) {
<< getCurToken().getIdentifierInfo();
// Consume the clause name.
- ConsumeToken();
+ SourceLocation ClauseLoc = ConsumeToken();
+
+ bool ParamsResult = ParseOpenACCClauseParams(DirKind, Kind);
- return ParseOpenACCClauseParams(DirKind, Kind);
+ // TODO OpenACC: this whole function should return a 'clause' type optional
+ // instead of bool, so we likely want to return the clause here.
+ getActions().ActOnOpenACCClause(Kind, ClauseLoc);
+ return ParamsResult;
}
bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
@@ -1116,9 +1121,12 @@ void Parser::ParseOpenACCCacheVarList() {
}
}
-void Parser::ParseOpenACCDirective() {
+Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
+ SourceLocation StartLoc = getCurToken().getLocation();
OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);
+ getActions().ActOnOpenACCConstruct(DirKind, StartLoc);
+
// Once we've parsed the construct/directive name, some have additional
// specifiers that need to be taken care of. Atomic has an 'atomic-clause'
// that needs to be parsed.
@@ -1172,10 +1180,11 @@ void Parser::ParseOpenACCDirective() {
// Parses the list of clauses, if present.
ParseOpenACCClauseList(DirKind);
- Diag(getCurToken(), diag::warn_pragma_acc_unimplemented);
assert(Tok.is(tok::annot_pragma_openacc_end) &&
"Didn't parse all OpenACC Clauses");
- ConsumeAnnotationToken();
+ SourceLocation EndLoc = ConsumeAnnotationToken();
+ assert(EndLoc.isValid());
+ return OpenACCDirectiveParseInfo{DirKind, StartLoc, EndLoc};
}
// Parse OpenACC directive on a declaration.
@@ -1185,7 +1194,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() {
ParsingOpenACCDirectiveRAII DirScope(*this);
ConsumeAnnotationToken();
- ParseOpenACCDirective();
+ OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
+ getActions().ActOnStartOpenACCDeclDirective(DirInfo.DirKind, DirInfo.StartLoc,
+ DirInfo.EndLoc);
+ // TODO OpenACC: Handle the declaration here.
+ getActions().ActOnEndOpenACCDeclDirective();
return nullptr;
}
@@ -1197,7 +1210,22 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
ParsingOpenACCDirectiveRAII DirScope(*this);
ConsumeAnnotationToken();
- ParseOpenACCDirective();
+ OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
+ StmtResult Result = getActions().ActOnStartOpenACCStmtDirective(
+ DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc);
+
+ // Parse associated statements if we are parsing a construct that takes a
+ // statement.
+ if (Result.isUsable()) {
+ if (auto *ASC = dyn_cast<OpenACCAssociatedStmtConstruct>(Result.get())) {
+ ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
+ StmtResult AssocStmt = ParseStatement();
+
+ if (AssocStmt.isUsable())
+ Result = getActions().ActOnOpenACCAssociatedStmt(ASC, AssocStmt.get());
+ }
+ }
+ getActions().ActOnEndOpenACCStmtDirective(Result);
- return StmtEmpty();
+ return Result;
}
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 1856a88e9a3271..862f9d4ffb825d 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -52,6 +52,7 @@ add_clang_library(clangSema
SemaLookup.cpp
SemaModule.cpp
SemaObjCProperty.cpp
+ SemaOpenACC.cpp
SemaOpenMP.cpp
SemaOverload.cpp
SemaPseudoObject.cpp
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
new file mode 100644
index 00000000000000..2e4853ea80dda2
--- /dev/null
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -0,0 +1,132 @@
+//===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements semantic analysis for OpenACC constructs and
+/// clauses.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/OpenACCKinds.h"
+#include "clang/Sema/Sema.h"
+
+using namespace clang;
+
+namespace {
+bool DiagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K,
+ SourceLocation StartLoc, bool IsStmt) {
+ switch (K) {
+ default:
+ case OpenACCDirectiveKind::Invalid:
+ // Nothing to do here, both invalid and unimplemented don't really need to
+ // do anything.
+ break;
+ case OpenACCDirectiveKind::Parallel:
+ if (!IsStmt)
+ return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
+ break;
+ }
+ return false;
+}
+} // namespace
+
+bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind,
+ SourceLocation StartLoc) {
+ // TODO OpenACC: this will probably want to take the Directive Kind as well to
+ // help with legalization.
+ if (ClauseKind == OpenACCClauseKind::Invalid)
+ return false;
+ // For now just diagnose that it is unsupported and leave the parsing to do
+ // whatever it can do. This function will eventually need to start returning
+ // some sort of Clause AST type, but for now just return true/false based on
+ // success.
+ return Diag(StartLoc, diag::warn_acc_clause_unimplemented) << ClauseKind;
+}
+
+void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K,
+ SourceLocation StartLoc) {
+ switch (K) {
+ case OpenACCDirectiveKind::Invalid:
+ // Nothing to do here, an invalid kind has nothing we can check here. We
+ // want to continue parsing clauses as far as we can, so we will just
+ // ensure that we can still work and don't check any construct-specific
+ // rules anywhere.
+ break;
+ case OpenACCDirectiveKind::Parallel:
+ // Nothing to do here, there is no real legalization that needs to happen
+ // here as these constructs do not take any arguments.
+ break;
+ default:
+ Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K;
+ break;
+ }
+}
+
+void Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ // TODO OpenACC: This should likely return something with the modified
+ // declaration. At the moment, only handle appertainment.
+ DiagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
+}
+
+void Sema::ActOnEndOpenACCDeclDirective() {
+ // TODO OpenACC: Should diagnose anything having to do with the associated
+ // statement, or any clause diagnostics that can only be done at the 'end' of
+ // the directive. We should also close any 'block' marking now that the decl
+ // parsing is complete.
+}
+
+StmtResult Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (DiagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true))
+ return StmtError();
+ switch (K) {
+ case OpenACCDirectiveKind::Invalid:
+ return StmtError();
+ default:
+ return StmtEmpty();
+ case OpenACCDirectiveKind::Parallel:
+ return OpenACCComputeConstruct::Create(getASTContext(), K, StartLoc,
+ EndLoc);
+ }
+ llvm_unreachable("Unhandled case in directive handling?");
+}
+
+StmtResult
+Sema::ActOnOpenACCAssociatedStmt(OpenACCAssociatedStmtConstruct *Construct,
+ Stmt *AssocStmt) {
+ assert(Construct && AssocStmt && "Invalid construct or statement");
+ switch (Construct->getDirectiveKind()) {
+ case OpenACCDirectiveKind::Parallel:
+ // There really isn't any checking here that could happen. As long as we
+ // have a statement to associate, this should be fine.
+ // OpenACC 3.3 Section 6:
+ // Structured Block: in C or C++, an executable statement, possibly
+ // compound, with a single entry at the top and a single exit at the
+ // bottom.
+ // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
+ // an interpretation of it is to allow this and treat the initializer as
+ // the 'structured block'.
+ Context.setOpenACCStructuredBlock(cast<OpenACCComputeConstruct>(Construct),
+ AssocStmt);
+ break;
+ default:
+ llvm_unreachable("Unimplemented associated statement application");
+ }
+ // TODO: ERICH: Implement.
+ return Construct;
+}
+
+void Sema::ActOnEndOpenACCStmtDirective(StmtResult Stmt) {
+ // TODO OpenACC: Should diagnose anything having to do with the associated
+ // statement, or any clause diagnostics that can only be done at the 'end' of
+ // the directive. We should also close any 'block' marking now that the
+ // statement parsing is complete.
+}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 6e5ae123a6ba2c..f27fa8d171b173 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4000,7 +4000,21 @@ class TreeTransform {
SourceLocation BeginLoc,
SourceLocation EndLoc,
StmtResult StrBlock) {
- llvm_unreachable("Not yet implemented!");
+ getSema().ActOnOpenACCConstruct(K, BeginLoc);
+ // TODO OpenACC: Include clauses.
+ StmtResult Construct =
+ getSema().ActOnStartOpenACCStmtDirective(K, BeginLoc, EndLoc);
+
+ if (!Construct.isUsable())
+ return Construct;
+
+ if (StrBlock.isUsable()) {
+ Construct = getSema().ActOnOpenACCAssociatedStmt(
+ cast<OpenACCComputeConstruct>(Construct.get()), StrBlock.get());
+ }
+
+ getSema().ActOnEndOpenACCStmtDirective(Construct);
+ return Construct;
}
private:
diff --git a/clang/test/ParserOpenACC/parse-cache-construct.c b/clang/test/ParserOpenACC/parse-cache-construct.c
index 093587f37df4fc..fd161c03c09f75 100644
--- a/clang/test/ParserOpenACC/parse-cache-construct.c
+++ b/clang/test/ParserOpenACC/parse-cache-construct.c
@@ -13,32 +13,32 @@ void func() {
for (int i = 0; i < 10; ++i) {
// expected-error at +2{{expected '('}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache
}
for (int i = 0; i < 10; ++i) {
// expected-error at +3{{expected '('}}
// expected-error at +2{{invalid OpenACC clause 'clause'}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache clause list
}
for (int i = 0; i < 10; ++i) {
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache()
}
for (int i = 0; i < 10; ++i) {
// expected-error at +2{{invalid OpenACC clause 'clause'}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache() clause-list
}
for (int i = 0; i < 10; ++i) {
// expected-error at +3{{expected ')'}}
// expected-note at +2{{to match this '('}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache(
}
@@ -46,25 +46,25 @@ void func() {
// expected-error at +4{{use of undeclared identifier 'invalid'}}
// expected-error at +3{{expected ')'}}
// expected-note at +2{{to match this '('}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache(invalid
}
for (int i = 0; i < 10; ++i) {
// expected-error at +3{{expected ')'}}
// expected-note at +2{{to match this '('}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache(ArrayPtr
}
for (int i = 0; i < 10; ++i) {
// expected-error at +2{{use of undeclared identifier 'invalid'}}
- // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ // expected-warning at +1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
#pragma acc cache(invalid)
}
for (int i = 0; i < 10; ++i) {
- // expected-warning at +1{{Ope...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/81659
More information about the cfe-commits
mailing list