History

Fix more attribute placements

when parsing the type in this cast: (int (__attribute__(X) *)(int))foo we ignored the attribute, which matters if it's e.g. a 'stdcall' attribute on the function pointer. Only this particular placement was misparsed. Putting the attribute after the '*' or outside the inner parens worked. This idiom seems to be used on SQLite, perhaps this fixes a compilation problem on win32 with that.

Michael Matz committed 7 years ago

Commit 3e007191 parent 325241c3 files · +79 −25Browse files

Unified · Split

3 files
  1. tccgen.c +53 −24
  2. tccpe.c +1 −1
  3. tests/tests2/82_attribs_position.c +25 −0
tccgen.c+53−24
@@ -846,6 +846,52 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r) · 845 unmodified lines
846846 return s;
847847 }
848848
849+/* Merge symbol attributes. */
850+static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1)
851+{
852+ if (sa1->aligned && !sa->aligned)
853+ sa->aligned = sa1->aligned;
854+ sa->packed |= sa1->packed;
855+ sa->weak |= sa1->weak;
856+ if (sa1->visibility != STV_DEFAULT) {
857+ int vis = sa->visibility;
858+ if (vis == STV_DEFAULT
859+ || vis > sa1->visibility)
860+ vis = sa1->visibility;
861+ sa->visibility = vis;
862+ }
863+ sa->dllexport |= sa1->dllexport;
864+ sa->nodecorate |= sa1->nodecorate;
865+ sa->dllimport |= sa1->dllimport;
866+}
867+
868+/* Merge function attributes. */
869+static void merge_funcattr(struct FuncAttr *fa, struct FuncAttr *fa1)
870+{
871+ if (fa1->func_call && !fa->func_call)
872+ fa->func_call = fa1->func_call;
873+ if (fa1->func_type && !fa->func_type)
874+ fa->func_type = fa1->func_type;
875+ if (fa1->func_args && !fa->func_args)
876+ fa->func_args = fa1->func_args;
877+}
878+
879+/* Merge attributes. */
880+static void merge_attr(AttributeDef *ad, AttributeDef *ad1)
881+{
882+ merge_symattr(&ad->a, &ad1->a);
883+ merge_funcattr(&ad->f, &ad1->f);
884+
885+ if (ad1->section)
886+ ad->section = ad1->section;
887+ if (ad1->alias_target)
888+ ad->alias_target = ad1->alias_target;
889+ if (ad1->asm_label)
890+ ad->asm_label = ad1->asm_label;
891+ if (ad1->attr_mode)
892+ ad->attr_mode = ad1->attr_mode;
893+}
894+
849895 /* Merge some type attributes. */
850896 static void patch_type(Sym *sym, CType *type)
851897 {
@@ -905,20 +951,8 @@ static void patch_storage(Sym *sym, AttributeDef *ad, CType *type) · 53 unmodified lines
905951 if (sym->a.dllimport != ad->a.dllimport)
906952 tcc_error("incompatible dll linkage for redefinition of '%s'",
907953 get_tok_str(sym->v, NULL));
908− sym->a.dllexport |= ad->a.dllexport;
909954 #endif
910− sym->a.weak |= ad->a.weak;
911− if (ad->a.visibility) {
912− int vis = sym->a.visibility;
913− int vis2 = ad->a.visibility;
914− if (vis == STV_DEFAULT)
915− vis = vis2;
916− else if (vis2 != STV_DEFAULT)
917− vis = (vis < vis2) ? vis : vis2;
918− sym->a.visibility = vis;
919− }
920− if (ad->a.aligned)
921− sym->a.aligned = ad->a.aligned;
955+ merge_symattr(&sym->a, &ad->a);
922956 if (ad->asm_label)
923957 sym->asm_label = ad->asm_label;
924958 update_storage(sym);
@@ -4000,14 +4034,8 @@ do_decl: · 3075 unmodified lines
40004034
40014035 static void sym_to_attr(AttributeDef *ad, Sym *s)
40024036 {
4003− if (s->a.aligned && 0 == ad->a.aligned)
4004− ad->a.aligned = s->a.aligned;
4005− if (s->f.func_call && 0 == ad->f.func_call)
4006− ad->f.func_call = s->f.func_call;
4007− if (s->f.func_type && 0 == ad->f.func_type)
4008− ad->f.func_type = s->f.func_type;
4009− if (s->a.packed)
4010− ad->a.packed = 1;
4037+ merge_symattr(&ad->a, &s->a);
4038+ merge_funcattr(&ad->f, &s->f);
40114039 }
40124040
40134041 /* Add type qualifiers to a type. If the type is an array then the qualifiers
@@ -4294,9 +4322,10 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) · 280 unmodified lines
42944322 l = 0;
42954323 else if (parse_btype(&pt, &ad1))
42964324 l = FUNC_NEW;
4297− else if (td)
4298− return 0;
4299− else
4325+ else if (td) {
4326+ merge_attr (ad, &ad1);
4327+ return 0;
4328+ } else
43004329 l = FUNC_OLD;
43014330 first = NULL;
43024331 plast = &first;
tccpe.c+1−1
@@ -1747,7 +1747,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd) · 1746 unmodified lines
17471747 ret = pe_load_def(s1, fd);
17481748 else if (pe_load_res(s1, fd) == 0)
17491749 ret = 0;
1750− else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4))
1750+ else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2))
17511751 ret = pe_load_dll(s1, filename);
17521752 return ret;
17531753 }
tests/tests2/82_attribs_position.c+25−0
@@ -16,6 +16,13 @@ void __attribute__((stdcall)) foo (void) · 15 unmodified lines
1616 {
1717 }
1818
19+#define __stdcall __attribute__((stdcall))
20+extern int some_stdcall_func (int, int, int) __stdcall;
21+__stdcall int __stdcall some_stdcall_func(int foo, int bar, int baz) {
22+ //printf("Hello from stdcall: %i %i %i\n", foo, bar, baz);
23+ return 43;
24+}
25+
1926 /* The actual attribute isn't important, must just be
2027 parsable. */
2128 #define ATTR __attribute__((__noinline__))
@@ -24,9 +31,11 @@ int ATTR actual_function() { · 2 unmodified lines
2431 }
2532
2633 extern int printf (const char *, ...);
34+static int globalvar;
2735 int main()
2836 {
2937 void *function_pointer = &actual_function;
38+ int localvar = 42, i;
3039
3140 int a = ((ATTR int(*) (void)) function_pointer)();
3241 printf("%i\n", a);
@@ -36,5 +45,21 @@ int main() · 3 unmodified lines
3645 int b = ( (int(ATTR *)(void)) function_pointer)();
3746 printf("%i\n", b);
3847
48+ /* All these should work and leave the stack pointer in its original
49+ position. */
50+ some_stdcall_func(1, 10, 100);
51+ ((int __stdcall (*)(int, int, int))some_stdcall_func) (2, 20, 200);
52+ ((int(*__stdcall)(int, int, int))some_stdcall_func) (3, 30, 300);
53+ for (i = 0; i < 1024; i++) {
54+ globalvar = i;
55+ /* This was once misparsed at <= gitrev 325241c0, forgetting
56+ the stdcall attribute on the function pointer leading to
57+ stack increment being done twice (in callee and caller).
58+ This will clobber 'i' and 'localvar' which is how we detect
59+ this. */
60+ ((int(__stdcall*)(int, int, int))some_stdcall_func) (4, 40, 400);
61+ if (localvar != 42 || globalvar != i)
62+ printf("error, localvar=%d i=%d globalvar=%d\n", localvar, i, globalvar);
63+ }
3964 return 0;
4065 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t