@@ -349,6 +349,12 @@ def __init__(self):
349349 # "goto exit" if there are any.
350350 self .return_conversion = []
351351
352+ # The C statements required to do some operations
353+ # after the end of parsing but before cleaning up.
354+ # These operations may be, for example, memory deallocations which
355+ # can only be done without any error happening during argument parsing.
356+ self .post_parsing = []
357+
352358 # The C statements required to clean up after the impl call.
353359 self .cleanup = []
354360
@@ -761,6 +767,7 @@ def parser_body(prototype, *fields, declarations=''):
761767 {modifications}
762768 {return_value} = {c_basename}_impl({impl_arguments});
763769 {return_conversion}
770+ {post_parsing}
764771
765772 {exit_label}
766773 {cleanup}
@@ -1405,6 +1412,7 @@ def render_function(self, clinic, f):
14051412 template_dict ['impl_parameters' ] = ", " .join (data .impl_parameters )
14061413 template_dict ['impl_arguments' ] = ", " .join (data .impl_arguments )
14071414 template_dict ['return_conversion' ] = format_escape ("" .join (data .return_conversion ).rstrip ())
1415+ template_dict ['post_parsing' ] = format_escape ("" .join (data .post_parsing ).rstrip ())
14081416 template_dict ['cleanup' ] = format_escape ("" .join (data .cleanup ))
14091417 template_dict ['return_value' ] = data .return_value
14101418
@@ -1429,6 +1437,7 @@ def render_function(self, clinic, f):
14291437 return_conversion = template_dict ['return_conversion' ],
14301438 initializers = template_dict ['initializers' ],
14311439 modifications = template_dict ['modifications' ],
1440+ post_parsing = template_dict ['post_parsing' ],
14321441 cleanup = template_dict ['cleanup' ],
14331442 )
14341443
@@ -2660,6 +2669,10 @@ def _render_non_self(self, parameter, data):
26602669 # parse_arguments
26612670 self .parse_argument (data .parse_arguments )
26622671
2672+ # post_parsing
2673+ if post_parsing := self .post_parsing ():
2674+ data .post_parsing .append ('/* Post parse cleanup for ' + name + ' */\n ' + post_parsing .rstrip () + '\n ' )
2675+
26632676 # cleanup
26642677 cleanup = self .cleanup ()
26652678 if cleanup :
@@ -2755,6 +2768,14 @@ def modify(self):
27552768 """
27562769 return ""
27572770
2771+ def post_parsing (self ):
2772+ """
2773+ The C statements required to do some operations after the end of parsing but before cleaning up.
2774+ Return a string containing this code indented at column 0.
2775+ If no operation is necessary, return an empty string.
2776+ """
2777+ return ""
2778+
27582779 def cleanup (self ):
27592780 """
27602781 The C statements required to clean up after this variable.
@@ -3351,10 +3372,10 @@ def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
33513372 if NoneType in accept and self .c_default == "Py_None" :
33523373 self .c_default = "NULL"
33533374
3354- def cleanup (self ):
3375+ def post_parsing (self ):
33553376 if self .encoding :
33563377 name = self .name
3357- return "" . join ([ "if (" , name , ") { \n PyMem_FREE(" , name , " );\n } \n " ])
3378+ return f" PyMem_FREE({ name } );\n "
33583379
33593380 def parse_arg (self , argname , displayname ):
33603381 if self .format_unit == 's' :
0 commit comments