]> granicus.if.org Git - clang/commitdiff
[OPENMP] Fix for declarative/standalone directives use.
authorAlexey Bataev <a.bataev@hotmail.com>
Wed, 13 Jan 2016 11:18:54 +0000 (11:18 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Wed, 13 Jan 2016 11:18:54 +0000 (11:18 +0000)
Fixes processing of declarative directives and standalone executable directives. Declarative directives should not be allowed as an immediate statements and standalone executable directives are allowed to be used in case-stmt constructs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@257586 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseOpenMP.cpp
lib/Parse/ParseStmt.cpp
test/OpenMP/barrier_ast_print.cpp
test/OpenMP/barrier_messages.cpp
test/OpenMP/cancel_messages.cpp
test/OpenMP/cancellation_point_messages.cpp
test/OpenMP/flush_messages.cpp
test/OpenMP/taskwait_messages.cpp
test/OpenMP/taskyield_messages.cpp
test/OpenMP/threadprivate_messages.cpp

index 8017f19c6184ae287f5c1582c85ee004776b5284..00885a5c7103190cd262c21653f72c88bd42fd90 100644 (file)
@@ -1644,13 +1644,22 @@ private:
   /// A SmallVector of types.
   typedef SmallVector<ParsedType, 12> TypeVector;
 
-  StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr);
+  StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
+                            bool AllowOpenMPStandalone = false);
+  enum AllowedContsructsKind {
+    /// \brief Allow any declarations, statements, OpenMP directives.
+    ACK_Any,
+    /// \brief Allow only statements and non-standalone OpenMP directives.
+    ACK_StatementsOpenMPNonStandalone,
+    /// \brief Allow statements and all executable OpenMP directives
+    ACK_StatementsOpenMPAnyExecutable
+  };
   StmtResult
-  ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+  ParseStatementOrDeclaration(StmtVector &Stmts, AllowedContsructsKind Allowed,
                               SourceLocation *TrailingElseLoc = nullptr);
   StmtResult ParseStatementOrDeclarationAfterAttributes(
                                          StmtVector &Stmts,
-                                         bool OnlyStatement,
+                                         AllowedContsructsKind Allowed,
                                          SourceLocation *TrailingElseLoc,
                                          ParsedAttributesWithRange &Attrs);
   StmtResult ParseExprStatement();
@@ -1678,7 +1687,8 @@ private:
   StmtResult ParseReturnStatement();
   StmtResult ParseAsmStatement(bool &msAsm);
   StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
-  StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
+  StmtResult ParsePragmaLoopHint(StmtVector &Stmts,
+                                 AllowedContsructsKind Allowed,
                                  SourceLocation *TrailingElseLoc,
                                  ParsedAttributesWithRange &Attrs);
 
@@ -2443,11 +2453,13 @@ private:
                                 bool AllowScopeSpecifier);
   /// \brief Parses declarative or executable directive.
   ///
-  /// \param StandAloneAllowed true if allowed stand-alone directives,
-  /// false - otherwise
+  /// \param Allowed ACK_Any, if any directives are allowed,
+  /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
+  /// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone
+  /// executable directives are allowed.
   ///
   StmtResult
-  ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed);
+  ParseOpenMPDeclarativeOrExecutableDirective(AllowedContsructsKind Allowed);
   /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
   ///
   /// \param DKind Kind of current directive.
index 078f4c38870588b485627f39edfde4d7bed0b63a..a08db5490fa9e4be156a10543f06d7f324ef378a 100644 (file)
@@ -165,8 +165,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
 ///         'distribute'
 ///         annot_pragma_openmp_end
 ///
