Bug 49702 - Undefined static functions resolve to external definitions
Summary: Undefined static functions resolve to external definitions
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid, diagnostic, wrong-code
Depends on:
Blocks:
 
Reported: 2011-07-11 11:38 UTC by Richard Biener
Modified: 2021-09-15 01:56 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-07-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2011-07-11 11:38:32 UTC
main.c:
-------
static int foo(); int main () { return foo(); }
t.c:
----
int foo() { return 0; }

> gcc -o t t1.c t.c
t.c:1: warning: ‘foo’ used but never defined
> ./t
> echo $?
0

> g++ -o t t1.c t.c
t.c:1: error: ‘int foo()’ used but never defined

For the C frontend you need -pedantic-errors to make it reject main.c.
Without -pedantic-errors wrong code is emitted:

Relocation section '.rela.eh_frame' at offset 0x5a8 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  00020000000a R_X86_64_32       0000000000000000 .text + 0

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
...
     9: 0000000000000000    16 FUNC    GLOBAL DEFAULT    1 main
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND foo

but that's hardly possible to improve without erroring out by default.

Is there a way to only make the assembler reject the code (if maybe
a toplevel asm contains the local symbol?)?
Comment 1 Richard Biener 2011-07-11 11:53:06 UTC
Warning code in question:

toplev.c:
void
check_global_declaration_1 (tree decl)
{
  /* Warn about any function declared static but not defined.  We don't
     warn about variables, because many programs have static variables
     that exist only to get some text into the object file.  */
  if (TREE_CODE (decl) == FUNCTION_DECL
      && DECL_INITIAL (decl) == 0
      && DECL_EXTERNAL (decl)
      && ! DECL_ARTIFICIAL (decl)
      && ! TREE_NO_WARNING (decl)
      && ! TREE_PUBLIC (decl)
      && (warn_unused_function
          || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
    {
      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
        pedwarn (input_location, 0, "%q+F used but never defined", decl);
      else
        warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl);
      /* This symbol is effectively an "extern" declaration now.  */
      TREE_PUBLIC (decl) = 1;
      assemble_external (decl);
    }
Comment 2 Eric Gallager 2017-07-25 19:26:43 UTC
Confirmed.
Comment 3 Eric Gallager 2018-04-25 13:13:58 UTC
Possibly related: bug 19315? (both cases of statics becoming externs; that for variables, this for functions)
Comment 4 Eric Gallager 2019-08-08 04:14:34 UTC
(In reply to Eric Gallager from comment #3)
> Possibly related: bug 19315? (both cases of statics becoming externs; that
> for variables, this for functions)

Update: that has since been fixed by r263556; I haven't checked to see if that revision fixed this bug too, yet, though...
(cc-ing Iain, who did that revision)