aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cc.h3
-rw-r--r--decl.c3
-rw-r--r--test/inline-definition.c7
-rw-r--r--test/inline-definition.qbe6
4 files changed, 18 insertions, 1 deletions
diff --git a/cc.h b/cc.h
index 47a2931..62c9780 100644
--- a/cc.h
+++ b/cc.h
@@ -262,6 +262,9 @@ struct decl {
/* alignment of object storage (may be stricter than type requires) */
int align;
+ /* the function might have an "inline definition" (C11 6.7.4p7) */
+ _Bool inlinedefn;
+
enum builtinkind builtin;
};
diff --git a/decl.c b/decl.c
index 26e9851..cff7564 100644
--- a/decl.c
+++ b/decl.c
@@ -994,6 +994,7 @@ decl(struct scope *s, struct func *f)
}
}
d = declcommon(s, kind, name, asmname, t, tq, sc, prior);
+ d->inlinedefn = d->linkage == LINKEXTERN && fs & FUNCINLINE && !(sc & SCEXTERN) && (!prior || prior->inlinedefn);
if (tok.kind == TLBRACE) {
if (!allowfunc)
error(&tok.loc, "function definition not allowed");
@@ -1003,7 +1004,7 @@ decl(struct scope *s, struct func *f)
f = mkfunc(d, name, t, s);
stmt(f, s);
/* XXX: need to keep track of function in case a later declaration specifies extern */
- if (!(fs & FUNCINLINE) || sc)
+ if (!d->inlinedefn)
emitfunc(f, d->linkage == LINKEXTERN);
s = delscope(s);
delfunc(f);
diff --git a/test/inline-definition.c b/test/inline-definition.c
new file mode 100644
index 0000000..224b14c
--- /dev/null
+++ b/test/inline-definition.c
@@ -0,0 +1,7 @@
+extern void f(void);
+
+/*
+f is not an inline definition, due to the preceeding declaration,
+so we *should* emit an external definition for it.
+*/
+inline void f(void) {}
diff --git a/test/inline-definition.qbe b/test/inline-definition.qbe
new file mode 100644
index 0000000..2401635
--- /dev/null
+++ b/test/inline-definition.qbe
@@ -0,0 +1,6 @@
+export
+function $f() {
+@start.1
+@body.2
+ ret
+}