-StmtResult
-Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
+StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
+    AllowedContsructsKind Allowed) {
   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
   ParenBraceBracketBalancer BalancerRAIIObj(*this);
   SmallVector<Expr *, 5> Identifiers;
@@ -186,6 +186,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
 
   switch (DKind) {
   case OMPD_threadprivate:
+    if (Allowed != ACK_Any) {
+      Diag(Tok, diag::err_omp_immediate_directive)
+          << getOpenMPDirectiveName(DKind) << 0;
+    }
     ConsumeToken();
     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
       // The last seen token is annot_pragma_openmp_end - need to check for
@@ -213,7 +217,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
   case OMPD_taskwait:
   case OMPD_cancellation_point:
   case OMPD_cancel:
-    if (!StandAloneAllowed) {
+    if (Allowed == ACK_StatementsOpenMPNonStandalone) {
       Diag(Tok, diag::err_omp_immediate_directive)
           << getOpenMPDirectiveName(DKind) << 0;
     }
@@ -299,7 +303,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
     // If the depend clause is specified, the ordered construct is a stand-alone
     // directive.
     if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
-      if (!StandAloneAllowed) {
+      if (Allowed == ACK_StatementsOpenMPNonStandalone) {
         Diag(Loc, diag::err_omp_immediate_directive)
             << getOpenMPDirectiveName(DKind) << 1
             << getOpenMPClauseName(OMPC_depend);
index 1dafae0c94c9b9cb65642b9ee8f92be1edcb2e49..edf0dda7df8c09ce006233187f986f439018f494 100644 (file)
@@ -32,14 +32,18 @@ using namespace clang;
 
 /// \brief Parse a standalone statement (for instance, as the body of an 'if',
 /// 'while', or 'for').
-StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) {
+StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
+                                  bool AllowOpenMPStandalone) {
   StmtResult Res;
 
   // We may get back a null statement if we found a #pragma. Keep going until
   // we get an actual statement.
   do {
     StmtVector Stmts;
-    Res = ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);
+    Res = ParseStatementOrDeclaration(
+        Stmts, AllowOpenMPStandalone ? ACK_StatementsOpenMPAnyExecutable
+                                     : ACK_StatementsOpenMPNonStandalone,
+        TrailingElseLoc);
   } while (!Res.isInvalid() && !Res.get());
 
   return Res;
@@ -95,7 +99,8 @@ StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) {
 /// [OBC]   '@' 'throw' ';'
 ///
 StmtResult
-Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
+                                    AllowedContsructsKind Allowed,
                                     SourceLocation *TrailingElseLoc) {
 
   ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -103,8 +108,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
   ParsedAttributesWithRange Attrs(AttrFactory);
   MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
 
-  StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,
-                                 OnlyStatement, TrailingElseLoc, Attrs);
+  StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
+      Stmts, Allowed, TrailingElseLoc, Attrs);
 
   assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
          "attributes on empty statement");
@@ -146,7 +151,7 @@ private:
 
 StmtResult
 Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
-          bool OnlyStatement, SourceLocation *TrailingElseLoc,
+          AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc,
           ParsedAttributesWithRange &Attrs) {
   const char *SemiError = nullptr;
   StmtResult Res;
@@ -202,7 +207,8 @@ Retry:
   }
 
   default: {
-    if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
+    if ((getLangOpts().CPlusPlus || Allowed == ACK_Any) &&
+        isDeclarationStatement()) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
       DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext,
                                              DeclEnd, Attrs);
@@ -346,7 +352,7 @@ Retry:
 
   case tok::annot_pragma_openmp:
     ProhibitAttributes(Attrs);
-    return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement);
+    return ParseOpenMPDeclarativeOrExecutableDirective(Allowed);
 
   case tok::annot_pragma_ms_pointers_to_members:
     ProhibitAttributes(Attrs);
@@ -365,7 +371,7 @@ Retry:
 
   case tok::annot_pragma_loop_hint:
     ProhibitAttributes(Attrs);
-    return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);
+    return ParsePragmaLoopHint(Stmts, Allowed, TrailingElseLoc, Attrs);
 
   case tok::annot_pragma_dump:
     HandlePragmaDump();
