Module Name:    src
Committed By:   rillig
Date:           Mon May  3 05:24:45 UTC 2021

Modified Files:
        src/tests/usr.bin/xlint/lint1: gcc_typeof_after_statement.c
            gcc_typeof_after_statement.exp
        src/usr.bin/xlint/lint1: cgram.y

Log Message:
lint: fix parsing of __typeof__ after statement in ({ ... })

Since C99, declarations and statements can be freely mixed, and GCC
supported this even before 1999.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 \
    src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c \
    src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp
cvs rdiff -u -r1.225 -r1.226 src/usr.bin/xlint/lint1/cgram.y

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c
diff -u src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c:1.1 src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c:1.2
--- src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c:1.1	Thu Apr 22 22:43:26 2021
+++ src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c	Mon May  3 05:24:44 2021
@@ -1,9 +1,9 @@
-/*	$NetBSD: gcc_typeof_after_statement.c,v 1.1 2021/04/22 22:43:26 rillig Exp $	*/
+/*	$NetBSD: gcc_typeof_after_statement.c,v 1.2 2021/05/03 05:24:44 rillig Exp $	*/
 # 3 "gcc_typeof_after_statement.c"
 
 /*
- * As of 2021-04-23, lint cannot parse typeof(...) if there is a statement
- * before it.
+ * Before cgram.y 1.226 from 2021-05-03, lint could not parse typeof(...) if
+ * there was a statement before it.
  */
 
 void *
@@ -12,12 +12,11 @@ example(void **ptr)
 	return ({
 		if (*ptr != (void *)0)
 			ptr++;
-
-		/* FIXME: This is a legitimate use case. */
-		/* expect+1: syntax error '__typeof__' [249] */
 		__typeof__(*ptr) ret = *ptr;
-		/* expect+1: 'ret' undefined [99] */
 		ret;
-		/* expect+1: illegal combination of pointer (pointer to void) and integer (int) [183] */
 	});
 }
+
+/* Just to keep the .exp file. */
+/* expect+1: static function unused declared but not defined */
+static void unused(void);
Index: src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp
diff -u src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp:1.1 src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp:1.2
--- src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp:1.1	Thu Apr 22 22:43:26 2021
+++ src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp	Mon May  3 05:24:44 2021
@@ -1,3 +1 @@
-gcc_typeof_after_statement.c(18): error: syntax error '__typeof__' [249]
-gcc_typeof_after_statement.c(20): error: 'ret' undefined [99]
-gcc_typeof_after_statement.c(22): warning: illegal combination of pointer (pointer to void) and integer (int) [183]
+gcc_typeof_after_statement.c(22): warning: static function unused declared but not defined [290]

Index: src/usr.bin/xlint/lint1/cgram.y
diff -u src/usr.bin/xlint/lint1/cgram.y:1.225 src/usr.bin/xlint/lint1/cgram.y:1.226
--- src/usr.bin/xlint/lint1/cgram.y:1.225	Sun May  2 20:53:13 2021
+++ src/usr.bin/xlint/lint1/cgram.y	Mon May  3 05:24:44 2021
@@ -1,5 +1,5 @@
 %{
-/* $NetBSD: cgram.y,v 1.225 2021/05/02 20:53:13 rillig Exp $ */
+/* $NetBSD: cgram.y,v 1.226 2021/05/03 05:24:44 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: cgram.y,v 1.225 2021/05/02 20:53:13 rillig Exp $");
+__RCSID("$NetBSD: cgram.y,v 1.226 2021/05/03 05:24:44 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -123,7 +123,7 @@ anonymize(sym_t *s)
 }
 %}
 
-%expect 189
+%expect 181
 
 %union {
 	val_t	*y_val;
@@ -323,8 +323,8 @@ anonymize(sym_t *s)
 %type	<y_sym>		parameter_type_list
 %type	<y_sym>		parameter_declaration
 %type	<y_tnode>	expr
-%type	<y_tnode>	expr_statement_val
-%type	<y_tnode>	expr_statement_list
+%type	<y_tnode>	gcc_statement_expr_list
+%type	<y_tnode>	gcc_statement_expr_item
 %type	<y_tnode>	term
 %type	<y_tnode>	generic_expr
 %type	<y_tnode>	func_arg_list
@@ -1614,33 +1614,6 @@ expr_statement:
 	  }
 	;
 
-/*
- * The following two productions are used to implement
- * ({ [[decl-list] stmt-list] }).
- * XXX: This is not well tested.
- */
-expr_statement_val:
-	  expr T_SEMI {
-		/* XXX: We should really do that only on the last name */
-		if ($1->tn_op == NAME)
-			$1->tn_sym->s_used = true;
-		$$ = $1;
-		expr($1, false, false, false, false);
-		seen_fallthrough = false;
-	  }
-	| non_expr_statement {
-		$$ = expr_zalloc_tnode();
-		$$->tn_type = gettyp(VOID);
-	  }
-	;
-
-expr_statement_list:
-	  expr_statement_val
-	| expr_statement_list expr_statement_val {
-		$$ = $2;
-	  }
-	;
-
 selection_statement:		/* C99 6.8.4 */
 	  if_without_else {
 		save_warning_flags();
@@ -1831,20 +1804,6 @@ read_until_rparen:
 	  }
 	;
 
-declaration_list_opt:
-	  /* empty */
-	| declaration_list
-	;
-
-declaration_list:
-	  declaration {
-		clear_warning_flags();
-	  }
-	| declaration_list declaration {
-		clear_warning_flags();
-	  }
-	;
-
 constant_expr_list_opt:
 	  /* empty */
 	| constant_expr_list
@@ -1933,11 +1892,10 @@ term:
 			$2->tn_parenthesized = true;
 		$$ = $2;
 	  }
-	| T_LPAREN compound_statement_lbrace declaration_list_opt
-	    expr_statement_list {
+	| T_LPAREN compound_statement_lbrace gcc_statement_expr_list {
 		block_level--;
 		mem_block_level--;
-		begin_initialization(mktempsym(dup_type($4->tn_type)));
+		begin_initialization(mktempsym(dup_type($3->tn_type)));
 		mem_block_level++;
 		block_level++;
 		/* ({ }) is a GCC extension */
@@ -2043,6 +2001,37 @@ term:
 	  }
 	;
 
+/*
+ * The inner part of a GCC statement-expression of the form ({ ... }).
+ *
+ * https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
+ */
+gcc_statement_expr_list:
+	  gcc_statement_expr_item
+	| gcc_statement_expr_list gcc_statement_expr_item {
+		$$ = $2;
+	  }
+	;
+
+gcc_statement_expr_item:
+	  declaration {
+		clear_warning_flags();
+		$$ = NULL;
+	  }
+	| non_expr_statement {
+		$$ = expr_zalloc_tnode();
+		$$->tn_type = gettyp(VOID);
+	  }
+	| expr T_SEMI {
+		/* XXX: We should really do that only on the last name */
+		if ($1->tn_op == NAME)
+			$1->tn_sym->s_used = true;
+		$$ = $1;
+		expr($1, false, false, false, false);
+		seen_fallthrough = false;
+	}
+	;
+
 string:
 	  T_STRING {
 		$$ = $1;

Reply via email to