Skip to content

Commit 140a6b1

Browse files
committed
[clang][OpenMP5.1] Initial parsing/sema for 'indirect' clause
Differential Revision: https://reviews.llvm.org/D116764
1 parent 4258d68 commit 140a6b1

File tree

13 files changed

+218
-39
lines changed

13 files changed

+218
-39
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,6 +3686,8 @@ def OMPDeclareTargetDecl : InheritableAttr {
36863686
EnumArgument<"DevType", "DevTypeTy",
36873687
[ "host", "nohost", "any" ],
36883688
[ "DT_Host", "DT_NoHost", "DT_Any" ]>,
3689+
ExprArgument<"IndirectExpr">,
3690+
BoolArgument<"Indirect">,
36893691
UnsignedArgument<"Level">
36903692
];
36913693
let AdditionalMembers = [{

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,15 +1344,17 @@ def warn_omp_unknown_assumption_clause_without_args
13441344
def note_omp_assumption_clause_continue_here
13451345
: Note<"the ignored tokens spans until here">;
13461346
def err_omp_declare_target_unexpected_clause: Error<
1347-
"unexpected '%0' clause, only %select{'device_type'|'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">;
1347+
"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">;
13481348
def err_omp_begin_declare_target_unexpected_implicit_to_clause: Error<
13491349
"unexpected '(', only 'to', 'link' or 'device_type' clauses expected for 'begin declare target' directive">;
13501350
def err_omp_declare_target_unexpected_clause_after_implicit_to: Error<
13511351
"unexpected clause after an implicit 'to' clause">;
13521352
def err_omp_declare_target_missing_to_or_link_clause: Error<
1353-
"expected at least one 'to' or 'link' clause">;
1353+
"expected at least one %select{'to' or 'link'|'to', 'link' or 'indirect'}0 clause">;
13541354
def err_omp_declare_target_multiple : Error<
13551355
"%0 appears multiple times in clauses on the same declare target directive">;
1356+
def err_omp_declare_target_indirect_device_type: Error<
1357+
"only 'device_type(any)' clause is allowed with indirect clause">;
13561358
def err_omp_expected_clause: Error<
13571359
"expected at least one clause on '#pragma omp %0' directive">;
13581360
def err_omp_mapper_illegal_identifier : Error<

clang/include/clang/Parse/Parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,6 +3316,11 @@ class Parser : public CodeCompletionHandler {
33163316
/// nullptr.
33173317
///
33183318
OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly);
3319+
/// Parses indirect clause
3320+
/// \param ParseOnly true to skip the clause's semantic actions and return
3321+
// false;
3322+
bool ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
3323+
bool ParseOnly);
33193324
/// Parses clause with a single expression and an additional argument
33203325
/// of a kind \a Kind.
33213326
///

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10333,6 +10333,9 @@ class Sema final {
1033310333
/// The directive kind, `begin declare target` or `declare target`.
1033410334
OpenMPDirectiveKind Kind;
1033510335

10336+
/// The directive with indirect clause.
10337+
Optional<Expr *> Indirect;
10338+
1033610339
/// The directive location.
1033710340
SourceLocation Loc;
1033810341

@@ -10639,7 +10642,7 @@ class Sema final {
1063910642
/// Called on correct id-expression from the '#pragma omp declare target'.
1064010643
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
1064110644
OMPDeclareTargetDeclAttr::MapTypeTy MT,
10642-
OMPDeclareTargetDeclAttr::DevTypeTy DT);
10645+
DeclareTargetContextInfo &DTCI);
1064310646

1064410647
/// Check declaration inside target region.
1064510648
void

clang/lib/AST/AttrImpl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ void OMPDeclareTargetDeclAttr::printPrettyPragma(
139139
OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
140140
if (getMapType() != MT_To)
141141
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
142+
if (Expr *E = getIndirectExpr()) {
143+
OS << " indirect(";
144+
E->printPretty(OS, nullptr, Policy);
145+
OS << ")";
146+
} else if (getIndirect()) {
147+
OS << " indirect";
148+
}
142149
}
143150

144151
llvm::Optional<OMPDeclareTargetDeclAttr *>

clang/lib/CodeGen/CGStmtOpenMP.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6049,6 +6049,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
60496049
case OMPC_inbranch:
60506050
case OMPC_notinbranch:
60516051
case OMPC_link:
6052+
case OMPC_indirect:
60526053
case OMPC_use:
60536054
case OMPC_novariants:
60546055
case OMPC_nocontext:

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,38 +1814,55 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
18141814
void Parser::ParseOMPDeclareTargetClauses(
18151815
Sema::DeclareTargetContextInfo &DTCI) {
18161816
SourceLocation DeviceTypeLoc;
1817-
bool RequiresToOrLinkClause = false;
1818-
bool HasToOrLinkClause = false;
1817+
bool RequiresToOrLinkOrIndirectClause = false;
1818+
bool HasToOrLinkOrIndirectClause = false;
18191819
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
18201820
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
18211821
bool HasIdentifier = Tok.is(tok::identifier);
18221822
if (HasIdentifier) {
18231823
// If we see any clause we need a to or link clause.
1824-
RequiresToOrLinkClause = true;
1824+
RequiresToOrLinkOrIndirectClause = true;
18251825
IdentifierInfo *II = Tok.getIdentifierInfo();
18261826
StringRef ClauseName = II->getName();
18271827
bool IsDeviceTypeClause =
18281828
getLangOpts().OpenMP >= 50 &&
18291829
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
18301830

1831+
bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1832+
getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1833+
if (DTCI.Indirect.hasValue() && IsIndirectClause) {
1834+
Diag(Tok, diag::err_omp_more_one_clause)
1835+
<< getOpenMPDirectiveName(OMPD_declare_target)
1836+
<< getOpenMPClauseName(OMPC_indirect) << 0;
1837+
break;
1838+
}
18311839
bool IsToOrLinkClause =
18321840
OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
18331841
assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
18341842

1835-
if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) {
1843+
if (!IsDeviceTypeClause && !IsIndirectClause &&
1844+
DTCI.Kind == OMPD_begin_declare_target) {
18361845
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1837-
<< ClauseName << 0;
1846+
<< ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
18381847
break;
18391848
}
1840-
if (!IsDeviceTypeClause && !IsToOrLinkClause) {
1849+
if (!IsDeviceTypeClause && !IsToOrLinkClause && !IsIndirectClause) {
18411850
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1842-
<< ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1);
1851+
<< ClauseName
1852+
<< (getLangOpts().OpenMP >= 51 ? 4
1853+
: getLangOpts().OpenMP >= 50 ? 2
1854+
: 1);
18431855
break;
18441856
}
18451857

1846-
if (IsToOrLinkClause)
1847-
HasToOrLinkClause = true;
1858+
if (IsToOrLinkClause || IsIndirectClause)
1859+
HasToOrLinkOrIndirectClause = true;
18481860

1861+
if (IsIndirectClause) {
1862+
if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1863+
break;
1864+
continue;
1865+
}
18491866
// Parse 'device_type' clause and go to next clause if any.
18501867
if (IsDeviceTypeClause) {
18511868
Optional<SimpleClauseData> DevTypeData =
@@ -1911,10 +1928,14 @@ void Parser::ParseOMPDeclareTargetClauses(
19111928
ConsumeToken();
19121929
}
19131930

1931+
if (DTCI.Indirect.hasValue() && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1932+
Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1933+
19141934
// For declare target require at least 'to' or 'link' to be present.
1915-
if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkClause &&
1916-
!HasToOrLinkClause)
1917-
Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause);
1935+
if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
1936+
!HasToOrLinkOrIndirectClause)
1937+
Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause)
1938+
<< (getLangOpts().OpenMP >= 51 ? 1 : 0);
19181939

19191940
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
19201941
}
@@ -2283,11 +2304,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
22832304
case OMPD_declare_target: {
22842305
SourceLocation DTLoc = ConsumeAnyToken();
22852306
bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2286-
bool HasImplicitMappings =
2287-
DKind == OMPD_begin_declare_target || !HasClauses;
22882307
Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
22892308
if (HasClauses)
22902309
ParseOMPDeclareTargetClauses(DTCI);
2310+
bool HasImplicitMappings =
2311+
DKind == OMPD_begin_declare_target || !HasClauses ||
2312+
(DTCI.ExplicitlyMapped.empty() && DTCI.Indirect.hasValue());
22912313

22922314
// Skip the last annot_pragma_openmp_end.
22932315
ConsumeAnyToken();
@@ -3384,6 +3406,47 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
33843406
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
33853407
}
33863408

