diff --git a/i386-gen.c b/i386-gen.c
index 51a514ae..7e1e0f49 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -95,6 +95,7 @@ ST_DATA const int reg_classes[NB_REGS] = {
 static unsigned long func_sub_sp_offset;
 static int func_ret_sub;
 #ifdef CONFIG_TCC_BCHECK
+static addr_t func_bound_offset;
 static unsigned long func_bound_ind;
 #endif
 
@@ -401,10 +402,8 @@ ST_FUNC void gfunc_call(int nb_args)
     Sym *func_sym;
     
 #ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check) {
-        save_temp_local (nb_args);
+    if (tcc_state->do_bounds_check)
         gbound_args(nb_args);
-    }
 #endif
 
     args_size = 0;
@@ -486,10 +485,6 @@ ST_FUNC void gfunc_call(int nb_args)
     if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
         gadd_sp(args_size);
     vtop--;
-#ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check)
-        restore_temp_local ();
-#endif
 }
 
 #ifdef TCC_TARGET_PE
diff --git a/tcc.h b/tcc.h
index eb46bbda..9013e87d 100644
--- a/tcc.h
+++ b/tcc.h
@@ -474,9 +474,8 @@ struct SymAttr {
     dllexport   : 1,
     nodecorate  : 1,
     dllimport   : 1,
-    constructor : 1,
-    destructor  : 1,
-    unused      : 2;
+    addrtaken   : 1,
+    unused      : 3;
 };
 
 /* function attributes or temporary attributes for parsing */
