diff options
-rw-r--r-- | cc.h | 3 | ||||
-rw-r--r-- | decl.c | 3 | ||||
-rw-r--r-- | test/inline-definition.c | 7 | ||||
-rw-r--r-- | test/inline-definition.qbe | 6 |
4 files changed, 18 insertions, 1 deletions
@@ -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; }; @@ -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 +} |