]> granicus.if.org Git - clang/commitdiff
[OPENMP 4.0] Support for 'inbranch|noinbranch' clauses in 'declare
authorAlexey Bataev <a.bataev@hotmail.com>
Mon, 4 Apr 2016 10:12:15 +0000 (10:12 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Mon, 4 Apr 2016 10:12:15 +0000 (10:12 +0000)
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

include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Sema/Sema.h
lib/Parse/ParseOpenMP.cpp
lib/Sema/SemaOpenMP.cpp
test/OpenMP/declare_simd_ast_print.c
test/OpenMP/declare_simd_ast_print.cpp
test/OpenMP/declare_simd_messages.cpp
test/OpenMP/dump.cpp

index 332796ea18a2664e8f413cfa669f26ced362b088..3dd83dcfe3ac9b9424973f25cf01a4190959f139 100644 (file)
@@ -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());
+    }
   }];
 }
 
index 79f7437c7534617fca52a253bef519b26d2db6e5..4c28f0e29f4532f380a63baef60a8bc5a7b28f86 100644 (file)
@@ -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<
index f7a56a26036e08579ac41fdaf6507ee6ea1f59d5..e58013856b830cfc8d453fe43114c09da4b7f913 100644 (file)
@@ -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,
index 96cf37912f2ab3b84cfc76b1a8b108a58cd73fa4..dcff1595611dd571d4ce110ff7b3378155cb2991 100644 (file)
@@ -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);
index 6458eee56cb31879bd09e87b77eee14f3f492eb4..8d53dc4e724a944967519756fdf850dc8c2cbdad 100644 (file)
@@ -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);
 }
index d2b91eb15ea72393919397ddd48a91fbb553e53b..5cadd0038ce5d1bff598f9fbdbe8a477032423a6 100644 (file)
@@ -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))
 
index aff2c944f08a1de946d8a14e48b4deab2234b467..4cee8df8954ac119fe1666bf4b27d76f35a26a44 100644 (file)
@@ -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));
 //
 
index 2085bfc2ddec870d42359f41cca95e8ff355c48e..76fdc2d87e26d44398e2ce4eb1bf1d2becdd3439 100644 (file)
@@ -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 <class T>
 struct St {
 // expected-error@+2 {{function declaration is expected after 'declare simd' directive}}
index 5059a044624b3ca6b3199159c1f76e43618c2512..b08df674ed53ee606030641dd30f1537ba9e1e70 100644 (file)
@@ -59,10 +59,10 @@ struct S {
 // CHECK-NEXT: |       | | |   `-DeclRefExpr {{.+}} <<invalid sloc>> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
 
 #pragma omp declare simd
-#pragma omp declare simd
+#pragma omp declare simd inbranch
 void foo();
 
 // CHECK:      `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void (void)'
-// CHECK-NEXT:   |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9> Implicit
-// CHECK-NEXT:   `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9> Implicit
+// CHECK-NEXT:   |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:34> Implicit BS_Inbranch
+// CHECK-NEXT:   `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9, col:25> Implicit BS_Undefined