cil-project / cil

C Intermediate Language
Other
348 stars 86 forks source link

Extern inline prototypes should not replace definitions #14

Open stephenrkell opened 10 years ago

stephenrkell commented 10 years ago

Currently CIL is defeated by always_inline extern inline functions whose prototypes are repeated after their definition (but before their use).

$ cat vminimal.i
extern void f(void);
extern inline __attribute__((always_inline)) void g()
{
        f();
}

extern inline __attribute__((always_inline)) void g();

void v(void)
{
        g();
}

$ cc -c -o vminimal.o vminimal.i
$ cilly -c -o vminimal.o vminimal.i

vminimal.i: In function ‘v’:
vminimal.i:2:59: error: inlining failed in call to always_inline ‘g’: function body not available
 extern inline __attribute__((always_inline)) void g()
                                                           ^
vminimal.i:11:3: error: called from here
  g();
   ^

The following patch fixes things for me. (I'll forward it by e-mail too, since GitHub doesn't let me attach it.)

diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml
index dc185e1..30633c6 100644
--- a/src/frontc/cabs2cil.ml
+++ b/src/frontc/cabs2cil.ml
@@ -1792,7 +1792,7 @@ let makeGlobalVarinfo (isadef: bool) (vi: varinfo) : varinfo * bool =

     (* New-style extern inline handling: the real definition replaces the extern
        inline one *)
-    if (not !Cil.oldstyleExternInline) && oldvi.vstorage = Extern && oldvi.vinline then begin
+    if (not !Cil.oldstyleExternInline) && oldvi.vstorage = Extern && oldvi.vinline && isadef then begin
       H.remove alreadyDefined oldvi.vname;
       theFile := Util.list_map (fun g -> match g with
           | GFun (fi, l) when fi.svar == oldvi -> GVarDecl(fi.svar, l)