/// 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();
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);
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.
/// '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;
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
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;
}
// 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);
/// \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;
/// [OBC] '@' 'throw' ';'
///
StmtResult
-Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
+ AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
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");
StmtResult
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
- bool OnlyStatement, SourceLocation *TrailingElseLoc,
+ AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
const char *SemiError = nullptr;
StmtResult Res;
}
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);
case tok::annot_pragma_openmp:
ProhibitAttributes(Attrs);
- return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement);
+ return ParseOpenMPDeclarativeOrExecutableDirective(Allowed);
case tok::annot_pragma_ms_pointers_to_members:
ProhibitAttributes(Attrs);
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();
// 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);
// 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.
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
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.
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
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.
MaybeParseCXX11Attributes(Attrs);
StmtResult S = ParseStatementOrDeclarationAfterAttributes(
- Stmts, OnlyStatement, TrailingElseLoc, Attrs);
+ Stmts, Allowed, TrailingElseLoc, Attrs);
Attrs.takeAllFrom(TempAttrs);
return S;
// 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());
}
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;
// 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;
}
#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
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
#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
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
#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
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
#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
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
#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
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
#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
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
#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
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
#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
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
#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
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
#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
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
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)
#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);