| @@ -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 | ST_FUNC void swap(int *p, int *q) | 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 | tcc_error("incompatible types for redefinition of '%s'", | 459 | tcc_error("incompatible types for redefinition of '%s'", |
| 437 | get_tok_str(v, NULL)); | 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 | return s; | 469 | return s; |
| 440 | } | 470 | } |
| 441 | | 471 | |
| @@ -2662,6 +2692,24 @@ static void parse_attribute(AttributeDef *ad) · 2220 unmodified lines |
| 2662 | next(); | 2692 | next(); |
| 2663 | skip(')'); | 2693 | skip(')'); |
| 2664 | break; | 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 | case TOK_ALIGNED1: | 2713 | case TOK_ALIGNED1: |
| 2666 | case TOK_ALIGNED2: | 2714 | case TOK_ALIGNED2: |
| 2667 | if (tok == '(') { | 2715 | if (tok == '(') { |
| @@ -5656,6 +5704,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2988 unmodified lines |
| 5656 | /* patch symbol weakness */ | 5704 | /* patch symbol weakness */ |
| 5657 | if (type->t & VT_WEAK) | 5705 | if (type->t & VT_WEAK) |
| 5658 | weaken_symbol(sym); | 5706 | weaken_symbol(sym); |
| | 5707 | apply_visibility(sym, type); |
| 5659 | #ifdef CONFIG_TCC_BCHECK | 5708 | #ifdef CONFIG_TCC_BCHECK |
| 5660 | /* handles bounds now because the symbol must be defined | 5709 | /* handles bounds now because the symbol must be defined |
| 5661 | before for the relocation */ | 5710 | before for the relocation */ |
| @@ -5801,6 +5850,7 @@ static void gen_function(Sym *sym) · 139 unmodified lines |
| 5801 | /* patch symbol weakness (this definition overrules any prototype) */ | 5850 | /* patch symbol weakness (this definition overrules any prototype) */ |
| 5802 | if (sym->type.t & VT_WEAK) | 5851 | if (sym->type.t & VT_WEAK) |
| 5803 | weaken_symbol(sym); | 5852 | weaken_symbol(sym); |
| | 5853 | apply_visibility(sym, &sym->type); |
| 5804 | if (tcc_state->do_debug) { | 5854 | if (tcc_state->do_debug) { |
| 5805 | put_stabn(N_FUN, 0, 0, ind - func_ind); | 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 | if (ad.a.func_export) | 5984 | if (ad.a.func_export) |
| 5935 | type.t |= VT_EXPORT; | 5985 | type.t |= VT_EXPORT; |
| 5936 | #endif | 5986 | #endif |
| | 5987 | type.t |= ad.a.visibility << VT_VIS_SHIFT; |
| | 5988 | |
| 5937 | if (tok == '{') { | 5989 | if (tok == '{') { |
| 5938 | if (l == VT_LOCAL) | 5990 | if (l == VT_LOCAL) |
| 5939 | tcc_error("cannot use local functions"); | 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 | if (sym->type.t & VT_STATIC) | 6025 | if (sym->type.t & VT_STATIC) |
| 5974 | type.t = (type.t & ~VT_EXTERN) | VT_STATIC; | 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 | if (!is_compatible_types(&sym->type, &type)) { | 6033 | if (!is_compatible_types(&sym->type, &type)) { |
| 5977 | func_error1: | 6034 | func_error1: |
| 5978 | tcc_error("incompatible types for redefinition of '%s'", | 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 | extern */ | 6120 | extern */ |
| 6064 | sym = external_sym(v, &type, r, asm_label); | 6121 | sym = external_sym(v, &type, r, asm_label); |
| 6065 | | 6122 | |
| 6066 | if (type.t & VT_WEAK) | | |
| 6067 | weaken_symbol(sym); | | |
| 6068 | | | |
| 6069 | if (ad.alias_target) { | 6123 | if (ad.alias_target) { |
| 6070 | Section tsec; | 6124 | Section tsec; |
| 6071 | Elf32_Sym *esym; | 6125 | Elf32_Sym *esym; |