| @@ -300,6 +300,29 @@ static void weaken_symbol(Sym *sym) · 299 unmodified lines |
| 300 | 300 | } |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | +static void apply_visibility(Sym *sym, CType *type) |
| 304 | +{ |
| 305 | + int vis = sym->type.t & VT_VIS_MASK; |
| 306 | + int vis2 = type->t & VT_VIS_MASK; |
| 307 | + if (vis == (STV_DEFAULT << VT_VIS_SHIFT)) |
| 308 | + vis = vis2; |
| 309 | + else if (vis2 == (STV_DEFAULT << VT_VIS_SHIFT)) |
| 310 | + ; |
| 311 | + else |
| 312 | + vis = (vis < vis2) ? vis : vis2; |
| 313 | + sym->type.t &= ~VT_VIS_MASK; |
| 314 | + sym->type.t |= vis; |
| 315 | + |
| 316 | + if (sym->c > 0) { |
| 317 | + int esym_type; |
| 318 | + ElfW(Sym) *esym; |
| 319 | + |
| 320 | + esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; |
| 321 | + vis >>= VT_VIS_SHIFT; |
| 322 | + esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis; |
| 323 | + } |
| 324 | +} |
| 325 | + |
| 303 | 326 | /* ------------------------------------------------------------------------- */ |
| 304 | 327 | |
| 305 | 328 | ST_FUNC void swap(int *p, int *q) |
| @@ -436,6 +459,13 @@ static Sym *external_sym(int v, CType *type, int r, char *asm_label) · 130 unmodified lines |
| 436 | 459 | tcc_error("incompatible types for redefinition of '%s'", |
| 437 | 460 | get_tok_str(v, NULL)); |
| 438 | 461 | } |
| 462 | + /* Merge some storage attributes. */ |
| 463 | + if (type->t & VT_WEAK) |
| 464 | + weaken_symbol(s); |
| 465 | + |
| 466 | + if (type->t & VT_VIS_MASK) |
| 467 | + apply_visibility(s, type); |
| 468 | + |
| 439 | 469 | return s; |
| 440 | 470 | } |
| 441 | 471 | |
| @@ -2662,6 +2692,24 @@ static void parse_attribute(AttributeDef *ad) · 2220 unmodified lines |
| 2662 | 2692 | next(); |
| 2663 | 2693 | skip(')'); |
| 2664 | 2694 | break; |
| 2695 | + case TOK_VISIBILITY1: |
| 2696 | + case TOK_VISIBILITY2: |
| 2697 | + skip('('); |
| 2698 | + if (tok != TOK_STR) |
| 2699 | + expect("visibility(\"default|hidden|internal|protected\")"); |
| 2700 | + if (!strcmp (tokc.cstr->data, "default")) |
| 2701 | + ad->a.visibility = STV_DEFAULT; |
| 2702 | + else if (!strcmp (tokc.cstr->data, "hidden")) |
| 2703 | + ad->a.visibility = STV_HIDDEN; |
| 2704 | + else if (!strcmp (tokc.cstr->data, "internal")) |
| 2705 | + ad->a.visibility = STV_INTERNAL; |
| 2706 | + else if (!strcmp (tokc.cstr->data, "protected")) |
| 2707 | + ad->a.visibility = STV_PROTECTED; |
| 2708 | + else |
| 2709 | + expect("visibility(\"default|hidden|internal|protected\")"); |
| 2710 | + next(); |
| 2711 | + skip(')'); |
| 2712 | + break; |
| 2665 | 2713 | case TOK_ALIGNED1: |
| 2666 | 2714 | case TOK_ALIGNED2: |
| 2667 | 2715 | if (tok == '(') { |
| @@ -5656,6 +5704,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2988 unmodified lines |
| 5656 | 5704 | /* patch symbol weakness */ |
| 5657 | 5705 | if (type->t & VT_WEAK) |
| 5658 | 5706 | weaken_symbol(sym); |
| 5707 | + apply_visibility(sym, type); |
| 5659 | 5708 | #ifdef CONFIG_TCC_BCHECK |
| 5660 | 5709 | /* handles bounds now because the symbol must be defined |
| 5661 | 5710 | before for the relocation */ |
| @@ -5801,6 +5850,7 @@ static void gen_function(Sym *sym) · 139 unmodified lines |
| 5801 | 5850 | /* patch symbol weakness (this definition overrules any prototype) */ |
| 5802 | 5851 | if (sym->type.t & VT_WEAK) |
| 5803 | 5852 | weaken_symbol(sym); |
| 5853 | + apply_visibility(sym, &sym->type); |
| 5804 | 5854 | if (tcc_state->do_debug) { |
| 5805 | 5855 | put_stabn(N_FUN, 0, 0, ind - func_ind); |
| 5806 | 5856 | } |
| @@ -5934,6 +5984,8 @@ static int decl0(int l, int is_for_loop_init) · 127 unmodified lines |
| 5934 | 5984 | if (ad.a.func_export) |
| 5935 | 5985 | type.t |= VT_EXPORT; |
| 5936 | 5986 | #endif |
| 5987 | + type.t |= ad.a.visibility << VT_VIS_SHIFT; |
| 5988 | + |
| 5937 | 5989 | if (tok == '{') { |
| 5938 | 5990 | if (l == VT_LOCAL) |
| 5939 | 5991 | tcc_error("cannot use local functions"); |
| @@ -5973,6 +6025,11 @@ static int decl0(int l, int is_for_loop_init) · 33 unmodified lines |
| 5973 | 6025 | if (sym->type.t & VT_STATIC) |
| 5974 | 6026 | type.t = (type.t & ~VT_EXTERN) | VT_STATIC; |
| 5975 | 6027 | |
| 6028 | + /* If the definition has no visibility use the |
| 6029 | + one from prototype. */ |
| 6030 | + if (! (type.t & VT_VIS_MASK)) |
| 6031 | + type.t |= sym->type.t & VT_VIS_MASK; |
| 6032 | + |
| 5976 | 6033 | if (!is_compatible_types(&sym->type, &type)) { |
| 5977 | 6034 | func_error1: |
| 5978 | 6035 | tcc_error("incompatible types for redefinition of '%s'", |
| @@ -6063,9 +6120,6 @@ static int decl0(int l, int is_for_loop_init) · 84 unmodified lines |
| 6063 | 6120 | extern */ |
| 6064 | 6121 | sym = external_sym(v, &type, r, asm_label); |
| 6065 | 6122 | |
| 6066 | | − if (type.t & VT_WEAK) |
| 6067 | | − weaken_symbol(sym); |
| 6068 | | − |
| 6069 | 6123 | if (ad.alias_target) { |
| 6070 | 6124 | Section tsec; |
| 6071 | 6125 | Elf32_Sym *esym; |