diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index da18cf88edcc9..69b9e837fe8be 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 978949a9803ac..53f06bcaeca16 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -41,6 +41,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" @@ -12701,6 +12702,46 @@ 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. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'statement' context. + bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'Decl' context. + bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc); + /// Called when we encounter an associated statement for our construct, this + /// should check legality of the statement as it appertains to this Construct. + StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, + StmtResult AssocStmt); + + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc, + SourceLocation EndLoc, + StmtResult AssocStmt); + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + DeclGroupRef ActOnEndOpenACCDeclDirective(); + /// The kind of conversion being performed. enum CheckedConversionKind { /// An implicit conversion. diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index e099d077198d0..8157656246873 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -550,6 +550,11 @@ void SkipUntilEndOfDirective(Parser &P) { P.ConsumeAnyToken(); } +bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) { + // TODO OpenACC: Implement. + return false; +} + } // namespace // OpenACC 3.3, section 1.7: @@ -745,9 +750,11 @@ bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) { << getCurToken().getIdentifierInfo(); // Consume the clause name. - ConsumeToken(); + SourceLocation ClauseLoc = ConsumeToken(); - return ParseOpenACCClauseParams(DirKind, Kind); + bool Result = ParseOpenACCClauseParams(DirKind, Kind); + getActions().ActOnOpenACCClause(Kind, ClauseLoc); + return Result; } bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind, @@ -1116,9 +1123,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. @@ -1175,7 +1185,10 @@ void Parser::ParseOpenACCDirective() { 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,9 +1198,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { ParsingOpenACCDirectiveRAII DirScope(*this); ConsumeAnnotationToken(); - ParseOpenACCDirective(); + OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); + + if (getActions().ActOnStartOpenACCDeclDirective(DirInfo.DirKind, + DirInfo.StartLoc)) + return nullptr; - return nullptr; + // TODO OpenACC: Do whatever decl parsing is required here. + return DeclGroupPtrTy::make(getActions().ActOnEndOpenACCDeclDirective()); } // Parse OpenACC Directive on a Statement. @@ -1197,7 +1215,19 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { ParsingOpenACCDirectiveRAII DirScope(*this); ConsumeAnnotationToken(); - ParseOpenACCDirective(); + OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); + if (getActions().ActOnStartOpenACCDeclDirective(DirInfo.DirKind, + DirInfo.StartLoc)) + return StmtError(); + + StmtResult AssocStmt; + + if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) { + ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); + AssocStmt = getActions().ActOnOpenACCAssociatedStmt(DirInfo.DirKind, + ParseStatement()); + } - return StmtEmpty(); + return getActions().ActOnEndOpenACCStmtDirective( + DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, AssocStmt); } diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 1856a88e9a327..862f9d4ffb825 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 0000000000000..dc53084543390 --- /dev/null +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -0,0 +1,47 @@ +//===--- 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/OpenACCKinds.h" +#include "clang/Sema/Sema.h" + +using namespace clang; +bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, + SourceLocation StartLoc) { + return true; +} +void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, + SourceLocation StartLoc) {} + +bool Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc) { + return true; +} + +StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc, + SourceLocation EndLoc, + StmtResult AssocStmt) { + return StmtEmpty(); +} + +StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, + StmtResult AssocStmt) { + return AssocStmt; +} + +bool Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc) { + return true; +} + +DeclGroupRef Sema::ActOnEndOpenACCDeclDirective() { return DeclGroupRef{}; }