diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 874e0e2049b1..bc097e0bf3fc 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -909,6 +909,8 @@ def err_omp_more_one_clause : Error< def err_pragma_loop_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " "vectorize_width, interleave, interleave_count, unroll, or unroll_count">; +def err_pragma_loop_missing_argument : Error< + "missing argument to loop pragma %0">; } // end of Parse Issue category. let CategoryName = "Modules Issue" in { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 002710e30a83..b3a732e9e4cb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -543,9 +543,9 @@ def err_pragma_pop_visibility_mismatch : Error< def note_surrounding_namespace_starts_here : Note< "surrounding namespace with visibility attribute starts here">; def err_pragma_loop_invalid_value : Error< - "%select{invalid|missing}0 value%select{ %1|}0; expected a positive integer value">; + "invalid argument; expected a positive integer value">; def err_pragma_loop_invalid_keyword : Error< - "%select{invalid|missing}0 keyword%select{ %1|}0; expected 'enable' or 'disable'">; + "invalid argument; expected 'enable' or 'disable'">; def err_pragma_loop_compatibility : Error< "%select{incompatible|duplicate}0 directives '%1(%2)' and '%3(%4)'">; def err_pragma_loop_precedes_nonloop : Error< diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index c7a344f59da4..2b248cc10fb3 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -1710,9 +1710,13 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, // FIXME: All tokens between '(' and ')' should be stored and parsed as a // constant expression. PP.Lex(Tok); - Token Value; - if (Tok.is(tok::identifier) || Tok.is(tok::numeric_constant)) - Value = Tok; + if (Tok.is(tok::r_paren)) { + // Nothing between the parentheses. + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_missing_argument) + << OptionInfo; + return; + } + Token Value = Tok; // Read ')' PP.Lex(Tok); diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index c0b5ede526ce..44169c2fdce8 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -75,18 +75,15 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) { if (!ValueInfo) { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword) - << /*MissingKeyword=*/true << ""; + S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword); return nullptr; } - if (ValueInfo->isStr("disable")) ValueInt = 0; else if (ValueInfo->isStr("enable")) ValueInt = 1; else { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword) - << /*MissingKeyword=*/false << ValueInfo; + S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword); return nullptr; } } else if (Option == LoopHintAttr::VectorizeWidth || @@ -95,15 +92,9 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, // FIXME: We should support template parameters for the loop hint value. // See bug report #19610. llvm::APSInt ValueAPS; - if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context)) { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value) - << /*MissingValue=*/true << ""; - return nullptr; - } - - if ((ValueInt = ValueAPS.getSExtValue()) < 1) { - S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value) - << /*MissingValue=*/false << ValueInt; + if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) || + (ValueInt = ValueAPS.getSExtValue()) < 1) { + S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value); return nullptr; } } else diff --git a/clang/test/Parser/pragma-loop.cpp b/clang/test/Parser/pragma-loop.cpp index 6535b62e3b5a..fad4feb8707f 100644 --- a/clang/test/Parser/pragma-loop.cpp +++ b/clang/test/Parser/pragma-loop.cpp @@ -55,6 +55,10 @@ void test(int *List, int Length) { /* expected-error {{expected ')'}} */ #pragma clang loop interleave_count(4 /* expected-error {{expected ')'}} */ #pragma clang loop unroll_count(4 +/* expected-error {{missing argument to loop pragma 'vectorize'}} */ #pragma clang loop vectorize() +/* expected-error {{missing argument to loop pragma 'interleave_count'}} */ #pragma clang loop interleave_count() +/* expected-error {{missing argument to loop pragma 'unroll'}} */ #pragma clang loop unroll() + /* expected-error {{missing option}} */ #pragma clang loop /* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword /* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword(enable) @@ -65,34 +69,46 @@ void test(int *List, int Length) { List[i] = i; } -/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop vectorize_width(0) -/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop interleave_count(0) -/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop unroll_count(0) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop vectorize_width(0) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop interleave_count(0) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop unroll_count(0) while (i-5 < Length) { List[i] = i; } -/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop vectorize_width(3000000000) -/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop interleave_count(3000000000) -/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop unroll_count(3000000000) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop vectorize_width(3000000000) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop interleave_count(3000000000) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop unroll_count(3000000000) while (i-6 < Length) { List[i] = i; } -/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop vectorize_width(badvalue) -/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop interleave_count(badvalue) -/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop unroll_count(badvalue) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop vectorize_width(badvalue) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop interleave_count(badvalue) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop unroll_count(badvalue) while (i-6 < Length) { List[i] = i; } -/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop vectorize(badidentifier) -/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop interleave(badidentifier) -/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop unroll(badidentifier) +/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop vectorize(badidentifier) +/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop interleave(badidentifier) +/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop unroll(badidentifier) while (i-7 < Length) { List[i] = i; } +// PR20069 - Loop pragma arguments that are not identifiers or numeric +// constants crash FE. +/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop vectorize(() +/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop interleave(*) +/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop unroll(=) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop vectorize_width(^) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop interleave_count(/) +/* expected-error {{invalid argument; expected a positive integer value}} */ #pragma clang loop unroll_count(==) + while (i-8 < Length) { + List[i] = i; + } + #pragma clang loop vectorize(enable) /* expected-error {{expected a for, while, or do-while loop to follow the '#pragma clang loop' directive}} */ int j = Length; List[0] = List[1];