@@ -348,6 +348,12 @@ def __init__(self):
348348 # "goto exit" if there are any.
349349 self .return_conversion = []
350350
351+ # The C statements required to do some operations
352+ # after the end of parsing but before cleaning up.
353+ # These operations may be, for example, memory deallocations which
354+ # can only be done without any error happening during argument parsing.
355+ self .post_parsing = []
356+
351357 # The C statements required to clean up after the impl call.
352358 self .cleanup = []
353359
@@ -820,6 +826,7 @@ def parser_body(prototype, *fields, declarations=''):
820826 {modifications}
821827 {return_value} = {c_basename}_impl({impl_arguments});
822828 {return_conversion}
829+ {post_parsing}
823830
824831 {exit_label}
825832 {cleanup}
@@ -1460,6 +1467,7 @@ def render_function(self, clinic, f):
14601467 template_dict ['impl_parameters' ] = ", " .join (data .impl_parameters )
14611468 template_dict ['impl_arguments' ] = ", " .join (data .impl_arguments )
14621469 template_dict ['return_conversion' ] = format_escape ("" .join (data .return_conversion ).rstrip ())
1470+ template_dict ['post_parsing' ] = format_escape ("" .join (data .post_parsing ).rstrip ())
14631471 template_dict ['cleanup' ] = format_escape ("" .join (data .cleanup ))
14641472 template_dict ['return_value' ] = data .return_value
14651473
@@ -1484,6 +1492,7 @@ def render_function(self, clinic, f):
14841492 return_conversion = template_dict ['return_conversion' ],
14851493 initializers = template_dict ['initializers' ],
14861494 modifications = template_dict ['modifications' ],
1495+ post_parsing = template_dict ['post_parsing' ],
14871496 cleanup = template_dict ['cleanup' ],
14881497 )
14891498
@@ -2725,6 +2734,10 @@ def _render_non_self(self, parameter, data):
27252734 # parse_arguments
27262735 self .parse_argument (data .parse_arguments )
27272736
2737+ # post_parsing
2738+ if post_parsing := self .post_parsing ():
2739+ data .post_parsing .append ('/* Post parse cleanup for ' + name + ' */\n ' + post_parsing .rstrip () + '\n ' )
2740+
27282741 # cleanup
27292742 cleanup = self .cleanup ()
27302743 if cleanup :
@@ -2820,6 +2833,14 @@ def modify(self):
28202833 """
28212834 return ""
28222835
2836+ def post_parsing (self ):
2837+ """
2838+ The C statements required to do some operations after the end of parsing but before cleaning up.
2839+ Return a string containing this code indented at column 0.
2840+ If no operation is necessary, return an empty string.
2841+ """
2842+ return ""
2843+
28232844 def cleanup (self ):
28242845 """
28252846 The C statements required to clean up after this variable.
@@ -3416,10 +3437,10 @@ def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
34163437 if NoneType in accept and self .c_default == "Py_None" :
34173438 self .c_default = "NULL"
34183439
3419- def cleanup (self ):
3440+ def post_parsing (self ):
34203441 if self .encoding :
34213442 name = self .name
3422- return "" . join ([ "if (" , name , ") { \n PyMem_FREE(" , name , " );\n } \n " ])
3443+ return f" PyMem_FREE({ name } );\n "
34233444
34243445 def parse_arg (self , argname , displayname ):
34253446 if self .format_unit == 's' :
0 commit comments