diff --git a/src/kernel_internals/parsing/cparser.mly b/src/kernel_internals/parsing/cparser.mly
index a7f848039f9ec28bbbc55424809ccf607cfe8e5b..b2e110ae8ab0f087a46c2092f373edbfb38e4923 100644
--- a/src/kernel_internals/parsing/cparser.mly
+++ b/src/kernel_internals/parsing/cparser.mly
@@ -866,10 +866,9 @@ bracket_comma_expression:
   LBRACKET comma_expression RBRACKET                   { $2 }
 ;
 
-
 /*** statements ***/
-block: /* ISO 6.8.2 */
-    block_begin local_labels block_attrs block_content RBRACE
+generic_block(content):
+    block_begin local_labels block_attrs content RBRACE
       {
        { blabels = $2;
          battrs = $3;
@@ -877,6 +876,13 @@ block: /* ISO 6.8.2 */
        $1, $5
       }
 ;
+
+block: /* ISO 6.8.2 */
+       generic_block(block_content) { $1 }
+
+main_block:
+  generic_block(main_block_content) { $1 }
+
 block_begin:
     LBRACE  { !Lexerhack.push_context (); $1 }
 ;
@@ -889,6 +895,17 @@ block_attrs:
 
 block_content: block_element_list { !Lexerhack.pop_context(); $1 }
 
+/* for the main block of a function, we must pop
+   _two_ contexts: the one of the block itself, and the one
+   introduced for the definition itself (which includes the
+   parameters and the function name)
+*/
+main_block_content: block_element_list {
+    !Lexerhack.pop_context();
+    !Lexerhack.pop_context();
+    $1
+}
+
 /* statements and declarations in a block, in any order (for C99 support) */
 block_element_list:
 |   annot_list_opt                                      { $1 }
@@ -1502,37 +1519,35 @@ abs_direct_decl_opt:
     abs_direct_decl                 { $1 }
 |   /* empty */                     { JUSTBASE }
 ;
+
+/* NB: we can't use SPEC? below for obscure shift/reduce conflicts.
+   Feel free to investigate more.
+*/
 function_def:  /* (* ISO 6.9.1 *) */
-  SPEC function_def_start block
+ s=SPEC fn=function_def_start b=main_block
           {
-            let (loc, specs, decl) = $2 in
+            let (loc, specs, decl) = fn in
             let spec_loc =
-              let loc = fst $1 in
+              let loc = fst s in
               Option.map
                 (fun (loc', spec) -> spec, (loc, loc'))
-                (Logic_lexer.spec $1)
+                (Logic_lexer.spec s)
             in
             currentFunctionName := "<__FUNCTION__ used outside any functions>";
-            !Lexerhack.pop_context (); (* The context pushed by
-                                    * announceFunctionName *)
-            doFunctionDef spec_loc loc (trd3 $3) specs decl (fst3 $3)
-          }
-|  function_def_start block
-          { let (loc, specs, decl) = $1 in
-            currentFunctionName := "<__FUNCTION__ used outside any functions>";
-            !Lexerhack.pop_context (); (* The context pushed by
-                                    * announceFunctionName *)
-            (*OCAMLYACC BUG??? Format.printf "%a@." d_cabsloc (trd3 $2);*)
-            doFunctionDef None ((*handleLoc*) loc) (trd3 $2) specs decl (fst3 $2)
+            doFunctionDef spec_loc loc (trd3 b) specs decl (fst3 b)
           }
-
+| fn = function_def_start b = main_block
+  { let (loc, specs, decl) = fn in
+    currentFunctionName:= "<__FUNCTION__ used outside any functions>";
+    doFunctionDef None loc (trd3 b) specs decl (fst3 b)
+  }
+;
 
 function_def_start:  /* (* ISO 6.9.1 *) */
   decl_spec_list declarator
                             { announceFunctionName $2;
                               (fourth4 $2, fst $1, $2)
                             }
-
 /* (* Old-style function prototype *) */
 | decl_spec_list old_proto_decl
                             { announceFunctionName $2;