File tree 6 files changed +63
-7
lines changed
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
632
632
- ``__is_array `` and ``__is_bounded_array `` no longer return ``true `` for
633
633
zero-sized arrays. Fixes (#GH54705).
634
634
635
+ - Correctly reject declarations where a statement is required in C.
636
+ Fixes #GH92775
637
+
635
638
Bug Fixes to Compiler Builtins
636
639
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
637
640
Original file line number Diff line number Diff line change @@ -467,15 +467,18 @@ class Parser : public CodeCompletionHandler {
467
467
468
468
// / Flags describing a context in which we're parsing a statement.
469
469
enum class ParsedStmtContext {
470
+ // / This context permits declarations in language modes where declarations
471
+ // / are not statements.
472
+ AllowDeclarationsInC = 0x1 ,
470
473
// / This context permits standalone OpenMP directives.
471
- AllowStandaloneOpenMPDirectives = 0x1 ,
474
+ AllowStandaloneOpenMPDirectives = 0x2 ,
472
475
// / This context is at the top level of a GNU statement expression.
473
- InStmtExpr = 0x2 ,
476
+ InStmtExpr = 0x4 ,
474
477
475
478
// / The context of a regular substatement.
476
479
SubStmt = 0 ,
477
480
// / The context of a compound-statement.
478
- Compound = AllowStandaloneOpenMPDirectives,
481
+ Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives,
479
482
480
483
LLVM_MARK_AS_BITMASK_ENUM (InStmtExpr)
481
484
};
Original file line number Diff line number Diff line change @@ -239,7 +239,15 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
239
239
auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr (); };
240
240
bool AllAttrsAreStmtAttrs = llvm::all_of (CXX11Attrs, IsStmtAttr) &&
241
241
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)) ||
243
251
isDeclarationStatement ())) {
244
252
SourceLocation DeclStart = Tok.getLocation (), DeclEnd;
245
253
DeclGroupPtrTy Decl;
Original file line number Diff line number Diff line change 18
18
19
19
enum {a , b };
20
20
void different (void ) {
21
- if (sizeof (enum {b , a }) != sizeof (int ))
21
+ if (sizeof (enum {b , a }) != sizeof (int )) {
22
22
_Static_assert (a == 1 , "" );
23
+ }
23
24
/* In C89, the 'b' found here would have been from the enum declaration in
24
25
* the controlling expression of the selection statement, not from the global
25
26
* 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;
33
33
34
34
void func () {
35
35
// 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.
37
39
#pragma acc parallel
38
- int foo ;
40
+ int foo ; // expected-error {{expected expression}}
39
41
40
42
#pragma acc parallel
41
43
{
You can’t perform that action at this time.
0 commit comments