aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libtcc.c2
-rw-r--r--tcc.h6
-rw-r--r--tccgen.c7
-rw-r--r--tests/tcctest.c18
4 files changed, 29 insertions, 4 deletions
diff --git a/libtcc.c b/libtcc.c
index 483670a..58a5ca0 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -429,7 +429,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
if (sym->type.t & VT_STATIC)
sym_bind = STB_LOCAL;
else {
- if (sym_type == STT_FUNC && sym->type.ref && FUNC_WEAK(sym->type.ref->r))
+ if (sym->type.t & VT_WEAK)
sym_bind = STB_WEAK;
else
sym_bind = STB_GLOBAL;
diff --git a/tcc.h b/tcc.h
index 2cd2043..b72f4e4 100644
--- a/tcc.h
+++ b/tcc.h
@@ -293,7 +293,6 @@ typedef struct AttributeDef {
#define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args)
#define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned)
#define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed)
-#define FUNC_WEAK(r) (((AttributeDef*)&(r))->weak)
#define ATTR_MODE(r) (((AttributeDef*)&(r))->mode)
#define INT_ATTR(ad) (*(int*)(ad))
@@ -629,11 +628,12 @@ struct TCCState {
#define VT_INLINE 0x00000400 /* inline definition */
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
+#define VT_WEAK 0x00010000 /* win32: data exported from dll */
-#define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
+#define VT_STRUCT_SHIFT 17 /* shift for bitfield shift values */
/* type mask (except storage) */
-#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT)
+#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK)
#define VT_TYPE (~(VT_STORAGE))
/* token values */
diff --git a/tccgen.c b/tccgen.c
index 3c6adbc..2d7e4ae 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -2922,6 +2922,9 @@ static int parse_btype(CType *type, AttributeDef *ad)
case TOK_ATTRIBUTE1:
case TOK_ATTRIBUTE2:
parse_attribute(ad);
+ if (ad->weak) {
+ t |= VT_WEAK;
+ }
if (ad->mode) {
u = ad->mode -1;
t = (t & ~VT_BTYPE) | u;
@@ -3189,6 +3192,10 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
post_type(type, ad);
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
parse_attribute(ad);
+
+ if (ad->weak)
+ type->t |= VT_WEAK;
+
if (!type1.t)
return;
/* append type at the end of type1 */
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 14ad1e6..8c2b2a2 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -82,6 +82,7 @@ void local_label_test(void);
void statement_expr_test(void);
void asm_test(void);
void builtin_test(void);
+void weak_test(void);
int fib(int n);
void num(int n);
@@ -537,6 +538,7 @@ int main(int argc, char **argv)
local_label_test();
asm_test();
builtin_test();
+ weak_test();
return 0;
}
@@ -2227,6 +2229,22 @@ void builtin_test(void)
}
+extern int __attribute__((weak)) weak_f1(void);
+extern int __attribute__((weak)) weak_f2(void);
+extern int __attribute__((weak)) weak_v1;
+extern int __attribute__((weak)) weak_v2;
+
+void __attribute__((weak)) weak_test(void)
+{
+ printf("weak_f1=%d\n", weak_f1 ? weak_f1() : 123);
+ printf("weak_f2=%d\n", weak_f2 ? weak_f2() : 123);
+ printf("weak_v1=%d\n",&weak_v1 ? weak_v1 : 123);
+ printf("weak_v2=%d\n",&weak_v2 ? weak_v2 : 123);
+}
+
+int __attribute__((weak)) weak_f2() { return 222; }
+int __attribute__((weak)) weak_v2 = 222;
+
void const_func(const int a)
{
}