From 20dfd778264a680cf46e24b7457b8b797e7987cb Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 4 Apr 2016 10:12:15 +0000 Subject: [PATCH] [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. llvm-svn: 265287 --- clang/include/clang/Basic/Attr.td | 8 +++- .../clang/Basic/DiagnosticParseKinds.td | 2 + clang/include/clang/Sema/Sema.h | 6 ++- clang/lib/Parse/ParseOpenMP.cpp | 47 ++++++++++++++++--- clang/lib/Sema/SemaOpenMP.cpp | 8 ++-- clang/test/OpenMP/declare_simd_ast_print.c | 6 ++- clang/test/OpenMP/declare_simd_ast_print.cpp | 6 ++- clang/test/OpenMP/declare_simd_messages.cpp | 6 +++ clang/test/OpenMP/dump.cpp | 6 +-- 9 files changed, 77 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 332796ea18a2..3dd83dcfe3ac 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/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/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 79f7437c7534..4c28f0e29f45 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f7a56a26036e..e58013856b83 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 96cf37912f2a..dcff1595611d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/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/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 6458eee56cb3..8d53dc4e724a 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/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/clang/test/OpenMP/declare_simd_ast_print.c b/clang/test/OpenMP/declare_simd_ast_print.c index d2b91eb15ea7..5cadd0038ce5 100644 --- a/clang/test/OpenMP/declare_simd_ast_print.c +++ b/clang/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/clang/test/OpenMP/declare_simd_ast_print.cpp b/clang/test/OpenMP/declare_simd_ast_print.cpp index aff2c944f08a..4cee8df8954a 100644 --- a/clang/test/OpenMP/declare_simd_ast_print.cpp +++ b/clang/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/clang/test/OpenMP/declare_simd_messages.cpp b/clang/test/OpenMP/declare_simd_messages.cpp index 2085bfc2ddec..76fdc2d87e26 100644 --- a/clang/test/OpenMP/declare_simd_messages.cpp +++ b/clang/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/clang/test/OpenMP/dump.cpp b/clang/test/OpenMP/dump.cpp index 5059a044624b..b08df674ed53 100644 --- a/clang/test/OpenMP/dump.cpp +++ b/clang/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