3409+
/// Parse indirect clause for '#pragma omp declare target' directive.
3410+
/// 'indirect' '[' '(' invoked-by-fptr ')' ']'
3411+
/// where invoked-by-fptr is a constant boolean expression that evaluates to
3412+
/// true or false at compile time.
3413+
bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
3414+
bool ParseOnly) {
3415+
SourceLocation Loc = ConsumeToken();
3416+
SourceLocation RLoc;
3417+
3418+
if (Tok.isNot(tok::l_paren)) {
3419+
if (ParseOnly)
3420+
return false;
3421+
DTCI.Indirect = nullptr;
3422+
return true;
3423+
}
3424+
3425+
ExprResult Val =
3426+
ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3427+
if (Val.isInvalid())
3428+
return false;
3429+
3430+
if (ParseOnly)
3431+
return false;
3432+
3433+
if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3434+
!Val.get()->isInstantiationDependent() &&
3435+
!Val.get()->containsUnexpandedParameterPack()) {
3436+
ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3437+
if (Ret.isInvalid())
3438+
return false;
3439+
llvm::APSInt Result;
3440+
Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3441+
Sema::AllowFold);
3442+
if (Ret.isInvalid())
3443+
return false;
3444+
DTCI.Indirect = Val.get();
3445+
return true;
3446+
}
3447+
return false;
3448+
}
3449+
33873450
/// Parsing of OpenMP clauses that use an interop-var.
33883451
///
33893452
/// init-clause:

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20762,8 +20762,7 @@ Sema::ActOnOpenMPEndDeclareTargetDirective() {
2076220762
void Sema::ActOnFinishedOpenMPDeclareTargetContext(
2076320763
DeclareTargetContextInfo &DTCI) {
2076420764
for (auto &It : DTCI.ExplicitlyMapped)
20765-
ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT,
20766-
DTCI.DT);
20765+
ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
2076720766
}
2076820767

