def _build_handle_function(functions): """ Wraps the switch statement in a function definition """ case_statement = _build_case(functions) available_check = c_ast.If( c_ast.BinaryOp( '<', c_ast.FuncCall( c_ast.ID('mailbox_available'), c_ast.ExprList([c_ast.Constant('int', '2')]) ), c_ast.Constant('int', '4') ), c_ast.Return(None), None ) handle_decl = c_ast.FuncDecl( None, c_ast.TypeDecl('_handle_events', [], c_ast.IdentifierType(['void'])), ) command_decl = c_ast.Decl('command', [], [], [], c_ast.TypeDecl('command', [], c_ast.IdentifierType(['int'])), [], []) command_read = _generate_read('command') body = c_ast.Compound([available_check, command_decl, command_read, case_statement]) return c_ast.FuncDef(handle_decl, [], body)
def test_scalar_children(self): b1 = c_ast.BinaryOp( op='+', left=c_ast.Constant(type='int', value='6'), right=c_ast.ID(name='joe')) cv = self.ConstantVisitor() cv.visit(b1) self.assertEqual(cv.values, ['6']) b2 = c_ast.BinaryOp( op='*', left=c_ast.Constant(type='int', value='111'), right=b1) b3 = c_ast.BinaryOp( op='^', left=b2, right=b1) cv = self.ConstantVisitor() cv.visit(b3) self.assertEqual(cv.values, ['111', '6', '6'])
def visit_EnumeratorList(self, node): """Replace enumerator expressions with '...' stubs.""" for type, enum in node.children(): if enum.value is None: pass elif isinstance(enum.value, (c_ast.BinaryOp, c_ast.UnaryOp)): enum.value = c_ast.Constant('int', '...') elif hasattr(enum.value, 'type'): enum.value = c_ast.Constant(enum.value.type, '...')
def set_outdated(ast_tree, ext_index, bock_item_index, func_name): new_node = c_ast.FuncCall( c_ast.ID('set_outdated'), c_ast.ExprList([ c_ast.UnaryOp('&', c_ast.ID('global_log')), c_ast.Constant('string', '"' + func_name + '"'), c_ast.Constant('int', str(len(func_name))) ])) return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, "insert_before")
def visit_FuncDef(self, node): # Skip if no loop counters exist if self.loop_counter_size == 0: return # Create loop_counter declaration/initialization constants = [c_ast.Constant("int", '0') for i in range(self.loop_counter_size)] init_list = c_ast.InitList(constants) identifier_type = c_ast.IdentifierType(["int"]) type_decl = c_ast.TypeDecl("loop_counter", [], identifier_type) dim = c_ast.Constant("int", str(self.loop_counter_size)) array_decl = c_ast.ArrayDecl(type_decl, dim, []) decl = c_ast.Decl("loop_counter", [], [], [], array_decl, init_list, None) node.body.block_items.insert(0, decl) # Label for return values to goto start_label = c_ast.Label("print_loop_counter", c_ast.EmptyStatement()) # Start and end labels used for inserting preprocessor commands for #if DEBUG_EN end_label = c_ast.Label("print_loop_counter_end", c_ast.EmptyStatement()) # Write to file if self.write_to_file: stmt = c_ast.ID("write_array(loop_counter, %d)\n" % (self.loop_counter_size)) compound = c_ast.Compound([start_label, stmt, end_label]) # Print to stdout else: # Add printf to the end of function # Start of printing stmt_start = c_ast.ID("printf(\"loop counter = (\")") # For loop # int i; identifier_type = c_ast.IdentifierType(["int"]) type_decl = c_ast.TypeDecl("i", [], identifier_type) for_decl = c_ast.Decl("i", [], [], [], type_decl, [], None) # i = 0 init = c_ast.Assignment("=", c_ast.ID("i"), c_ast.Constant("int", '0')) # i < self.loop_counter_size cond = c_ast.BinaryOp("<", c_ast.ID("i"), c_ast.Constant("int", str(self.loop_counter_size))) # i++ next_stmt = c_ast.UnaryOp("p++", c_ast.ID("i")) # printf in for stmt = c_ast.ID("printf(\"%d, \", loop_counter[i])") # Cosntruct for loop stmt_for = c_ast.For(init, cond, next_stmt, stmt) # End of printing stmt_end = c_ast.ID("printf(\")\\n\")") # Put it all together body = c_ast.Compound([stmt_start, for_decl, stmt_for, stmt_end]) # Surround with labels compound = c_ast.Compound([start_label, body, end_label]) node.body.block_items.append(compound)
def insertTest(self,block,functionName,varVals,varTypes,timer,preOut,testId): #Fork call cFork=c_ast.Assignment( lvalue=c_ast.ID(name='child_pid'), op='=', rvalue=c_ast.FuncCall( c_ast.ID(name='fork'), args=None)) #Child ##stdout = freopen("out.txt", "w", stdout); if self.functype=='int': printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"') elif self.functype=='float' or self.functype=='double': printLeft=c_ast.Constant(type="char",value='"'+"%f" +'"') else: printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"') fileOut=c_ast.Constant(type="char",value='"'+preOut +'.' +testId+".out.txt" +'"') fileW=c_ast.Constant(type="char",value='"'+"w" +'"') fileStdout=c_ast.ID(name='stdout') expressList = [fileOut,fileW,fileStdout] freopenC = c_ast.FuncCall(c_ast.ID(name="freopen"),c_ast.ExprList(expressList)) outReassign=c_ast.Assignment( lvalue=fileStdout, op='=', rvalue=freopenC) ##mainfake() expressList = list(c_ast.Constant(type=varTypes[i],value=str(varVals[i])) for i in range(len(varVals))) funcCall = c_ast.FuncCall(c_ast.ID(name=functionName),c_ast.ExprList(expressList)) expressList = [printLeft,funcCall] funcCall = c_ast.FuncCall(c_ast.ID(name="printf"),c_ast.ExprList(expressList)) ##exit(0) funcCall2 = c_ast.FuncCall(c_ast.ID(name="exit"),c_ast.ExprList([c_ast.Constant(type='int',value='0')])) #Parent cAlarm=c_ast.FuncCall( c_ast.ID(name='alarm'),c_ast.ExprList([c_ast.Constant(type='int',value=str(timer))])) cWait=c_ast.FuncCall( c_ast.ID(name='wait'),c_ast.ExprList([c_ast.ID(name='0')])) #IFs if_false= c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='==',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([outReassign,funcCall,funcCall2]),iffalse=None) if_ini=c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='>',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([cAlarm,cWait]),iffalse=if_false) block.body.block_items.insert(1,if_ini) block.body.block_items.insert(1,cFork)
def check_value(ast_tree, ext_index, bock_item_index, var_name, func_name): Cast = c_ast.Cast( c_ast.Typename( None, [], c_ast.PtrDecl([], c_ast.TypeDecl(None, [], c_ast.IdentifierType(['void'])))), c_ast.ID(var_name)) func_call = c_ast.FuncCall( c_ast.ID('check_value'), c_ast.ExprList([ c_ast.UnaryOp('&', c_ast.ID('global_log')), Cast, c_ast.Constant('string', '"' + var_name + '"'), c_ast.Constant('string', '"' + func_name + '"'), c_ast.Constant('int', str(len(var_name))), c_ast.Constant('int', str(len(func_name))) ])) new_node = c_ast.If( c_ast.BinaryOp('==', func_call, c_ast.Constant('int', '0')), c_ast.Compound([ c_ast.FuncCall( c_ast.ID('printf'), c_ast.ExprList([ c_ast.Constant('string', '"%s\\n"'), c_ast.Constant('string', '"Attack Detected"') ])), c_ast.FuncCall(c_ast.ID('exit'), c_ast.ExprList([c_ast.Constant('int', '1')])) ]), None) return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, "insert_before")
def tests_list_children(self): c1 = c_ast.Constant(type='float', value='5.6') c2 = c_ast.Constant(type='char', value='t') b1 = c_ast.BinaryOp(op='+', left=c1, right=c2) b2 = c_ast.BinaryOp(op='-', left=b1, right=c2) comp = c_ast.Compound(block_items=[b1, b2, c1, c2]) cv = self.ConstantVisitor() cv.visit(comp) self.assertEqual(cv.values, ['5.6', 't', '5.6', 't', 't', '5.6', 't'])
def makePostDecAssignLog(coord, declname, underlying=None): type = getType(vars[-1][declname]) name = declname (file, line) = getLocation(coord) if underlying != None: name = underlying return c_ast.FuncCall( c_ast.ID('fprintf'), c_ast.ExprList([ c_ast.ID('stderr'), c_ast.Constant( 'string', '"{0}:{1}:assign({2},{3},{4})\\n"'.format( file, line, getTypeString(type), getTypeName(type), getTypeFormatString(type))), c_ast.BinaryOp('-', c_ast.ID(name), c_ast.Constant('int', '1')) ]))
def nested_for_loop(node, inner_loop_body, loop_iterator_base, rename_index=0): """ Recursively create nested for loops for copying a multi-dimensional array. """ if isinstance(node.type.type, c_ast.ArrayDecl): # Multi-dimensional array, recurse to generate inner loop for_loop_body = nested_for_loop(node.type, inner_loop_body, loop_iterator_base, rename_index + 1) else: # Single or last dimension of array for_loop_body = [inner_loop_body] # Declare iterator loop_iterator = c_ast.ID("%s_i%d" % (loop_iterator_base, rename_index)) loop_iterator_decl = c_ast.Decl( loop_iterator.name, [], [], [], c_ast.TypeDecl(loop_iterator.name, [], c_ast.IdentifierType(["int"])), None, None) # For loop array_size = node.type.dim for_loop = c_ast.For( c_ast.Assignment('=', loop_iterator, c_ast.Constant("int", "0")), c_ast.BinaryOp('<', loop_iterator, array_size), c_ast.UnaryOp('p++', loop_iterator), c_ast.Compound(for_loop_body)) return [loop_iterator_decl, for_loop]
def pre_argument(self, name): commands = [] commands.append( _generate_decl( name + '_int', c_ast.TypeDecl(name + '_int', [], c_ast.IdentifierType(['unsigned', 'int'])))) commands.append(_generate_read(name + '_int')) commands.append( c_ast.Assignment('|=', c_ast.ID(name + '_int'), c_ast.Constant('int', PTR_OFFSET))) commands.append( c_ast.Decl( name, [], [], [], c_ast.PtrDecl( [], c_ast.TypeDecl(name, [], c_ast.IdentifierType(['void'])), ), c_ast.Cast( c_ast.Typename( None, [], c_ast.PtrDecl([], c_ast.TypeDecl( None, [], c_ast.IdentifierType(['void'])))), c_ast.ID(name + '_int')), [])) return commands
def perm_add_mask(fn: ca.FuncDef, ast: ca.FileAST, indices: Indices, region: Region, random: Random) -> bool: """Add a mask of 0xFF[FFFFFFFFFFFFFF] to a random expression of integer type. In some cases this mask is optimized out but affects regalloc.""" typemap = build_typemap(ast) # Find expression to add the mask to cands: List[Expression] = get_block_expressions(fn.body, region) if not cands: return False expr = random.choice(cands) type: SimpleType = decayed_expr_type(expr, typemap) if not allowed_simple_type( type, typemap, ["int", "char", "long", "short", "signed", "unsigned"]): return False # Mask as if restricting the value to 8, 16, 32, or 64-bit width. # Sometimes use an unsigned mask like '0xFFu' masks: List[str] = ["0xFF", "0xFFFF", "0xFFFFFFFF", "0xFFFFFFFFFFFFFFFF"] mask = random.choice(masks) + random.choice(["", "u"]) visit_replace( fn.body, lambda n, _: ca.BinaryOp("&", expr, ca.Constant("int", mask)) if n is expr else None, ) return True
def on_preincrement_node(self, expr_node): # this is kinda hacky but w/e return self.on_assign_node( c_ast.Assignment('+=', expr_node, c_ast.Constant('int', '1'), coord=expr_node.coord))
def __for_loop(self, depth: int) -> c_ast.For: """ A helper function to construct a for loop corresponding to allocating one dimension of an array. Recursively calls itself to generate next levels or generates an initialisation line if it is the last level. Example: for(i_2 = 0; i_2 < N; i_2++) { ... } :param depth: :return: C-ast.For """ i = self.counter_prefix + str(depth) init = c_ast.DeclList([ c_ast.Decl(c_ast.ID(i), [], [], [], c_ast.TypeDecl(i, [], c_ast.IdentifierType(['int'])), c_ast.Constant('int', '0'), '') ]) cond = c_ast.BinaryOp('<', c_ast.ID(i), self.sizes[depth]) nxt = c_ast.Assignment('++', c_ast.ID(i), None) stmt = c_ast.Compound([]) if depth < len(self.sizes) - 1: stmt.block_items = [ self.__malloc_assign(depth + 1), self.__for_loop(depth + 1) ] else: stmt.block_items = [self.initialiser(depth + 1)] return c_ast.For(init, cond, nxt, stmt)
def make_klee_symbolic(variable_name, trackingName): arg1 = c_ast.UnaryOp(op='&', expr=c_ast.ID(variable_name)) arg2 = c_ast.UnaryOp(op='sizeof', expr = c_ast.Typename(name=None, quals =[], type= c_ast.TypeDecl(declname=None,quals=[], type=c_ast.IdentifierType(names=['int'])))) arg3 = c_ast.Constant(type='string', value='\"'+ trackingName +'\"') return c_ast.FuncCall(name=c_ast.ID(name = "klee_make_symbolic"), args=c_ast.ExprList(exprs=[arg1,arg2,arg3]))
def work(self, new_stuffs): for parent, child in self.target_location: if isinstance(child, c_ast.Return): new_stuffs_copy = new_stuffs[:-1] + [ c_ast.FuncCall( name=c_ast.ID(name="_RETTYPE"), args=c_ast.ExprList(exprs=[ child.expr, c_ast.Constant(type='int', value=str(len(new_stuffs) - 1)) ])) ] + new_stuffs[-1:] else: new_stuffs_copy = new_stuffs if isinstance(parent, c_ast.Compound): child_loc = parent.block_items.index(child) parent.block_items = parent.block_items[: child_loc] + new_stuffs_copy + parent.block_items[ child_loc + 1:] elif isinstance(parent, c_ast.If): if parent.iftrue == child: parent.iftrue = c_ast.Compound(block_items=new_stuffs_copy) elif parent.iffalse == child: parent.iffalse = c_ast.Compound( block_items=new_stuffs_copy) elif isinstance(parent, c_ast.While): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy) elif isinstance(parent, c_ast.For): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy) elif isinstance(parent, c_ast.DoWhile): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy) elif isinstance(parent, c_ast.Label): parent.stmt = c_ast.Compound(block_items=new_stuffs_copy)
def visit_Return(self, node): align, _ = _DistanceGenerator(self._types).visit(node.expr) if align != '0': raise ReturnDistanceNotZero(node.coord, _code_generator.visit(node.expr), align) # insert assert(__SHADOWDP_v_epsilon <= epsilon); epsilon, *_ = self._parameters if self._set_epsilon and self._set_epsilon.isdigit(): epsilon_node = c_ast.Constant(type='float', value=self._set_epsilon) elif self._set_epsilon and not self._set_epsilon.isdigit(): epsilon_node = c_ast.ID(name=self._set_epsilon) else: epsilon_node = c_ast.ID(epsilon) if self._set_goal: assert_node = c_ast.FuncCall( c_ast.ID(self._func_map['assert']), args=c_ast.ExprList( [c_ast.BinaryOp('<=', c_ast.ID(name='__SHADOWDP_v_epsilon'), c_ast.BinaryOp(op='*', left=epsilon_node, right=convert_to_ast(self._set_goal)))])) else: assert_node = c_ast.FuncCall(c_ast.ID(self._func_map['assert']), args=c_ast.ExprList([c_ast.BinaryOp('<=', c_ast.ID('__SHADOWDP_v_epsilon'), epsilon_node)])) self._parents[node].block_items.insert(self._parents[node].block_items.index(node), assert_node) self._inserted.add(assert_node) # because we have inserted a statement before Return statement while iterating, it will be a forever loop # add the current node to the set to not visit this same node again self._inserted.add(node)
def createMain(self): #Main Function #Declaration z1 = c_ast.TypeDecl('args',[],c_ast.IdentifierType(['int'])) args = c_ast.Decl('args',[],[],[],z1,None,None) z2= c_ast.PtrDecl([],c_ast.TypeDecl('argv',[],c_ast.IdentifierType(['char']))) z3=c_ast.ArrayDecl(z2,None,[]) argv = c_ast.Decl('argv',[],[],[],z3,None,None) params=c_ast.ParamList([args,argv]) mainDec=c_ast.FuncDecl(params,c_ast.TypeDecl('main',[],c_ast.IdentifierType(['int']))) # insertTest(functionName,varVals,varTypes) #Body ##Signal sigalrm=c_ast.ID(name="14") funcCast=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['void'])) paramCast=c_ast.ParamList([c_ast.Typename(name=None,quals=[],type=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['int'])))]) typeFunc=c_ast.PtrDecl(type=c_ast.FuncDecl(paramCast,funcCast),quals=[]) kchild=c_ast.Cast(to_type=c_ast.Typename(name=None, quals=[],type=typeFunc),expr=c_ast.ID(name="kill_child")) expressList = [sigalrm,kchild] signalStmt=c_ast.FuncCall(c_ast.ID(name="signal"),c_ast.ExprList(expressList)) ##Return returnStmt=c_ast.Return(c_ast.Constant(type="int",value="0")) comp=c_ast.Compound([signalStmt,returnStmt]) return c_ast.FuncDef(mainDec,None,comp)
def insertTest(self, block, functionName, varVals, varTypes): expressList = list( c_ast.Constant(type=varTypes[i], value=str(varVals[i])) for i in range(len(varVals))) funcCall = c_ast.FuncCall(c_ast.ID(name=functionName), c_ast.ExprList(expressList)) block.body.block_items.insert(0, funcCall)
def push_literal(lookup, stack, code, lit): name = gensym() const = c_ast.Constant(lit.type, lit.value) tdecl = c_ast.TypeDecl(name, [], c_ast.IdentifierType([lit.type])) decl = c_ast.Decl(name, [], [], [], tdecl, const, None) code.append(decl) stack.setdefault(lit.type, []).append(decl)
def __init__(self, linenum): self.linenum = linenum self.path = [] self.reached = False expressList = [c_ast.Constant(type='int', value='0')] self.funcCall = c_ast.FuncCall(c_ast.ID(name="assert"), c_ast.ExprList(expressList))
def __malloc(self, depth: int) -> c_ast.FuncCall: """ A helper function to generate the call of malloc function with proper arguments. Note that a constant of 2 is added to the number of allocated cells. This is meant to compensate minor errors in size estimation. Example: malloc((N + 2) * sizeof(int*)) :param depth: Which dimension of the array we want to allocate. Used to generate the argument of sizeof(). :return: c_ast.FuncCall """ size_expr = \ c_ast.BinaryOp( '+', self.sizes[depth], c_ast.Constant('int', '2') ) sizeof = \ c_ast.FuncCall( c_ast.ID('sizeof'), c_ast.ExprList([c_ast.ID(self.dtype.name + '*' * (len(self.sizes) - depth - 1))]) ) arg = c_ast.BinaryOp('*', size_expr, sizeof) return c_ast.FuncCall(c_ast.ID('malloc'), c_ast.ExprList([arg]))
def __init__(self, func, variable_declaration, structs): self.func = func self.variable_declaration = variable_declaration if variable_declaration.storage is not None: variable_declaration.storage.append("static") else: variable_declaration.storage = ["static"] if self.variable_declaration.init is None: if "extern" in variable_declaration.storage: variable_declaration.storage.remove("extern") if type(self.variable_declaration.type) is c_ast.ArrayDecl or \ any(x in structs for x in self.variable_declaration.type.type.names): self.variable_declaration.init = c_ast.InitList( exprs=[c_ast.Constant(type="int", value="0")]) else: self.variable_declaration.init = c_ast.Constant(type="int", value="0")
def astAssiDef(isr): larr = c_ast.ArrayRef( c_ast.ID('deferral'), c_ast.Constant( 'int', str(int(isr) - 1))) # the second param of Constant is String rarr = c_ast.UnaryOp('&', c_ast.ID('deferral_' + isr)) assi = c_ast.Assignment('=', larr, rarr) return assi
def astScheDefer(id): schedef = c_ast.FuncCall(c_ast.ID('scheduler_deferral'), c_ast.Constant('int', id)) # astseq.ext[166].body.block_items[6].args = c_ast.Constant('int', id) # schedef=astseq.ext[166].body.block_items[6] # print ("\033[1;5;32;45;1mFuncCall scheduler_deferral\033[0m") # schedef.show() return schedef
def replace_enum_values(self, enum_object, storage_lvalue=None): constants = [] for enum in enum_object.members.enumerators: constants.append( c_ast.Constant(type="int", value=str(enum.value.value))) init_list = c_ast.InitList(exprs=constants) init_count = c_ast.Constant(type="int", value=str(len(constants))) values = None values_len = None for node in self.get_nodes(self.ast): if type(node) == c_ast.Decl: if node.name == "values": values = node if node.name == "values_len": values_len = node if node.name == "idx": idx = node if type(node) == c_ast.ID: if node.name == "values_len": values_len_id = node if node.name == "values": values_id = node if node.name == "idx": idx_id = node if type(node) == c_ast.Assignment: if node.lvalue.expr.name == "storage": storage_expr = node values.init = init_list new_values_name = values.name + str(nesting_context.values_count) values.name = new_values_name change_declname(values, new_values_name) values_id.name = new_values_name values_len.init = init_count new_values_len_name = values_len.name + str( nesting_context.values_count) values_len.name = new_values_len_name change_declname(values_len, new_values_len_name) values_len_id.name = new_values_len_name new_idx_name = idx.name + str(nesting_context.values_count) idx.name = new_values_name change_declname(idx, new_idx_name) idx_id.name = new_idx_name if storage_lvalue: storage_expr.lvalue = storage_lvalue nesting_context.values_count += 1
def MakePrintfCall(fmt_str, arg_node: Optional[c_ast.Node], use_specialized_printf): if use_specialized_printf: if arg_node: args = [CONST_STDOUT, arg_node] name = GetSingleArgPrintForFormat(fmt_str) else: args = [ CONST_STDOUT, c_ast.Constant("string", '"' + fmt_str + '"') ] name = "write_s" else: args = [c_ast.Constant("string", '"' + fmt_str + '"')] if arg_node: args.append(arg_node) name = "printf" return c_ast.FuncCall(c_ast.ID(name), c_ast.ExprList(args))
def replaceByPrint(self, ast): expressList = [ c_ast.Constant(type='string', value='"[[REACHED]]"') ] ifexpress = c_ast.Assignment(op="=", lvalue=c_ast.ID(name="inst_flag"), rvalue=c_ast.Constant(type='int', value='1')) self.funcCall.name = c_ast.ID(name="perror") self.funcCall.args = c_ast.ExprList(expressList) if_all = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='inst_flag'), op='==', right=c_ast.Constant(type='int', value='0')), c_ast.Compound([self.funcCall, ifexpress]), iffalse=None) for position, inst_block in enumerate(self.inst_block): inst_block[self.inst_pos[position]] = if_all
def visit_FuncDef(self, node): label = c_ast.Label("predict_exec_time", c_ast.EmptyStatement()) decl = c_ast.Decl("exec_time", None, None, None, c_ast.TypeDecl("exec_time", None, c_ast.IdentifierType(["float"])), None, None) assignment = c_ast.Assignment('=', c_ast.ID("exec_time"), c_ast.Constant("int", 0)) ret = c_ast.Return(c_ast.ID("exec_time")) compound = c_ast.Compound([label, decl, assignment, ret]) node.body.block_items.append(compound)
def visit_ArrayDecl(self, node): # autopxd doesn't support array with an expression as size, but in: # typedef struct {uint8_t _dont_touch_that[GODOT_VECTOR3_SIZE];} godot_vector3; # `GODOT_VECTOR3_SIZE` gets resolved as `sizeof(void*)` :( if node.type.declname == "_dont_touch_that": # Of course the 0 size is wrong, but it's not an issue given # we don't touch this array in Cython code (hence the name ^^) node.dim = c_ast.Constant(type="int", value="0") return super().visit_ArrayDecl(node)