| //===--- 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: |
| case OpenACCDirectiveKind::Serial: |
| case OpenACCDirectiveKind::Kernels: |
| if (!IsStmt) |
| return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K; |
| break; |
| } |
| return false; |
| } |
| } // namespace |
| |
| bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, |
| SourceLocation StartLoc) { |
| 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: |
| case OpenACCDirectiveKind::Serial: |
| case OpenACCDirectiveKind::Kernels: |
| // 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; |
| } |
| } |
| |
| bool Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, |
| SourceLocation StartLoc) { |
| return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); |
| } |
| |
| StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, |
| SourceLocation StartLoc, |
| SourceLocation EndLoc, |
| StmtResult AssocStmt) { |
| switch (K) { |
| default: |
| return StmtEmpty(); |
| case OpenACCDirectiveKind::Invalid: |
| return StmtError(); |
| case OpenACCDirectiveKind::Parallel: |
| case OpenACCDirectiveKind::Serial: |
| case OpenACCDirectiveKind::Kernels: |
| return OpenACCComputeConstruct::Create( |
| getASTContext(), K, StartLoc, EndLoc, |
| AssocStmt.isUsable() ? AssocStmt.get() : nullptr); |
| } |
| llvm_unreachable("Unhandled case in directive handling?"); |
| } |
| |
| StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, |
| StmtResult AssocStmt) { |
| switch (K) { |
| default: |
| llvm_unreachable("Unimplemented associated statement application"); |
| case OpenACCDirectiveKind::Parallel: |
| case OpenACCDirectiveKind::Serial: |
| case OpenACCDirectiveKind::Kernels: |
| // 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'. |
| return AssocStmt; |
| } |
| llvm_unreachable("Invalid associated statement application"); |
| } |
| |
| bool Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, |
| SourceLocation StartLoc) { |
| return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false); |
| } |
| |
| DeclGroupRef Sema::ActOnEndOpenACCDeclDirective() { return DeclGroupRef{}; } |