summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJennifer Yu <jennifer.yu@intel.com>2022-01-10 16:20:02 -0800
committerJennifer Yu <jennifer.yu@intel.com>2022-01-10 16:58:56 -0800
commit140a6b1e5c6857617a83f66680b4829ff2b08d82 (patch)
tree40bb6e5cec41591b9e94af7795dfd7245791a70d
parent4258d68dc73789bc7fc491734c9c392809b1b29a (diff)
downloadllvm-140a6b1e5c6857617a83f66680b4829ff2b08d82.tar.gz
[clang][OpenMP5.1] Initial parsing/sema for 'indirect' clause
Differential Revision: https://reviews.llvm.org/D116764
-rw-r--r--clang/include/clang/Basic/Attr.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td6
-rw-r--r--clang/include/clang/Parse/Parser.h5
-rw-r--r--clang/include/clang/Sema/Sema.h5
-rw-r--r--clang/lib/AST/AttrImpl.cpp7
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp1
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp91
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp36
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp6
-rw-r--r--clang/test/OpenMP/declare_target_ast_print.cpp45
-rw-r--r--clang/test/OpenMP/declare_target_messages.cpp47
-rw-r--r--flang/lib/Semantics/check-omp-structure.cpp1
-rw-r--r--llvm/include/llvm/Frontend/OpenMP/OMP.td5
13 files changed, 218 insertions, 39 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 10c5c7f1b879..b071ebb4d576 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3686,6 +3686,8 @@ def OMPDeclareTargetDecl : InheritableAttr {
EnumArgument<"DevType", "DevTypeTy",
[ "host", "nohost", "any" ],
[ "DT_Host", "DT_NoHost", "DT_Any" ]>,
+ ExprArgument<"IndirectExpr">,
+ BoolArgument<"Indirect">,
UnsignedArgument<"Level">
];
let AdditionalMembers = [{
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9dc036c03faa..193dff8b9c8f 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1344,15 +1344,17 @@ def warn_omp_unknown_assumption_clause_without_args
def note_omp_assumption_clause_continue_here
: Note<"the ignored tokens spans until here">;
def err_omp_declare_target_unexpected_clause: Error<
- "unexpected '%0' clause, only %select{'device_type'|'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">;
+ "unexpected '%0' clause, only %select{'device_type'|'to' or 'link'|'to', 'link' or 'device_type'|'device_type', 'indirect'|'to', 'link', 'device_type' or 'indirect'}1 clauses expected">;
def err_omp_begin_declare_target_unexpected_implicit_to_clause: Error<
"unexpected '(', only 'to', 'link' or 'device_type' clauses expected for 'begin declare target' directive">;
def err_omp_declare_target_unexpected_clause_after_implicit_to: Error<
"unexpected clause after an implicit 'to' clause">;
def err_omp_declare_target_missing_to_or_link_clause: Error<
- "expected at least one 'to' or 'link' clause">;
+ "expected at least one %select{'to' or 'link'|'to', 'link' or 'indirect'}0 clause">;
def err_omp_declare_target_multiple : Error<
"%0 appears multiple times in clauses on the same declare target directive">;
+def err_omp_declare_target_indirect_device_type: Error<
+ "only 'device_type(any)' clause is allowed with indirect clause">;
def err_omp_expected_clause: Error<
"expected at least one clause on '#pragma omp %0' directive">;
def err_omp_mapper_illegal_identifier : Error<
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index a98ad78401f0..74935c890017 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3316,6 +3316,11 @@ private:
/// nullptr.
///
OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly);
+ /// Parses indirect clause
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ // false;
+ bool ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
+ bool ParseOnly);
/// Parses clause with a single expression and an additional argument
/// of a kind \a Kind.
///
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9b6d9d20ca43..f1e90356c836 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10333,6 +10333,9 @@ private:
/// The directive kind, `begin declare target` or `declare target`.
OpenMPDirectiveKind Kind;
+ /// The directive with indirect clause.
+ Optional<Expr *> Indirect;
+
/// The directive location.
SourceLocation Loc;
@@ -10639,7 +10642,7 @@ public:
/// Called on correct id-expression from the '#pragma omp declare target'.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
OMPDeclareTargetDeclAttr::MapTypeTy MT,
- OMPDeclareTargetDeclAttr::DevTypeTy DT);
+ DeclareTargetContextInfo &DTCI);
/// Check declaration inside target region.
void
diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp
index c2f13cf63830..7b8acfcd92be 100644
--- a/clang/lib/AST/AttrImpl.cpp
+++ b/clang/lib/AST/AttrImpl.cpp
@@ -139,6 +139,13 @@ void OMPDeclareTargetDeclAttr::printPrettyPragma(
OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
if (getMapType() != MT_To)
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
+ if (Expr *E = getIndirectExpr()) {
+ OS << " indirect(";
+ E->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ } else if (getIndirect()) {
+ OS << " indirect";
+ }
}
llvm::Optional<OMPDeclareTargetDeclAttr *>
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index b340e0505a78..11af2812a411 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -6049,6 +6049,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_inbranch:
case OMPC_notinbranch:
case OMPC_link:
+ case OMPC_indirect:
case OMPC_use:
case OMPC_novariants:
case OMPC_nocontext:
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 0264d385610a..0089da741b59 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1814,38 +1814,55 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
void Parser::ParseOMPDeclareTargetClauses(
Sema::DeclareTargetContextInfo &DTCI) {
SourceLocation DeviceTypeLoc;
- bool RequiresToOrLinkClause = false;
- bool HasToOrLinkClause = false;
+ bool RequiresToOrLinkOrIndirectClause = false;
+ bool HasToOrLinkOrIndirectClause = false;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
bool HasIdentifier = Tok.is(tok::identifier);
if (HasIdentifier) {
// If we see any clause we need a to or link clause.
- RequiresToOrLinkClause = true;
+ RequiresToOrLinkOrIndirectClause = true;
IdentifierInfo *II = Tok.getIdentifierInfo();
StringRef ClauseName = II->getName();
bool IsDeviceTypeClause =
getLangOpts().OpenMP >= 50 &&
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
+ bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
+ getOpenMPClauseKind(ClauseName) == OMPC_indirect;
+ if (DTCI.Indirect.hasValue() && IsIndirectClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(OMPD_declare_target)
+ << getOpenMPClauseName(OMPC_indirect) << 0;
+ break;
+ }
bool IsToOrLinkClause =
OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
- if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) {
+ if (!IsDeviceTypeClause && !IsIndirectClause &&
+ DTCI.Kind == OMPD_begin_declare_target) {
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << 0;
+ << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
break;
}
- if (!IsDeviceTypeClause && !IsToOrLinkClause) {
+ if (!IsDeviceTypeClause && !IsToOrLinkClause && !IsIndirectClause) {
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1);
+ << ClauseName
+ << (getLangOpts().OpenMP >= 51 ? 4
+ : getLangOpts().OpenMP >= 50 ? 2
+ : 1);
break;
}
- if (IsToOrLinkClause)
- HasToOrLinkClause = true;
+ if (IsToOrLinkClause || IsIndirectClause)
+ HasToOrLinkOrIndirectClause = true;
+ if (IsIndirectClause) {
+ if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
+ break;
+ continue;
+ }
// Parse 'device_type' clause and go to next clause if any.
if (IsDeviceTypeClause) {
Optional<SimpleClauseData> DevTypeData =
@@ -1911,10 +1928,14 @@ void Parser::ParseOMPDeclareTargetClauses(
ConsumeToken();
}
+ if (DTCI.Indirect.hasValue() && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
+ Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
+
// For declare target require at least 'to' or 'link' to be present.
- if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkClause &&
- !HasToOrLinkClause)
- Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause);
+ if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
+ !HasToOrLinkOrIndirectClause)
+ Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause)
+ << (getLangOpts().OpenMP >= 51 ? 1 : 0);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
@@ -2283,11 +2304,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
- bool HasImplicitMappings =
- DKind == OMPD_begin_declare_target || !HasClauses;
Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
if (HasClauses)
ParseOMPDeclareTargetClauses(DTCI);
+ bool HasImplicitMappings =
+ DKind == OMPD_begin_declare_target || !HasClauses ||
+ (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect.hasValue());
// Skip the last annot_pragma_openmp_end.
ConsumeAnyToken();
@@ -3384,6 +3406,47 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
}
+/// Parse indirect clause for '#pragma omp declare target' directive.
+/// 'indirect' '[' '(' invoked-by-fptr ')' ']'
+/// where invoked-by-fptr is a constant boolean expression that evaluates to
+/// true or false at compile time.
+bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
+ bool ParseOnly) {
+ SourceLocation Loc = ConsumeToken();
+ SourceLocation RLoc;
+
+ if (Tok.isNot(tok::l_paren)) {
+ if (ParseOnly)
+ return false;
+ DTCI.Indirect = nullptr;
+ return true;
+ }
+
+ ExprResult Val =
+ ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
+ if (Val.isInvalid())
+ return false;
+
+ if (ParseOnly)
+ return false;
+
+ if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
+ !Val.get()->isInstantiationDependent() &&
+ !Val.get()->containsUnexpandedParameterPack()) {
+ ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
+ if (Ret.isInvalid())
+ return false;
+ llvm::APSInt Result;
+ Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
+ Sema::AllowFold);
+ if (Ret.isInvalid())
+ return false;
+ DTCI.Indirect = Val.get();
+ return true;
+ }
+ return false;
+}
+
/// Parsing of OpenMP clauses that use an interop-var.
///
/// init-clause:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index b97d9d90f6ca..20b090faaf4c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -20762,8 +20762,7 @@ Sema::ActOnOpenMPEndDeclareTargetDirective() {
void Sema::ActOnFinishedOpenMPDeclareTargetContext(
DeclareTargetContextInfo &DTCI) {
for (auto &It : DTCI.ExplicitlyMapped)
- ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT,
- DTCI.DT);
+ ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
}
NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
@@ -20800,9 +20799,9 @@ NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
return ND;
}
-void Sema::ActOnOpenMPDeclareTargetName(
- NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
- OMPDeclareTargetDeclAttr::DevTypeTy DT) {
+void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
+ OMPDeclareTargetDeclAttr::MapTypeTy MT,
+ DeclareTargetContextInfo &DTCI) {
assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
isa<FunctionTemplateDecl>(ND)) &&
"Expected variable, function or function template.");
@@ -20819,10 +20818,10 @@ void Sema::ActOnOpenMPDeclareTargetName(
auto *VD = cast<ValueDecl>(ND);
llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
OMPDeclareTargetDeclAttr::getActiveAttr(VD);
- if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getDevType() != DT &&
+ if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getDevType() != DTCI.DT &&
ActiveAttr.getValue()->getLevel() == Level) {
Diag(Loc, diag::err_omp_device_type_mismatch)
- << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT)
+ << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
ActiveAttr.getValue()->getDevType());
return;
@@ -20836,8 +20835,16 @@ void Sema::ActOnOpenMPDeclareTargetName(
if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() == Level)
return;
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, Level,
- SourceRange(Loc, Loc));
+ Expr *IndirectE = nullptr;
+ bool IsIndirect = false;
+ if (DTCI.Indirect.hasValue()) {
+ IndirectE = DTCI.Indirect.getValue();
+ if (!IndirectE)
+ IsIndirect = true;
+ }
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+ Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
+ SourceRange(Loc, Loc));
ND->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
@@ -20928,9 +20935,16 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() >= Level)
return;
DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
+ Expr *IndirectE = nullptr;
+ bool IsIndirect = false;
+ if (DTCI.Indirect.hasValue()) {
+ IndirectE = DTCI.Indirect.getValue();
+ if (!IndirectE)
+ IsIndirect = true;
+ }
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, Level,
- SourceRange(DTCI.Loc, DTCI.Loc));
+ Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, IndirectE,
+ IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc));
D->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 2144befcdb14..310bbc0f3cbb 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -4781,10 +4781,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
case UPD_DECL_MARKED_OPENMP_DECLARETARGET: {
auto MapType = Record.readEnum<OMPDeclareTargetDeclAttr::MapTypeTy>();
auto DevType = Record.readEnum<OMPDeclareTargetDeclAttr::DevTypeTy>();
+ Expr *IndirectE = Record.readExpr();
+ bool Indirect = Record.readBool();
unsigned Level = Record.readInt();
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
- Reader.getContext(), MapType, DevType, Level, readSourceRange(),
- AttributeCommonInfo::AS_Pragma));
+ Reader.getContext(), MapType, DevType, IndirectE, Indirect, Level,
+ readSourceRange(), AttributeCommonInfo::AS_Pragma));
break;
}
diff --git a/clang/test/OpenMP/declare_target_ast_print.cpp b/clang/test/OpenMP/declare_target_ast_print.cpp
index dbd0b923a7d6..2dd45bbc7948 100644
--- a/clang/test/OpenMP/declare_target_ast_print.cpp
+++ b/clang/test/OpenMP/declare_target_ast_print.cpp
@@ -3,8 +3,11 @@
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP51
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP51
// RUN: %clang_cc1 -verify -fopenmp-simd -I %S/Inputs -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
@@ -32,6 +35,48 @@ void bazz();
// OMP50: #pragma omp end declare target{{$}}
#endif // _OPENMP
+#if _OPENMP == 202011
+extern "C" {
+void boo_c() {}
+#pragma omp declare target to(boo_c) indirect
+// OMP51: #pragma omp declare target indirect
+// OMP51: void boo_c() {
+// OMP51: }
+// OMP51: #pragma omp end declare target
+#pragma omp declare target indirect
+void yoo(){}
+#pragma omp end declare target
+// OMP51: #pragma omp declare target indirect
+// OMP51: void yoo() {
+// OMP51: }
+// OMP51: #pragma omp end declare target
+}
+extern "C++" {
+void boo_cpp() {}
+#pragma omp declare target to(boo_cpp) indirect
+// OMP51: #pragma omp declare target indirect
+// OMP51: void boo_cpp() {
+// OMP51: }
+// OMP51: #pragma omp end declare target
+
+constexpr bool f() {return false;}
+#pragma omp begin declare target indirect(f())
+void zoo() {}
+void xoo();
+#pragma omp end declare target
+#pragma omp declare target to(zoo) indirect(false)
+// OMP51: #pragma omp declare target indirect(f())
+// OMP51: #pragma omp declare target indirect(false)
+// OMP51: void zoo() {
+// OMP51: }
+// OMP51: #pragma omp end declare target
+// OMP51: #pragma omp declare target indirect(f())
+// OMP51: void xoo();
+// OMP51: #pragma omp end declare target
+
+}
+#endif // _OPENMP
+
int out_decl_target = 0;
#pragma omp declare target (out_decl_target)
diff --git a/clang/test/OpenMP/declare_target_messages.cpp b/clang/test/OpenMP/declare_target_messages.cpp
index 1f608e927421..31185881e192 100644
--- a/clang/test/OpenMP/declare_target_messages.cpp
+++ b/clang/test/OpenMP/declare_target_messages.cpp
@@ -5,11 +5,13 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp5,host5 -fopenmp-simd -fopenmp-targets=x86_64-apple-macos10.7.0 -fnoopenmp-use-tls -ferror-limit 100 -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp5,host5 -fopenmp-simd -fopenmp-is-device -fopenmp-targets=x86_64-apple-macos10.7.0 -fnoopenmp-use-tls -ferror-limit 100 -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd -fnoopenmp-use-tls -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp51 -fopenmp -fopenmp-version=51 -fnoopenmp-use-tls -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp51 -fopenmp-version=51 -fopenmp-simd -fnoopenmp-use-tls -ferror-limit 100 -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp5 -fopenmp -fnoopenmp-use-tls -ferror-limit 100 -o - %s
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
-int a, b, z; // omp5-error {{variable captured in declare target region must appear in a to clause}}
+int a, b, z; // omp5-error {{variable captured in declare target region must appear in a to clause}} // omp51-error {{variable captured in declare target region must appear in a to clause}}
__thread int t; // expected-note {{defined as threadprivate or thread local}}
#pragma omp declare target . // expected-error {{expected '(' after 'declare target'}}
@@ -18,7 +20,7 @@ __thread int t; // expected-note {{defined as threadprivate or thread local}}
void f();
#pragma omp end declare target shared(a) // expected-warning {{extra tokens at the end of '#pragma omp end declare target' are ignored}}
-#pragma omp declare target map(a) // expected-error {{expected at least one 'to' or 'link' clause}} omp45-error {{unexpected 'map' clause, only 'to' or 'link' clauses expected}} omp5-error {{unexpected 'map' clause, only 'to', 'link' or 'device_type' clauses expected}}
+#pragma omp declare target map(a) // omp45-error {{expected at least one 'to' or 'link' clause}} omp5-error {{expected at least one 'to' or 'link' clause}} omp51-error {{expected at least one 'to', 'link' or 'indirect' clause}} omp45-error {{unexpected 'map' clause, only 'to' or 'link' clauses expected}} omp5-error {{unexpected 'map' clause, only 'to', 'link' or 'device_type' clauses expected}} omp51-error {{unexpected 'map' clause, only 'to', 'link', 'device_type' or 'indirect' clauses expected}}
#pragma omp declare target to(foo1) // expected-error {{use of undeclared identifier 'foo1'}}
@@ -27,17 +29,46 @@ void f();
#pragma omp declare target to(f) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} dev5-note {{marked as 'device_type(host)' here}}
void q();
-#pragma omp declare target to(q) device_type(any) device_type(any) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-warning {{more than one 'device_type' clause is specified}}
+#pragma omp declare target to(q) device_type(any) device_type(any) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-warning {{more than one 'device_type' clause is specified}} // omp51-warning {{more than one 'device_type' clause is specified}}
+
+#if _OPENMP == 202011
+// omp51-error@+1 {{directive '#pragma omp declare target' cannot contain more than one 'indirect' clause}}
+#pragma omp declare target to(q) indirect(true) indirect(false)
+
+int xxx; //expected-note {{declared here}}
+// omp51-error@+2 {{expression is not an integral constant expression}}
+// omp51-note@+1 {{read of non-const variable 'xxx' is not allowed in a constant expression}}
+#pragma omp declare target to(q) indirect(xxx)
+
+constexpr bool fz() {return true;}
+// omp51-error@+1 {{unexpected 'to' clause, only 'device_type', 'indirect' clauses expected}}
+#pragma omp begin declare target to(q) indirect(fz()) device_type(nohost)
+#pragma omp end declare target
+
+// omp51-error@+1 {{unexpected 'to' clause, only 'device_type', 'indirect' clauses expected}}
+#pragma omp begin declare target indirect to(xxx)
+void bar();
+#pragma omp end declare target
+
+// omp51-error@+2 {{unexpected 'tofrom' clause, only 'to', 'link', 'device_type' or 'indirect' clauses expected}}
+// omp51-error@+1 {{expected at least one 'to', 'link' or 'indirect' clause}}
+#pragma omp declare target tofrom(xxx)
+
+// omp51-error@+1 {{only 'device_type(any)' clause is allowed with indirect clause}}
+#pragma omp begin declare target device_type(host) indirect
+void bar();
+#pragma omp end declare target
+#endif // _OPENMP
void c();
void func() {} // expected-note {{'func' defined here}}
-#pragma omp declare target link(func) allocate(a) // expected-error {{function name is not allowed in 'link' clause}} omp45-error {{unexpected 'allocate' clause, only 'to' or 'link' clauses expected}} omp5-error {{unexpected 'allocate' clause, only 'to', 'link' or 'device_type' clauses expected}}
+#pragma omp declare target link(func) allocate(a) // expected-error {{function name is not allowed in 'link' clause}} omp45-error {{unexpected 'allocate' clause, only 'to' or 'link' clauses expected}} omp5-error {{unexpected 'allocate' clause, only 'to', 'link' or 'device_type' clauses expected}} omp51-error {{unexpected 'allocate' clause, only 'to', 'link', 'device_type' or 'indirect' clauses expected}}
void bar();
void baz() {bar();}
-#pragma omp declare target(bar) // omp5-warning {{declaration marked as declare target after first use, it may lead to incorrect results}}
+#pragma omp declare target(bar) // omp5-warning {{declaration marked as declare target after first use, it may lead to incorrect results}} // omp51-warning {{declaration marked as declare target after first use, it may lead to incorrect results}}
extern int b;
@@ -128,7 +159,7 @@ void foo(int p) {
}
#pragma omp declare target
void foo1() {
- [&](){ (void)(b+z);}(); // omp5-note {{variable 'z' is captured here}}
+ [&](){ (void)(b+z);}(); // omp5-note {{variable 'z' is captured here}} //omp51-note {{variable 'z' is captured here}}
}
#pragma omp end declare target
@@ -194,8 +225,8 @@ void any8() {any2();}
int MultiDevTy;
#pragma omp declare target to(MultiDevTy) device_type(any) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}}
-#pragma omp declare target to(MultiDevTy) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}}
-#pragma omp declare target to(MultiDevTy) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}}
+#pragma omp declare target to(MultiDevTy) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}} omp51-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}}
+#pragma omp declare target to(MultiDevTy) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}} // omp51-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}}
// TODO: Issue an error message error {{expected '#pragma omp end declare target'}} note {{to match this '#pragma omp declare target'}}
#pragma omp declare target
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index db7dd2e9670f..df66a42dede5 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1528,6 +1528,7 @@ CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads)
CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch)
CHECK_SIMPLE_CLAUSE(IsDevicePtr, OMPC_is_device_ptr)
CHECK_SIMPLE_CLAUSE(Link, OMPC_link)
+CHECK_SIMPLE_CLAUSE(Indirect, OMPC_indirect)
CHECK_SIMPLE_CLAUSE(Mergeable, OMPC_mergeable)
CHECK_SIMPLE_CLAUSE(Nogroup, OMPC_nogroup)
CHECK_SIMPLE_CLAUSE(Notinbranch, OMPC_notinbranch)
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 18d577dff497..c5abb16dd9e5 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -358,6 +358,7 @@ def OMPC_Unknown : Clause<"unknown"> {
def OMPC_Link : Clause<"link"> {
let flangClass = "OmpObjectList";
}
+def OMPC_Indirect : Clause<"indirect"> {}
def OMPC_Inbranch : Clause<"inbranch"> {}
def OMPC_Notinbranch : Clause<"notinbranch"> {}
def OMPC_Filter : Clause<"filter"> {
@@ -973,12 +974,14 @@ def OMP_BeginDeclareTarget : Directive<"begin declare target"> {
VersionedClause<OMPC_To>,
VersionedClause<OMPC_Link>,
VersionedClause<OMPC_DeviceType>,
+ VersionedClause<OMPC_Indirect>
];
}
def OMP_DeclareTarget : Directive<"declare target"> {
let allowedClauses = [
VersionedClause<OMPC_To>,
- VersionedClause<OMPC_Link>
+ VersionedClause<OMPC_Link>,
+ VersionedClause<OMPC_Indirect>
];
}
def OMP_EndDeclareTarget : Directive<"end declare target"> {}