jyu2 created this revision. jyu2 added reviewers: ABataev, mikerice, jdoerfert. jyu2 added a project: clang. Herald added subscribers: guansong, yaxunl. Herald added a reviewer: aaron.ballman. Herald added a project: Flang. jyu2 requested review of this revision. Herald added subscribers: llvm-commits, sstefan1. Herald added a project: LLVM.
Added basic parsing/sema/ support for the 'indirect' clause. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D116764 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/DiagnosticParseKinds.td clang/include/clang/Parse/Parser.h clang/include/clang/Sema/Sema.h clang/lib/AST/AttrImpl.cpp clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/Parse/ParseOpenMP.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/test/OpenMP/declare_target_ast_print.cpp clang/test/OpenMP/declare_target_messages.cpp flang/lib/Semantics/check-omp-structure.cpp llvm/include/llvm/Frontend/OpenMP/OMP.td
Index: llvm/include/llvm/Frontend/OpenMP/OMP.td =================================================================== --- llvm/include/llvm/Frontend/OpenMP/OMP.td +++ llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -358,6 +358,7 @@ 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 @@ 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"> {} Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -1528,6 +1528,7 @@ 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) Index: clang/test/OpenMP/declare_target_messages.cpp =================================================================== --- clang/test/OpenMP/declare_target_messages.cpp +++ 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 @@ 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 @@ #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 @@ } #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 @@ 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 Index: clang/test/OpenMP/declare_target_ast_print.cpp =================================================================== --- clang/test/OpenMP/declare_target_ast_print.cpp +++ 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 @@ // 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) Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -4781,10 +4781,12 @@ 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; } Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -15729,6 +15729,27 @@ StartLoc, LParenLoc, EndLoc); } +bool Sema::ActOnOpenMPIndirectClause(Expr *Condition, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = Condition; + if (!Condition->isValueDependent() && !Condition->isTypeDependent() && + !Condition->isInstantiationDependent() && + !Condition->containsUnexpandedParameterPack()) { + ExprResult Val = CheckBooleanCondition(StartLoc, Condition); + if (Val.isInvalid()) + return false; + llvm::APSInt Result; + Val = VerifyIntegerConstantExpression(ValExpr, &Result, AllowFold); + if (Val.isInvalid()) + return false; + if (Result.getBoolValue() == true) + return true; + } + return false; +} + OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -20763,7 +20784,7 @@ DeclareTargetContextInfo &DTCI) { for (auto &It : DTCI.ExplicitlyMapped) ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, - DTCI.DT); + DTCI); } NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope, @@ -20802,7 +20823,7 @@ void Sema::ActOnOpenMPDeclareTargetName( NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, - OMPDeclareTargetDeclAttr::DevTypeTy DT) { + DeclareTargetContextInfo &DTCI) { assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) && "Expected variable, function or function template."); @@ -20819,10 +20840,10 @@ 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 +20857,9 @@ if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() == Level) return; - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, Level, - SourceRange(Loc, Loc)); + auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( + Context, MT, DTCI.DT, DTCI.IndirectExpr, DTCI.IsIndirect, Level, + SourceRange(Loc, Loc)); ND->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); @@ -20929,7 +20951,8 @@ return; DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back(); auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, Level, + Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, + DTCI.IndirectExpr, DTCI.IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc)); D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) Index: clang/lib/Parse/ParseOpenMP.cpp =================================================================== --- clang/lib/Parse/ParseOpenMP.cpp +++ clang/lib/Parse/ParseOpenMP.cpp @@ -1814,38 +1814,55 @@ 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.IsIndirect && 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, /*ParseOlyn*/false)) + break; + continue; + } // Parse 'device_type' clause and go to next clause if any. if (IsDeviceTypeClause) { Optional<SimpleClauseData> DevTypeData = @@ -1911,10 +1928,14 @@ ConsumeToken(); } + if (DTCI.IsIndirect && 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 @@ 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.IsIndirect); // Skip the last annot_pragma_openmp_end. ConsumeAnyToken(); @@ -3384,6 +3406,38 @@ 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 LLoc = Tok.getLocation(); + SourceLocation RLoc; + + if (Tok.isNot(tok::l_paren)) { + DTCI.IsIndirect = true; + return true; + } + + ExprResult Val = + ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc); + + DTCI.IndirectExpr = Val.get(); + if (Val.isInvalid()) + return false; + + if (ParseOnly) + return false; + + if (Actions.ActOnOpenMPIndirectClause(Val.get(), Loc, LLoc, RLoc)) { + DTCI.IsIndirect = true; + return true; + } + return false; +} + /// Parsing of OpenMP clauses that use an interop-var. /// /// init-clause: Index: clang/lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- clang/lib/CodeGen/CGStmtOpenMP.cpp +++ clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -6046,6 +6046,7 @@ case OMPC_inbranch: case OMPC_notinbranch: case OMPC_link: + case OMPC_indirect: case OMPC_use: case OMPC_novariants: case OMPC_nocontext: Index: clang/lib/AST/AttrImpl.cpp =================================================================== --- clang/lib/AST/AttrImpl.cpp +++ clang/lib/AST/AttrImpl.cpp @@ -139,6 +139,13 @@ 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 *> Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -10333,6 +10333,10 @@ /// The directive kind, `begin declare target` or `declare target`. OpenMPDirectiveKind Kind; + /// The directive with indirect clause. + Expr *IndirectExpr = nullptr; + bool IsIndirect = false; + /// The directive location. SourceLocation Loc; @@ -10639,7 +10643,7 @@ /// 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 @@ -11238,6 +11242,10 @@ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'indirect' clause. + bool ActOnOpenMPIndirectClause(Expr *Condition, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// Called on well-formed 'filter' clause. OMPClause *ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -3315,6 +3315,11 @@ /// 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. /// Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1344,15 +1344,17 @@ 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< Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -3686,6 +3686,8 @@ EnumArgument<"DevType", "DevTypeTy", [ "host", "nohost", "any" ], [ "DT_Host", "DT_NoHost", "DT_Any" ]>, + ExprArgument<"IndirectExpr">, + BoolArgument<"Indirect">, UnsignedArgument<"Level"> ]; let AdditionalMembers = [{
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits