blob: d3a602d1c382fa601b7eda1c369402a20bc0fc72 [file] [log] [blame] [edit]
//===--- 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{}; }