@@ -587,7 +593,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
       // can't handle GNU attributes), so only call it in the one case where
       // GNU attributes are allowed.
       SubStmt = ParseStatementOrDeclarationAfterAttributes(
-          Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs);
+          Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr,
+          TempAttrs);
       if (!TempAttrs.empty() && !SubStmt.isInvalid())
         SubStmt = Actions.ProcessStmtAttributes(
             SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
@@ -726,7 +733,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
     // continue parsing the sub-stmt.
     if (Case.isInvalid()) {
       if (TopLevelCase.isInvalid())  // No parsed case stmts.
-        return ParseStatement();
+        return ParseStatement(/*TrailingElseLoc=*/nullptr,
+                              /*AllowOpenMPStandalone=*/true);
       // Otherwise, just don't add it as a nested case.
     } else {
       // If this is the first case statement we parsed, it becomes TopLevelCase.
@@ -746,7 +754,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
   StmtResult SubStmt;
 
   if (Tok.isNot(tok::r_brace)) {
-    SubStmt = ParseStatement();
+    SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr,
+                             /*AllowOpenMPStandalone=*/true);
   } else {
     // Nicely diagnose the common error "switch (X) { case 4: }", which is
     // not valid.  If ColonLoc doesn't point to a valid text location, there was
@@ -798,7 +807,8 @@ StmtResult Parser::ParseDefaultStatement() {
   StmtResult SubStmt;
 
   if (Tok.isNot(tok::r_brace)) {
-    SubStmt = ParseStatement();
+    SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr,
+                             /*AllowOpenMPStandalone=*/true);
   } else {
     // Diagnose the common error "switch (X) {... default: }", which is
     // not valid.
@@ -972,7 +982,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
 
     StmtResult R;
     if (Tok.isNot(tok::kw___extension__)) {
-      R = ParseStatementOrDeclaration(Stmts, false);
+      R = ParseStatementOrDeclaration(Stmts, ACK_Any);
     } else {
       // __extension__ can start declarations and it can also be a unary
       // operator for expressions.  Consume multiple __extension__ markers here
@@ -1868,7 +1878,8 @@ StmtResult Parser::ParseReturnStatement() {
   return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
 }
 
-StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
+StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
+                                       AllowedContsructsKind Allowed,
                                        SourceLocation *TrailingElseLoc,
                                        ParsedAttributesWithRange &Attrs) {
   // Create temporary attribute list.
@@ -1891,7 +1902,7 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
   MaybeParseCXX11Attributes(Attrs);
 
   StmtResult S = ParseStatementOrDeclarationAfterAttributes(
-      Stmts, OnlyStatement, TrailingElseLoc, Attrs);
+      Stmts, Allowed, TrailingElseLoc, Attrs);
 
   Attrs.takeAllFrom(TempAttrs);
   return S;
@@ -2189,7 +2200,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
 
   // Condition is true, parse the statements.
   while (Tok.isNot(tok::r_brace)) {
-    StmtResult R = ParseStatementOrDeclaration(Stmts, false);
+    StmtResult R = ParseStatementOrDeclaration(Stmts, ACK_Any);
     if (R.isUsable())
       Stmts.push_back(R.get());
   }
index fbb478bfb6b7bde2515d327939dce46425f838d7..062df80a226e347bf0851b285e5374a0574670de 100644 (file)
@@ -12,6 +12,15 @@ template <class T>
 T tmain(T argc) {
   static T a;
 #pragma omp barrier
+  switch (argc) {
+  case 0:
+#pragma omp barrier
+    break;
+  default:
+#pragma omp barrier
+#pragma omp barrier
+    break;
+  }
   return a + argc;
 }
 // CHECK:      static int a;
@@ -20,12 +29,39 @@ T tmain(T argc) {
 // CHECK-NEXT: #pragma omp barrier
 // CHECK:      static T a;
 // CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: switch (argc) {
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: break;
+// CHECK-NEXT: default:
+// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: break;
+// CHECK-NEXT: }
 
 int main(int argc, char **argv) {
   static int a;
 // CHECK: static int a;
 #pragma omp barrier
   // CHECK-NEXT: #pragma omp barrier
+  switch (argc) {
+  case 0:
+#pragma omp barrier
+#pragma omp barrier
+    break;
+  default:
+#pragma omp barrier
+    break;
+  }
+// CHECK-NEXT: switch (argc) {
+// CHECK-NEXT: case 0:
+// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: break;
+// CHECK-NEXT: default:
+// CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: break;
+// CHECK-NEXT: }
   return tmain(argc) + tmain(argv[0][0]) + a;
 }
 
index 4dc6480a57e25a0d863a65ff718a22aa811b7a26..7d79445d285772392644679fe4e4a5292d09949c 100644 (file)
@@ -27,7 +27,7 @@ T tmain(T argc) {
 #pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
+#pragma omp barrier
   switch (argc)
   case 1: {
 #pragma omp barrier
@@ -35,7 +35,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp barrier
   case 1:
-#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
+#pragma omp barrier
     break;
   default: {
 #pragma omp barrier
@@ -81,7 +81,7 @@ int main(int argc, char **argv) {
 #pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
+#pragma omp barrier
   switch (argc)
   case 1: {
 #pragma omp barrier
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp barrier
   case 1:
-#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
+#pragma omp barrier
     break;
   default: {
 #pragma omp barrier
index 07088387cb4f5e09cefc195cd0db70656c7665f9..e23b5c337bc805b84499442698efd92c0a24467c 100644 (file)
@@ -53,7 +53,7 @@ int main(int argc, char **argv) {
 #pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp cancel sections // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel sections
   switch (argc)
   case 1: {
 #pragma omp cancel for
@@ -61,7 +61,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp cancel taskgroup
   case 1:
-#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel parallel
     break;
   default: {
 #pragma omp cancel sections
index d25cb6113d1614bbb2c86118650dacf5bc0423c0..2324915e83f8221b2f3fa131c525d981fa11f683 100644 (file)
@@ -53,7 +53,7 @@ int main(int argc, char **argv) {
 #pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp cancellation point sections // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point sections
   switch (argc)
   case 1: {
 #pragma omp cancellation point for
@@ -61,7 +61,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp cancellation point taskgroup
   case 1:
-#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point parallel
     break;
   default: {
 #pragma omp cancellation point sections
index 2f87a2938476b49a02aec99959a943bd703fba04..1c086a3f3fa4abc55eff45652d0dfe3fb593838e 100644 (file)
@@ -31,7 +31,7 @@ T tmain(T argc) {
 #pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+#pragma omp flush
   switch (argc)
   case 1: {
 #pragma omp flush
@@ -39,7 +39,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp flush
   case 1:
-#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+#pragma omp flush
     break;
   default: {
 #pragma omp flush
@@ -95,7 +95,7 @@ int main(int argc, char **argv) {
 #pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+#pragma omp flush
   switch (argc)
   case 1: {
 #pragma omp flush
@@ -103,7 +103,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp flush
   case 1:
-#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+#pragma omp flush
     break;
   default: {
 #pragma omp flush
index 08405135404585c6b244d89c96a093694ac5f350..06e8e6b8bdf275f3fc5b424153dd7e9642274512 100644 (file)
@@ -27,7 +27,7 @@ T tmain(T argc) {
 #pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}}
+#pragma omp taskwait
   switch (argc)
   case 1: {
 #pragma omp taskwait
@@ -35,7 +35,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp taskwait
   case 1:
-#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}}
+#pragma omp taskwait
     break;
   default: {
 #pragma omp taskwait
@@ -81,7 +81,7 @@ int main(int argc, char **argv) {
 #pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}}
+#pragma omp taskwait
   switch (argc)
   case 1: {
 #pragma omp taskwait
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp taskwait
   case 1:
-#pragma omp taskwait // expected-error {{'#pragma omp taskwait' cannot be an immediate substatement}}
+#pragma omp taskwait
     break;
   default: {
 #pragma omp taskwait
index 23c0b5339012f6e92626280946bc9f1f39803762..cfeaa63815b32b6353d84dc95ef6afbe65a3fded 100644 (file)
@@ -27,7 +27,7 @@ T tmain(T argc) {
 #pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
+#pragma omp taskyield
   switch (argc)
   case 1: {
 #pragma omp taskyield
@@ -35,7 +35,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp taskyield
   case 1:
-#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
+#pragma omp taskyield
     break;
   default: {
 #pragma omp taskyield
@@ -81,7 +81,7 @@ int main(int argc, char **argv) {
 #pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
     switch (argc)
     case 1:
-#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
+#pragma omp taskyield
   switch (argc)
   case 1: {
 #pragma omp taskyield
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp taskyield
   case 1:
-#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
+#pragma omp taskyield
     break;
   default: {
 #pragma omp taskyield
index f71d58bc52a4deb348b16085039d4377d0d5c7ea..8c442f47ad5eedfee8bc087ba29942d2a1987a81 100644 (file)
@@ -118,6 +118,7 @@ int main(int argc, char **argv) { // expected-note {{'argc' defined here}}
   static double d1;
   static double d2;
   static double d3; // expected-note {{'d3' defined here}}
+  static double d4;
   static TestClass LocalClass(y); // expected-error {{variable with local storage in initial value of threadprivate variable}}
 #pragma omp threadprivate(LocalClass)
 
@@ -133,6 +134,8 @@ int main(int argc, char **argv) { // expected-note {{'argc' defined here}}
 #pragma omp threadprivate(d3) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'd3' variable declaration}}
   }
 #pragma omp threadprivate(d3)
+label:
+#pragma omp threadprivate(d4) // expected-error {{'#pragma omp threadprivate' cannot be an immediate substatement}}
 
 #pragma omp threadprivate(a) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'a' variable declaration}}
   return (y);