2076920768
NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
@@ -20800,9 +20799,9 @@ NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
2080020799
return ND;
2080120800
}
2080220801

20803-
void Sema::ActOnOpenMPDeclareTargetName(
20804-
NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
20805-
OMPDeclareTargetDeclAttr::DevTypeTy DT) {
20802+
void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
20803+
OMPDeclareTargetDeclAttr::MapTypeTy MT,
20804+
DeclareTargetContextInfo &DTCI) {
2080620805
assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
2080720806
isa<FunctionTemplateDecl>(ND)) &&
2080820807
"Expected variable, function or function template.");
@@ -20819,10 +20818,10 @@ void Sema::ActOnOpenMPDeclareTargetName(
2081920818
auto *VD = cast<ValueDecl>(ND);
2082020819
llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
2082120820
OMPDeclareTargetDeclAttr::getActiveAttr(VD);
20822-
if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getDevType() != DT &&
20821+
if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getDevType() != DTCI.DT &&
2082320822
ActiveAttr.getValue()->getLevel() == Level) {
2082420823
Diag(Loc, diag::err_omp_device_type_mismatch)
20825-
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT)
20824+
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
2082620825
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
2082720826
ActiveAttr.getValue()->getDevType());
2082820827
return;
@@ -20836,8 +20835,16 @@ void Sema::ActOnOpenMPDeclareTargetName(
2083620835
if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() == Level)
2083720836
return;
2083820837

