diff options
author | Christopher Li <sparse@chrisli.org> | 2009-07-10 11:19:22 -0700 |
---|---|---|
committer | Christopher Li <sparse@chrisli.org> | 2009-07-19 02:17:32 +0000 |
commit | 8cf99394ee4c08a3ede8ef52cd0b3ce73afcf076 (patch) | |
tree | 9b280f75bda93d150735509c86f98a68439b9837 | |
parent | 37f041aba632b7ffc46eb779df07804d9d7d547a (diff) | |
download | sparse-8cf99394ee4c08a3ede8ef52cd0b3ce73afcf076.tar.gz |
move extern inline function to file scope
In gcc extern inline function has special meaning. The inline
function will never emit stand alone copy of the function. It also
allow multiple implementations cross different file. That effectively
makes the extern inline has file scope.
Signed-off-by: Christopher Li <sparse@chrisli.org>
-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 00000000..4f12ac06 --- /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. + */ |