File tree Expand file tree Collapse file tree 6 files changed +63
-7
lines changed
Expand file tree Collapse file tree 6 files changed +63
-7
lines changed Original file line number Diff line number Diff line change @@ -632,6 +632,9 @@ Bug Fixes in This Version
632632- ``__is_array `` and ``__is_bounded_array `` no longer return ``true `` for
633633 zero-sized arrays. Fixes (#GH54705).
634634
635+ - Correctly reject declarations where a statement is required in C.
636+ Fixes #GH92775
637+
635638Bug Fixes to Compiler Builtins
636639^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
637640
Original file line number Diff line number Diff line change @@ -467,15 +467,18 @@ class Parser : public CodeCompletionHandler {
467467
468468 // / Flags describing a context in which we're parsing a statement.
469469 enum class ParsedStmtContext {
470+ // / This context permits declarations in language modes where declarations
471+ // / are not statements.
472+ AllowDeclarationsInC = 0x1 ,
470473 // / This context permits standalone OpenMP directives.
471- AllowStandaloneOpenMPDirectives = 0x1 ,
474+ AllowStandaloneOpenMPDirectives = 0x2 ,
472475 // / This context is at the top level of a GNU statement expression.
473- InStmtExpr = 0x2 ,
476+ InStmtExpr = 0x4 ,
474477
475478 // / The context of a regular substatement.
476479 SubStmt = 0 ,
477480 // / The context of a compound-statement.
478- Compound = AllowStandaloneOpenMPDirectives,
481+ Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives,
479482
480483 LLVM_MARK_AS_BITMASK_ENUM (InStmtExpr)
481484 };
Original file line number Diff line number Diff line change @@ -239,7 +239,15 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
239239 auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr (); };
240240 bool AllAttrsAreStmtAttrs = llvm::all_of (CXX11Attrs, IsStmtAttr) &&
241241 llvm::all_of (GNUAttrs, IsStmtAttr);
242- if (((GNUAttributeLoc.isValid () && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
242+ // In C, the grammar production for statement (C23 6.8.1p1) does not allow
243+ // for declarations, which is different from C++ (C++23 [stmt.pre]p1). So
244+ // in C++, we always allow a declaration, but in C we need to check whether
245+ // we're in a statement context that allows declarations. e.g., in C, the
246+ // following is invalid: if (1) int x;
247+ if ((getLangOpts ().CPlusPlus || getLangOpts ().MicrosoftExt ||
248+ (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
249+ ParsedStmtContext ()) &&
250+ ((GNUAttributeLoc.isValid () && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
243251 isDeclarationStatement ())) {
244252 SourceLocation DeclStart = Tok.getLocation (), DeclEnd;
245253 DeclGroupPtrTy Decl;
Original file line number Diff line number Diff line change 1818
1919enum {a , b };
2020void different (void ) {
21- if (sizeof (enum {b , a }) != sizeof (int ))
21+ if (sizeof (enum {b , a }) != sizeof (int )) {
2222 _Static_assert (a == 1 , "" );
23+ }
2324 /* In C89, the 'b' found here would have been from the enum declaration in
2425 * the controlling expression of the selection statement, not from the global
2526 * declaration. In C99 and later, that enumeration is scoped to the 'if'
Original file line number Diff line number Diff line change 1+ // RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic
2+
3+ // Test that we can parse declarations at global scope.
4+ int v ;
5+
6+ void func (void ) {
7+ // Test that we can parse declarations within a compound statement.
8+ int a ;
9+ {
10+ int b ;
11+ }
12+
13+ int z = ({ // expected-warning {{use of GNU statement expression extension}}
14+ // Test that we can parse declarations within a GNU statement expression.
15+ int w = 12 ;
16+ w ;
17+ });
18+
19+ // Test that we diagnose declarations where a statement is required.
20+ // See GH92775.
21+ if (1 )
22+ int x ; // expected-error {{expected expression}}
23+ for (;;)
24+ int c ; // expected-error {{expected expression}}
25+
26+ label :
27+ int y ; // expected-warning {{label followed by a declaration is a C23 extension}}
28+
29+ // Test that lookup works as expected.
30+ (void )a ;
31+ (void )v ;
32+ (void )z ;
33+ (void )b ; // expected-error {{use of undeclared identifier 'b'}}
34+ (void )w ; // expected-error {{use of undeclared identifier 'w'}}
35+ (void )x ; // expected-error {{use of undeclared identifier 'x'}}
36+ (void )c ; // expected-error {{use of undeclared identifier 'c'}}
37+ (void )y ;
38+ }
39+
Original file line number Diff line number Diff line change @@ -33,9 +33,11 @@ int foo3;
3333
3434void func () {
3535 // FIXME: Should we disallow this on declarations, or consider this to be on
36- // the initialization?
36+ // the initialization? This is currently rejected in C because
37+ // Parser::ParseOpenACCDirectiveStmt() calls ParseStatement() and passes the
38+ // statement context as "SubStmt" which does not allow for a declaration in C.
3739#pragma acc parallel
38- int foo ;
40+ int foo ; // expected-error {{expected expression}}
3941
4042#pragma acc parallel
4143 {
You can’t perform that action at this time.
0 commit comments