diff options
-rw-r--r-- | evaluate.c | 5 | ||||
-rw-r--r-- | symbol.c | 6 | ||||
-rw-r--r-- | symbol.h | 12 | ||||
-rw-r--r-- | validation/extern-inline.c | 23 |
4 files changed, 40 insertions, 6 deletions
@@ -536,11 +536,6 @@ static inline int lvalue_expression(struct expression *expr) return expr->type == EXPR_PREOP && expr->op == '*'; } -static inline int is_function(struct symbol *type) -{ - return type && type->type == SYM_FN; -} - static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *itype) { struct expression *index = expr->right; @@ -522,6 +522,8 @@ void check_declaration(struct symbol *sym) return; } if (sym->ctype.modifiers & next->ctype.modifiers & MOD_EXTERN) { + if ((sym->ctype.modifiers ^ next->ctype.modifiers) & MOD_INLINE) + continue; sym->same_symbol = next; return; } @@ -558,8 +560,10 @@ void bind_symbol(struct symbol *sym, struct ident *ident, enum namespace ns) scope = block_scope; if (ns == NS_SYMBOL && toplevel(scope)) { unsigned mod = MOD_ADDRESSABLE | MOD_TOPLEVEL; + scope = global_scope; - if (sym->ctype.modifiers & MOD_STATIC) { + if (sym->ctype.modifiers & MOD_STATIC || + is_extern_inline(sym)) { scope = file_scope; mod = MOD_TOPLEVEL; } @@ -340,6 +340,18 @@ static inline int is_void_type(struct symbol *type) return type == &void_ctype; } +static inline int is_function(struct symbol *type) +{ + return type && type->type == SYM_FN; +} + +static inline int is_extern_inline(struct symbol *sym) +{ + return (sym->ctype.modifiers & MOD_EXTERN) && + (sym->ctype.modifiers & MOD_INLINE) && + is_function(sym->ctype.base_type); +} + static inline int get_sym_type(struct symbol *type) { if (type->type == SYM_NODE) diff --git a/validation/extern-inline.c b/validation/extern-inline.c new file mode 100644 index 0000000..4f12ac0 --- /dev/null +++ b/validation/extern-inline.c @@ -0,0 +1,23 @@ +extern __inline__ int f(int); + +extern __inline__ int +f(int x) +{ + return x; +} + +extern int g(int); + +extern __inline__ int +g(int x) +{ + return x; +} + + +/* + * check-name: extern inline function + * check-command: sparse $file $file + * check-description: Extern inline function never emits stand alone copy + * of the function. It allows multiple such definitions in different file. + */ |