@@ -620,6 +619,8 @@ typedef struct TokenString {
 typedef struct AttributeDef {
     struct SymAttr a;
     struct FuncAttr f;
+    unsigned short constructor:1;
+    unsigned short destructor:1;
     struct Section *section;
     Sym *cleanup_func;
     int alias_target; /* token */
@@ -1378,9 +1379,6 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi
 ST_DATA int func_var; /* true if current function is variadic */
 ST_DATA int func_vc;
 ST_DATA const char *funcname;
-#ifdef CONFIG_TCC_BCHECK
-ST_DATA addr_t func_bound_offset;
-#endif
 
 ST_FUNC void tcc_debug_start(TCCState *s1);
 ST_FUNC void tcc_debug_end(TCCState *s1);
@@ -1446,8 +1444,6 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty);
 #endif
 #ifdef CONFIG_TCC_BCHECK
 ST_FUNC void gbound_args(int nb_args);
-ST_FUNC void save_temp_local(int nb_args);
-ST_FUNC void restore_temp_local(void);
 #endif
 
 /* ------------ tccelf.c ------------ */
diff --git a/tccgen.c b/tccgen.c
index 946a9e21..21aaac63 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -111,16 +111,6 @@ ST_DATA struct temp_local_variable {
 	short align;
 } arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
 short nb_temp_local_vars;
-#ifdef CONFIG_TCC_BCHECK
-static short call_nesting;
-static char used_location[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
-static int nb_bound_local_param;
-struct {
-    unsigned long data_offset;
-    int v;
-} *bound_local_param;
-ST_DATA addr_t func_bound_offset;
-#endif
 
 static struct scope {
     struct scope *prev;
@@ -1502,11 +1492,7 @@ static int get_temp_local_var(int size,int align){
 	found=0;
 	for(i=0;i<nb_temp_local_vars;i++){
 		temp_var=&arr_temp_local_vars[i];
-		if(temp_var->size<size||align!=temp_var->align
-#ifdef CONFIG_TCC_BCHECK
-		   || (tcc_state->do_bounds_check && used_location[i])
-#endif
-		   ){
+		if(temp_var->size<size||align!=temp_var->align){
 			continue;
 		}
 		/*check if temp_var is free*/
@@ -1607,51 +1593,37 @@ ST_FUNC void gbound_args(int nb_args)
         }
 }
 
-ST_FUNC void save_temp_local(int nb_args)
+/* Add bounds for local symbols from S to E (via ->prev) */
+static void add_local_bounds(Sym *s, Sym *e)
 {
-    int i, j;
-
-    if (call_nesting++ == 0)
-        for (i = 1; i <= nb_args; ++i)
-            for (j = 0; j < nb_temp_local_vars; j++)
-                if (vtop[1 - i].c.i == arr_temp_local_vars[j].location) {
-                    used_location[j] = 1;
-                    break;
-                }
-}
-
-ST_FUNC void restore_temp_local()
-{
-    if (--call_nesting == 0)
-        memset (used_location, 0, sizeof (used_location));
-}
-
-static void add_bound_param(CType *type, int size, int v, int c)
-{
-    addr_t *bounds_ptr;
-    /* Add arrays/structs/unions because we always take address */
-    int taken = (type->t & VT_ARRAY)
-	        || (type->t & VT_BTYPE) == VT_STRUCT;
-
-    if (taken == 0) {
-	/* Add parameter to check */
-	nb_bound_local_param++;
-	bound_local_param =
-	    tcc_realloc (bound_local_param,
-			 nb_bound_local_param *
-			 sizeof (*bound_local_param));
-	bound_local_param[nb_bound_local_param-1].data_offset =
-	    lbounds_section->data_offset;
-	bound_local_param[nb_bound_local_param-1].v = v;
+    for (; s != e; s = s->prev) {
+        if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
+          continue;
+        /* Add arrays/structs/unions because we always take address */
+        if ((s->type.t & VT_ARRAY)
+            || (s->type.t & VT_BTYPE) == VT_STRUCT
+            || s->a.addrtaken) {
+            /* add local bound info */
+            int align, size = type_size(&s->type, &align);
+            addr_t *bounds_ptr = section_ptr_add(lbounds_section,
+                                                 2 * sizeof(addr_t));
+            bounds_ptr[0] = s->c;
+            bounds_ptr[1] = size;
+        }
     }
-    /* add local bound info */
-    bounds_ptr = section_ptr_add(lbounds_section,
-				 2 * sizeof(addr_t));
-    bounds_ptr[0] = c;
-    bounds_ptr[1] = taken ? size : ~size;
 }
 #endif
 
+/* Wrapper around sym_pop, that potentially also registers local bounds.  */
+static void pop_local_syms(Sym **ptop, Sym *b, int keep)
+{
+#ifdef CONFIG_TCC_BCHECK
+    if (!keep && tcc_state->do_bounds_check)
+        add_local_bounds(*ptop, b);
+#endif
+    sym_pop(ptop, b, keep);
+}
+
 static void incr_bf_adr(int o)
 {
     vtop->type = char_pointer_type;
@@ -3690,11 +3662,11 @@ redo:
 	}
        case TOK_CONSTRUCTOR1:
        case TOK_CONSTRUCTOR2:
-            ad->a.constructor = 1;
+            ad->constructor = 1;
             break;
        case TOK_DESTRUCTOR1:
        case TOK_DESTRUCTOR2:
-            ad->a.destructor = 1;
+            ad->destructor = 1;
             break;
         case TOK_SECTION1:
         case TOK_SECTION2:
@@ -5138,23 +5110,8 @@ ST_FUNC void unary(void)
         if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
             !(vtop->type.t & VT_ARRAY))
             test_lvalue();
-#ifdef CONFIG_TCC_BCHECK
-        if (tcc_state->do_bounds_check && vtop->sym) {
-	    int i;
-
-            /* Mark parameter as being used for address off */
-            for (i = 0; i < nb_bound_local_param; i++) {
-	        if (bound_local_param[i].v == vtop->sym->v) {
-		    addr_t *bounds_ptr =
-                        (addr_t *) (lbounds_section->data +
-                                    bound_local_param[i].data_offset);
-		    bounds_ptr[1] = ~bounds_ptr[1];
-		    bound_local_param[i].v = 0;
-		    break;
-		}
-	    }
-        }
-#endif
+        if (vtop->sym)
+          vtop->sym->a.addrtaken = 1;
         mk_pointer(&vtop->type);
         gaddrof();
         break;
@@ -6454,7 +6411,7 @@ void prev_scope(struct scope *o, int is_expr)
        tables, though.  sym_pop will do that.  */
 
     /* pop locally defined symbols */
-    sym_pop(&local_stack, o->lstk, is_expr);
+    pop_local_syms(&local_stack, o->lstk, is_expr);
 
     cur_scope = o->prev;
     --local_scope;
@@ -7426,17 +7383,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
     Sym *sym = NULL;
     int saved_nocode_wanted = nocode_wanted;
 #ifdef CONFIG_TCC_BCHECK
-    int bcheck;
+    int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
 #endif
 
     /* Always allocate static or global variables */
     if (v && (r & VT_VALMASK) == VT_CONST)
         nocode_wanted |= 0x80000000;
 
-#ifdef CONFIG_TCC_BCHECK
-    bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
-#endif
-
     flexible_array = NULL;
     if ((type->t & VT_BTYPE) == VT_STRUCT) {
         Sym *field = type->ref->next;
@@ -7508,17 +7461,15 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
         sec = NULL;
 #ifdef CONFIG_TCC_BCHECK
         if (bcheck && v) {
-            /* add padding between stack variables */
+            /* add padding between stack variables for bound checking */
             loc--;
         }
 #endif
         loc = (loc - size) & -align;
         addr = loc;
 #ifdef CONFIG_TCC_BCHECK
-        /* handles bounds */
         if (bcheck && v) {
-            add_bound_param (type, size, v, addr);
-            /* add padding between stack variables */
+            /* add padding between stack variables for bound checking */
             loc--;
         }
 #endif
@@ -7682,10 +7633,10 @@ static void gen_function(Sym *sym, AttributeDef *ad)
     /* NOTE: we patch the symbol size later */
     put_extern_sym(sym, cur_text_section, ind, 0);
 
-    if (ad && ad->a.constructor) {
+    if (ad && ad->constructor) {
         add_init_array (tcc_state, sym);
     }
-    if (ad && ad->a.destructor) {
+    if (ad && ad->destructor) {
         add_fini_array (tcc_state, sym);
     }
 
@@ -7698,56 +7649,16 @@ static void gen_function(Sym *sym, AttributeDef *ad)
     sym_push2(&local_stack, SYM_FIELD, 0, 0);
     local_scope = 1; /* for function parameters */
     gfunc_prolog(sym);
-#ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check
-        && sym->type.ref->f.func_type != FUNC_ELLIPSIS) {
-        Sym *fpar;
-
-        /* Add function arguments in case & is used */
-        for (fpar = sym->type.ref->next; fpar; fpar = fpar->next) {
-            Sym *fsym = sym_find (fpar->v & ~SYM_FIELD);
-
-            if (fsym && (fsym->r & VT_VALMASK) == VT_LOCAL) {
-                int align;
-                int size = type_size(&fsym->type, &align);
-
-                if (size > 0)
-                    add_bound_param (&fsym->type, size, fsym->v, fsym->c);
-            }
-        }
-    }
-#endif
     local_scope = 0;
     rsym = 0;
     clear_temp_local_var_list();
     block(0);
     gsym(rsym);
     nocode_wanted = 0;
-#ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check) {
-        addr_t o = func_bound_offset;
-
-        /* Remove parameters where address off is not used */
-        while (o != lbounds_section->data_offset) {
-            addr_t *bounds_ptr = (addr_t *) (lbounds_section->data + o);
-            if ((ssize_t) bounds_ptr[1] < 0) {
-                lbounds_section->data_offset -= 2 * sizeof (addr_t);
-                memmove(bounds_ptr, bounds_ptr + 2,
-                        lbounds_section->data_offset - o);
-            }
-            else {
-                o += 2 * sizeof (addr_t);
-            }
-        }
-        tcc_free (bound_local_param);
-        nb_bound_local_param = 0;
-        bound_local_param = NULL;
-    }
-#endif
     gfunc_epilog();
     cur_text_section->data_offset = ind;
     /* reset local stack */
-    sym_pop(&local_stack, NULL, 0);
+    pop_local_syms(&local_stack, NULL, 0);
     local_scope = 0;
     label_pop(&global_label_stack, NULL, 0);
     sym_pop(&all_cleanups, NULL, 0);
diff --git a/x86_64-gen.c b/x86_64-gen.c
index b4a546c2..439fd988 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -637,6 +637,7 @@ static void gcall_or_jmp(int is_jmp)
 }
 
 #if defined(CONFIG_TCC_BCHECK)
+static addr_t func_bound_offset;
 static unsigned long func_bound_ind;
 
 static void gen_bounds_call(int v)
@@ -783,10 +784,8 @@ void gfunc_call(int nb_args)
     int arg;
 
 #ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check) {
-        save_temp_local (nb_args);
+    if (tcc_state->do_bounds_check)
         gbound_args(nb_args);
-    }
 #endif
 
     args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
@@ -907,10 +906,6 @@ void gfunc_call(int nb_args)
 
     }
     vtop--;
-#ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check)
-        restore_temp_local ();
-#endif
 }
 
 
@@ -1276,10 +1271,8 @@ void gfunc_call(int nb_args)
     char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
 
 #ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check) {
-        save_temp_local (nb_args);
+    if (tcc_state->do_bounds_check)
         gbound_args(nb_args);
-    }
 #endif
 
     /* calculate the number of integer/float register arguments, remember
@@ -1460,10 +1453,6 @@ void gfunc_call(int nb_args)
     if (args_size)
         gadd_sp(args_size);
     vtop--;
-#ifdef CONFIG_TCC_BCHECK
-    if (tcc_state->do_bounds_check)
-        restore_temp_local ();
-#endif
 }
 
 #define FUNC_PROLOG_SIZE 11