------- Comment #1 from jakub at gcc dot gnu dot org 2009-02-13 10:36 ------- The problem is in the redundant prototype after function. First the foo FUNCTION_DECL is created, afterwards finish_function calls c_determine_visibility on it which changes its visibility from default to hidden. After this make_decl_rtl is called, determines the function binds locally and sets SYMBOL_FLAG_LOCAL|SYMBOL_FLAG_FUNCTION. Then merge_decls is called, which in turn clears visibility (sets it back to default) and calls make_decl_rtl to update the flags. At this point targetm.binds_local_p returns false, as it at that point has default visibility, so changes DECL_RTL's flags to SYMBOL_FLAG_FUNCTION alone. Then finish_decl calls c_determine_visibility again and sets it back to hidden visibility. But nothing afterwards calls make_decl_rtl again to update the symbol flags again.
To fix this, IMHO either c_determine_visibility and C++ determine_visibility need to if (((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) || TREE_CODE (decl) == FUNCTION_DECL) && DECL_RTL_SET_P (decl)) make_decl_rtl (decl); if it changed the visibility, or merge_decls/duplicate_decls would need to determine visibility. I'll try the former. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39175