20839-
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, Level,
20840-
SourceRange(Loc, Loc));
20838+
Expr *IndirectE = nullptr;
20839+
bool IsIndirect = false;
20840+
if (DTCI.Indirect.hasValue()) {
20841+
IndirectE = DTCI.Indirect.getValue();
20842+
if (!IndirectE)
20843+
IsIndirect = true;
20844+
}
20845+
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
20846+
Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
20847+
SourceRange(Loc, Loc));
2084120848
ND->addAttr(A);
2084220849
if (ASTMutationListener *ML = Context.getASTMutationListener())
2084320850
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
@@ -20928,9 +20935,16 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
2092820935
if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() >= Level)
2092920936
return;
2093020937
DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
20938+
Expr *IndirectE = nullptr;
20939+
bool IsIndirect = false;
20940+
if (DTCI.Indirect.hasValue()) {
20941+
IndirectE = DTCI.Indirect.getValue();
20942+
if (!IndirectE)
20943+
IsIndirect = true;
20944+
}
2093120945
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
20932-
Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, Level,
20933-
SourceRange(DTCI.Loc, DTCI.Loc));
20946+
Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, IndirectE,
20947+
IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc));
2093420948
D->addAttr(A);
2093520949
if (ASTMutationListener *ML = Context.getASTMutationListener())
2093620950
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4781,10 +4781,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
47814781
case UPD_DECL_MARKED_OPENMP_DECLARETARGET: {
47824782
auto MapType = Record.readEnum<OMPDeclareTargetDeclAttr::MapTypeTy>();
47834783
auto DevType = Record.readEnum<OMPDeclareTargetDeclAttr::DevTypeTy>();
4784+
Expr *IndirectE = Record.readExpr();
4785+
bool Indirect = Record.readBool();
47844786
unsigned Level = Record.readInt();
47854787
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
4786-
Reader.getContext(), MapType, DevType, Level, readSourceRange(),
4787-
AttributeCommonInfo::AS_Pragma));
4788+
Reader.getContext(), MapType, DevType, IndirectE, Indirect, Level,
4789+
readSourceRange(), AttributeCommonInfo::AS_Pragma));
47884790
break;
47894791
}
47904792

clang/test/OpenMP/declare_target_ast_print.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s
44

55
// RUN: %clang_cc1 -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50
6+
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP51
67
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
78
// 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
9+
// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
10+
// 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
811

912
// RUN: %clang_cc1 -verify -fopenmp-simd -I %S/Inputs -ast-print %s | FileCheck %s
1013
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
@@ -32,6 +35,48 @@ void bazz();
3235
// OMP50: #pragma omp end declare target{{$}}
3336
#endif // _OPENMP
3437

38+
#if _OPENMP == 202011
39+
extern "C" {
40+
void boo_c() {}
41+
#pragma omp declare target to(boo_c) indirect
42+
// OMP51: #pragma omp declare target indirect
43+
// OMP51: void boo_c() {
44+
// OMP51: }
45+
// OMP51: #pragma omp end declare target
46+
#pragma omp declare target indirect
47+
void yoo(){}
48+
#pragma omp end declare target
49+
// OMP51: #pragma omp declare target indirect
50+
// OMP51: void yoo() {
51+
// OMP51: }
52+
// OMP51: #pragma omp end declare target
53+
}
54+
extern "C++" {
55+
void boo_cpp() {}
56+
#pragma omp declare target to(boo_cpp) indirect
57+
// OMP51: #pragma omp declare target indirect
58+
// OMP51: void boo_cpp() {
59+
// OMP51: }
60+
// OMP51: #pragma omp end declare target
61+
62+
constexpr bool f() {return false;}
63+
#pragma omp begin declare target indirect(f())
64+
void zoo() {}
65+
void xoo();
66+
#pragma omp end declare target
67+
#pragma omp declare target to(zoo) indirect(false)
68+
// OMP51: #pragma omp declare target indirect(f())
69+
// OMP51: #pragma omp declare target indirect(false)
70+
// OMP51: void zoo() {
71+
// OMP51: }
72+
// OMP51: #pragma omp end declare target
73+
// OMP51: #pragma omp declare target indirect(f())
74+
// OMP51: void xoo();
75+
// OMP51: #pragma omp end declare target
76+
77+
}
78+
#endif // _OPENMP
79+
3580
int out_decl_target = 0;
3681
#pragma omp declare target (out_decl_target)
3782

0 commit comments

Comments
 (0)