From: Alexey Bataev Date: Mon, 4 Apr 2016 10:12:15 +0000 (+0000) Subject: [OPENMP 4.0] Support for 'inbranch|noinbranch' clauses in 'declare X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dffb97b7784248a8e340791697392b17fe74de5b;p=clang [OPENMP 4.0] Support for 'inbranch|noinbranch' clauses in 'declare simd'. Added parsing/semantic analysis for 'inbranch|notinbranch' clauses of '#pragma omp declare simd' construct. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@265287 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 332796ea18..3dd83dcfe3 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -2265,8 +2265,14 @@ def OMPDeclareSimdDecl : Attr { let SemaHandler = 0; let HasCustomParsing = 1; let Documentation = [OMPDeclareSimdDocs]; + let Args = [EnumArgument<"BranchState", "BranchStateTy", + ["", "inbranch", "notinbranch"], + ["BS_Undefined", "BS_Inbranch", "BS_Notinbranch"]>]; let AdditionalMembers = [{ - void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {} + void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy) + const { + OS << ' ' << ConvertBranchStateTyToStr(getBranchState()); + } }]; } diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 79f7437c75..4c28f0e29f 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -961,6 +961,8 @@ def err_omp_unknown_map_type_modifier : Error< "incorrect map type modifier, expected 'always'">; def err_omp_map_type_missing : Error< "missing map type">; +def err_omp_declare_simd_inbranch_notinbranch : Error< + "unexpected '%0' clause, '%1' is specified already">; // Pragma loop support. def err_pragma_loop_missing_argument : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f7a56a2603..e58013856b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -8091,8 +8091,10 @@ public: /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of /// the associated method/function. - DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, - SourceLocation StartLoc); + DeclGroupPtrTy + ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, + OMPDeclareSimdDeclAttr::BranchStateTy BS, + SourceRange SR); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 96cf37912f..dcff159561 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -323,6 +323,37 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { IsCorrect); } +/// Parses clauses for 'declare simd' directive. +/// clause: +/// 'inbranch' | 'notinbranch' +static void parseDeclareSimdClauses(Parser &P, + OMPDeclareSimdDeclAttr::BranchStateTy &BS) { + SourceRange BSRange; + const Token &Tok = P.getCurToken(); + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + if (Tok.isNot(tok::identifier)) + break; + OMPDeclareSimdDeclAttr::BranchStateTy Out; + StringRef TokName = Tok.getIdentifierInfo()->getName(); + // Parse 'inranch|notinbranch' clauses. + if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(TokName, Out)) { + if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { + P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) + << TokName << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) + << BSRange; + } + BS = Out; + BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); + } else + // TODO: add parsing of other clauses. + break; + P.ConsumeToken(); + // Skip ',' if any. + if (Tok.is(tok::comma)) + P.ConsumeToken(); + } +} + /// \brief Parsing of declarative OpenMP directives. /// /// threadprivate-directive: @@ -387,8 +418,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( // ConsumeToken(); - // The last seen token is annot_pragma_openmp_end - need to check for - // extra tokens. + OMPDeclareSimdDeclAttr::BranchStateTy BS = + OMPDeclareSimdDeclAttr::BS_Undefined; + parseDeclareSimdClauses(*this, BS); + + // Need to check for extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) << getOpenMPDirectiveName(OMPD_declare_simd); @@ -396,12 +430,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ConsumeAnyToken(); } // Skip the last annot_pragma_openmp_end. - ConsumeToken(); + SourceLocation EndLoc = ConsumeToken(); DeclGroupPtrTy Ptr; - if (Tok.is(tok::annot_pragma_openmp)) { + if (Tok.is(tok::annot_pragma_openmp)) Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); - } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Here we expect to see some function declaration. if (AS == AS_none) { assert(TagType == DeclSpec::TST_unspecified); @@ -419,7 +453,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( return DeclGroupPtrTy(); } - return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, Loc); + return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, BS, + SourceRange(Loc, EndLoc)); } case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 6458eee56c..8d53dc4e72 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -3183,12 +3183,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, - SourceLocation StartLoc) { + OMPDeclareSimdDeclAttr::BranchStateTy BS, + SourceRange SR) { if (!DG || DG.get().isNull()) return DeclGroupPtrTy(); if (!DG.get().isSingleDecl()) { - Diag(StartLoc, diag::err_omp_single_decl_in_declare_simd); + Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd); return DG; } auto *ADecl = DG.get().getSingleDecl(); @@ -3201,8 +3202,7 @@ Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, return DeclGroupPtrTy(); } - auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( - Context, SourceRange(StartLoc, StartLoc)); + auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(Context, BS, SR); ADecl->addAttr(NewAttr); return ConvertDeclToDeclGroup(ADecl); } diff --git a/test/OpenMP/declare_simd_ast_print.c b/test/OpenMP/declare_simd_ast_print.c index d2b91eb15e..5cadd0038c 100644 --- a/test/OpenMP/declare_simd_ast_print.c +++ b/test/OpenMP/declare_simd_ast_print.c @@ -8,9 +8,13 @@ #pragma omp declare simd #pragma omp declare simd +#pragma omp declare simd inbranch +#pragma omp declare simd notinbranch void add_1(float *d, float *s1, float *s2) __attribute__((cold)); -// CHECK: #pragma omp declare simd +// CHECK: #pragma omp declare simd notinbranch +// CHECK-NEXT: #pragma omp declare simd inbranch +// CHECK-NEXT: #pragma omp declare simd // CHECK-NEXT: #pragma omp declare simd // CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold)) diff --git a/test/OpenMP/declare_simd_ast_print.cpp b/test/OpenMP/declare_simd_ast_print.cpp index aff2c944f0..4cee8df895 100644 --- a/test/OpenMP/declare_simd_ast_print.cpp +++ b/test/OpenMP/declare_simd_ast_print.cpp @@ -7,9 +7,13 @@ #define HEADER #pragma omp declare simd +#pragma omp declare simd inbranch +#pragma omp declare simd notinbranch void add_1(float *d) __attribute__((cold)); -// CHECK: #pragma omp declare simd +// CHECK: #pragma omp declare simd notinbranch +// CHECK-NEXT: #pragma omp declare simd inbranch +// CHECK-NEXT: #pragma omp declare simd // CHECK-NEXT: void add_1(float *d) __attribute__((cold)); // diff --git a/test/OpenMP/declare_simd_messages.cpp b/test/OpenMP/declare_simd_messages.cpp index 2085bfc2dd..76fdc2d87e 100644 --- a/test/OpenMP/declare_simd_messages.cpp +++ b/test/OpenMP/declare_simd_messages.cpp @@ -46,6 +46,12 @@ void h(int *hp, int *hp2, int *hq, int *lin) { h((float *)hp, (float *)hp2, (float *)hq, (float *)lin); } +#pragma omp declare simd inbranch inbranch +#pragma omp declare simd notinbranch notinbranch +#pragma omp declare simd inbranch inbranch notinbranch // expected-error {{unexpected 'notinbranch' clause, 'inbranch' is specified already}} +#pragma omp declare simd notinbranch notinbranch inbranch // expected-error {{unexpected 'inbranch' clause, 'notinbranch' is specified already}} +void foo(); + template struct St { // expected-error@+2 {{function declaration is expected after 'declare simd' directive}} diff --git a/test/OpenMP/dump.cpp b/test/OpenMP/dump.cpp index 5059a04462..b08df674ed 100644 --- a/test/OpenMP/dump.cpp +++ b/test/OpenMP/dump.cpp @@ -59,10 +59,10 @@ struct S { // CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} <> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &' #pragma omp declare simd -#pragma omp declare simd +#pragma omp declare simd inbranch void foo(); // CHECK: `-FunctionDecl {{.+}} col:6 foo 'void (void)' -// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} Implicit -// CHECK-NEXT: `-OMPDeclareSimdDeclAttr {{.+}} Implicit +// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} Implicit BS_Inbranch +// CHECK-NEXT: `-OMPDeclareSimdDeclAttr {{.+}} Implicit BS_Undefined