From: Richard Smith Date: Mon, 28 Oct 2013 22:04:30 +0000 (+0000) Subject: Fix a parser crash when there are #pragmas in a context which requires a single X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=961d0573487933199cb287ce8c472121812b3c78;p=clang Fix a parser crash when there are #pragmas in a context which requires a single statement (after a case label, if, etc). Patch by Olivier Goffart! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193545 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 1fd1d866b2..9ff5bdfb45 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1470,10 +1470,7 @@ private: /// A SmallVector of types. typedef SmallVector TypeVector; - StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0) { - StmtVector Stmts; - return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc); - } + StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0); StmtResult ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, SourceLocation *TrailingElseLoc = 0); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index f57ff97ceb..caf0011dba 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -41,6 +41,21 @@ using namespace clang; // C99 6.8: Statements and Blocks. //===----------------------------------------------------------------------===// +/// \brief Parse a standalone statement (for instance, as the body of an 'if', +/// 'while', or 'for'). +StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) { + 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); + } while (!Res.isInvalid() && !Res.get()); + + return Res; +} + /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'. /// StatementOrDeclaration: /// statement diff --git a/test/CodeGen/pragma-weak.c b/test/CodeGen/pragma-weak.c index 559be831a5..b5d186324b 100644 --- a/test/CodeGen/pragma-weak.c +++ b/test/CodeGen/pragma-weak.c @@ -149,6 +149,28 @@ void PR14046f() { } // CHECK: declare extern_weak i32 @PR14046e() +// Parse #pragma weak after a label or case statement +extern int PR16705a(void); +extern int PR16705b(void); +extern int PR16705c(void); +void PR16705f(int a) { + switch(a) { + case 1: +#pragma weak PR16705a + PR16705a(); + default: +#pragma weak PR16705b + PR16705b(); + } +label: + #pragma weak PR16705c + PR16705c(); +} + +// CHECK: declare extern_weak i32 @PR16705a() +// CHECK: declare extern_weak i32 @PR16705b() +// CHECK: declare extern_weak i32 @PR16705c() + ///////////// TODO: stuff that still doesn't work diff --git a/test/Parser/pragma-weak.c b/test/Parser/pragma-weak.c index 7e5740b483..fd47dd8696 100644 --- a/test/Parser/pragma-weak.c +++ b/test/Parser/pragma-weak.c @@ -15,3 +15,30 @@ extern int z; extern int a; /* expected-warning {{extra tokens at end of '#pragma weak'}}*/ #pragma weak a b /* expected-warning {{extra tokens at end of '#pragma weak'}}*/ #pragma weak a = x c + + +void pragma_is_not_a_statement(int x) +{ + int t; + + { + if (x) +#pragma weak t + else // expected-error {{expected expression}} +#pragma weak t + } + + switch (x) { + case 1: +#pragma weak t + } // expected-error {{expected statement}} + switch(x) { + default: +#pragma weak t + } // expected-error {{expected statement}} + +label: +#pragma weak t +} // expected-error {{expected statement}} + +