aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--evaluate.c5
-rw-r--r--symbol.c6
-rw-r--r--symbol.h12
-rw-r--r--validation/extern-inline.c23
4 files changed, 40 insertions, 6 deletions
diff --git a/evaluate.c b/evaluate.c
index b63fa36..1ab5ae8 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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;
diff --git a/symbol.c b/symbol.c
index b7bb5af..cda6bd0 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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;
}
diff --git a/symbol.h b/symbol.h
index 751dec1..42d69d6 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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.
+ */