@@ -10686,7 +10686,7 @@ c_write_global_declarations_1 (tree globals)
{
/* Check for used but undefined static functions using the C
standard's definition of "used", and set TREE_NO_WARNING so
- that check_global_declarations doesn't repeat the check. */
+ that check_global_declaration doesn't repeat the check. */
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) == 0
&& DECL_EXTERNAL (decl)
@@ -10707,9 +10707,6 @@ c_write_global_declarations_1 (tree globals)
reconsider |= wrapup_global_declaration_2 (decl);
}
while (reconsider);
-
- for (decl = globals; decl; decl = DECL_CHAIN (decl))
- check_global_declaration_1 (decl);
}
/* Callback to collect a source_ref from a DECL. */
@@ -10811,7 +10808,7 @@ c_parse_final_cleanups (void)
}
/* Process all file scopes in this compilation, and the external_scope,
- through wrapup_global_declarations and check_global_declarations. */
+ through wrapup_global_declarations. */
FOR_EACH_VEC_ELT (*all_translation_units, i, t)
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
@@ -51,7 +51,7 @@ c_missing_noreturn_ok_p (tree decl)
return flag_hosted && MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
}
-/* Called from check_global_declarations. */
+/* Called from check_global_declaration. */
bool
c_warn_unused_global_decl (const_tree decl)
@@ -314,7 +314,7 @@ public:
bool needed_p (void);
/* Return true when there are references to the node. */
- bool referred_to_p (void);
+ bool referred_to_p (bool include_self = true);
/* Return true if NODE can be discarded by linker from the binary. */
inline bool
@@ -406,10 +406,11 @@ cgraph_node::reset (void)
remove_all_references ();
}
-/* Return true when there are references to the node. */
+/* Return true when there are references to the node. INCLUDE_SELF is
+ true if a self reference counts as a reference. */
bool
-symtab_node::referred_to_p (void)
+symtab_node::referred_to_p (bool include_self)
{
ipa_ref *ref = NULL;
@@ -419,7 +420,13 @@ symtab_node::referred_to_p (void)
/* For functions check also calls. */
cgraph_node *cn = dyn_cast <cgraph_node *> (this);
if (cn && cn->callers)
- return true;
+ {
+ if (include_self)
+ return true;
+ for (cgraph_edge *e = cn->callers; e; e = e->next_caller)
+ if (e->caller != this)
+ return true;
+ }
return false;
}
@@ -928,8 +935,12 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
static cgraph_node *first_analyzed;
static varpool_node *first_analyzed_var;
+/* FIRST_TIME is set to TRUE for the first time we are called for a
+ translation unit from finalize_compilation_unit() or false
+ otherwise. */
+
static void
-analyze_functions (void)
+analyze_functions (bool first_time)
{
/* Keep track of already processed nodes when called multiple times for
intermodule optimization. */
@@ -1101,6 +1112,13 @@ analyze_functions (void)
symtab_node::dump_table (symtab->dump_file);
}
+ if (first_time)
+ {
+ symtab_node *snode;
+ FOR_EACH_SYMBOL (snode)
+ check_global_declaration (snode->decl);
+ }
+
if (symtab->dump_file)
fprintf (symtab->dump_file, "\nRemoving unused symbols:");
@@ -2449,13 +2467,13 @@ symbol_table::finalize_compilation_unit (void)
/* Gimplify and lower all functions, compute reachability and
remove unreachable nodes. */
- analyze_functions ();
+ analyze_functions (true);
/* Mark alias targets necessary and emit diagnostics. */
handle_alias_pairs ();
/* Gimplify and lower thunks. */
- analyze_functions ();
+ analyze_functions (false);
/* Emit early debug for reachable functions, and by consequence,
locally scoped symbols. */
@@ -60,7 +60,7 @@ cxx_get_alias_set (tree t)
return c_common_get_alias_set (t);
}
-/* Called from check_global_declarations. */
+/* Called from check_global_declaration. */
bool
cxx_warn_unused_global_decl (const_tree decl)
@@ -4359,21 +4359,6 @@ dump_tu (void)
}
}
-/* Issue warnings for globals in NAME_SPACE (unused statics, etc). */
-
-static int
-check_statics_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
-{
- cp_binding_level *level = NAMESPACE_LEVEL (name_space);
- vec<tree, va_gc> *statics = level->static_decls;
- tree *vec = statics->address ();
- int len = statics->length ();
-
- check_global_declarations (vec, len);
-
- return 0;
-}
-
static location_t locus_at_end_of_parsing;
/* Check the deallocation functions for CODE to see if we want to warn that
@@ -4739,7 +4724,7 @@ c_parse_final_cleanups (void)
(template_for_substitution (decl)))))
{
warning (0, "inline function %q+D used but never defined", decl);
- /* Avoid a duplicate warning from check_global_declaration_1. */
+ /* Avoid a duplicate warning from check_global_declaration. */
TREE_NO_WARNING (decl) = 1;
}
}
@@ -4802,10 +4787,6 @@ c_parse_final_cleanups (void)
generate initial debug information. */
timevar_stop (TV_PHASE_PARSING);
timevar_start (TV_PHASE_DBGINFO);
- walk_namespaces (check_statics_for_namespace, 0);
- if (vec_safe_length (pending_statics) != 0)
- check_global_declarations (pending_statics->address (),
- pending_statics->length ());
perform_deferred_noexcept_checks ();
@@ -4718,7 +4718,8 @@ write_roots (pair_p variables, bool emit_pch)
this funcion will have to be adjusted to be more like
output_mangled_typename. */
-static void
+/* ?? Why are we keeping this? Is this actually used anywhere? */
+static void ATTRIBUTE_UNUSED
output_typename (outf_p of, const_type_p t)
{
switch (t->kind)
@@ -3084,8 +3084,6 @@ Gcc_backend::write_global_definitions(
wrapup_global_declarations(defs, i);
- check_global_declarations(defs, i);
-
delete[] defs;
}
@@ -139,12 +139,12 @@ lhd_print_tree_nothing (FILE * ARG_UNUSED (file),
{
}
-/* Called from check_global_declarations. */
+/* Called from check_global_declaration. */
bool
lhd_warn_unused_global_decl (const_tree decl)
{
- /* This is what used to exist in check_global_declarations. Probably
+ /* This is what used to exist in check_global_declaration. Probably
not many of these actually apply to non-C languages. */
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
@@ -338,7 +338,6 @@ global_decl_processing (void)
vec[len - i - 1] = decl;
wrapup_global_declarations (vec, len);
- check_global_declarations (vec, len);
timevar_stop (TV_PHASE_DEFERRED);
timevar_start (TV_PHASE_PARSING);
@@ -160,7 +160,7 @@ namespace std
typedef _Alloc allocator_type;
template < typename _Key_compare > struct _Rb_tree_impl
{
- _Rb_tree_impl (_Key_compare, _Node_allocator);
+ _Rb_tree_impl (_Key_compare, _Node_allocator); // { dg-warning "used but never defined" }
};
_Rb_tree_impl < _Compare > _M_impl;
_Rb_tree (_Compare __comp, allocator_type __a):
@@ -6,7 +6,7 @@
namespace {
struct A {
- virtual ~A();
+ virtual ~A(); // { dg-warning "used but never defined" }
};
struct B : public A {
@@ -4,7 +4,7 @@
namespace
{
struct A {
- static int bar ();
+ static int bar (); // { dg-error "used but never defined" "" }
static int i; // { dg-error "used, but not defined" "" { xfail *-*-* } }
static int j;
static int k;
@@ -178,7 +178,7 @@ public:
}
};
template <typename AttributeValueT>
-attribute_actor<AttributeValueT> attr (attribute_name);
+attribute_actor<AttributeValueT> attr (attribute_name); // { dg-warning "used but never defined" }
terminal<>::type stream;
template <typename LeftT, typename ImplT> class attribute_output_terminal
{
@@ -311,7 +311,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
typename __add_ref<
typename tuple_element<__i, tuple<_Elements...>>::type
>::type
- get(tuple<_Elements...>& __t) noexcept;
+ get(tuple<_Elements...>& __t) noexcept; // { dg-warning "used but never defined" }
template<std::size_t... _Indexes>
struct _Index_tuple
{};
@@ -386,7 +386,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
};
template<typename _Callable, typename... _Args>
typename _Bind_simple_helper<_Callable, _Args...>::__type
- __bind_simple(_Callable&& __callable, _Args&&... __args)
+ __bind_simple(_Callable&& __callable, _Args&&... __args) // { dg-warning "used but never defined" }
;
union _Any_data
;
@@ -403,7 +403,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
{
protected:
static _Functor*
- _M_get_pointer(const _Any_data& __source)
+ _M_get_pointer(const _Any_data& __source) // { dg-warning "used but never defined" }
;
};
};
@@ -510,7 +510,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
static pointer
- allocate(_Alloc& __a, size_type __n)
+ allocate(_Alloc& __a, size_type __n) // { dg-warning "used but never defined" }
;
template<typename _Tp, typename... _Args>
static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
@@ -8,7 +8,7 @@ namespace
{
struct A
{
- virtual C foo ();
+ virtual C foo (); // { dg-warning "used but never defined" }
C bar () { return foo (); }
};
}
@@ -6,7 +6,7 @@ namespace
{
struct A
{
- virtual int foo ();
+ virtual int foo (); // { dg-warning "used but never defined" }
int bar () { return foo (); }
};
}
@@ -145,7 +145,7 @@ here:
double
f10 (void)
{
- void foo10 (void)
+ void foo10 (void) /* { dg-warning "defined but not used" } */
{
a = 1.0;
}
@@ -500,15 +500,15 @@ wrapup_global_declarations (tree *vec, int len)
return output_something;
}
-/* A subroutine of check_global_declarations. Issue appropriate warnings
- for the global declaration DECL. */
+/* Issue appropriate warnings for the global declaration DECL. */
void
-check_global_declaration_1 (tree decl)
+check_global_declaration (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. */
+ symtab_node *snode = symtab_node::get (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) == 0
&& DECL_EXTERNAL (decl)
@@ -516,9 +516,9 @@ check_global_declaration_1 (tree decl)
&& ! TREE_NO_WARNING (decl)
&& ! TREE_PUBLIC (decl)
&& (warn_unused_function
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ || snode->referred_to_p (false)))
{
- if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ if (snode->referred_to_p (false))
pedwarn (input_location, 0, "%q+F used but never defined", decl);
else
warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl);
@@ -533,6 +533,11 @@ check_global_declaration_1 (tree decl)
|| (warn_unused_variable
&& TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl)
+ && ! snode->referred_to_p (false)
+ /* ?? Why are we looking at TREE_USED? Shouldn't the call to
+ referred_to_p above be enough? Apparently not, because the
+ `__unused__' attribute is not being considered for
+ referred_to_p. */
&& ! TREE_USED (decl)
/* The TREE_USED bit for file-scope decls is kept in the identifier,
to handle multiple external decls in different scopes. */
@@ -543,6 +548,10 @@ check_global_declaration_1 (tree decl)
&& ! TREE_THIS_VOLATILE (decl)
/* Global register variables must be declared to reserve them. */
&& ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ /* Global ctors and dtors are called by the runtime. */
+ && (TREE_CODE (decl) != FUNCTION_DECL
+ || (!DECL_STATIC_CONSTRUCTOR (decl)
+ && !DECL_STATIC_DESTRUCTOR (decl)))
/* Otherwise, ask the language. */
&& lang_hooks.decls.warn_unused_global (decl))
warning ((TREE_CODE (decl) == FUNCTION_DECL)
@@ -551,18 +560,6 @@ check_global_declaration_1 (tree decl)
"%q+D defined but not used", decl);
}
-/* Issue appropriate warnings for the global declarations in V (of
- which there are LEN). */
-
-void
-check_global_declarations (tree *v, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- check_global_declaration_1 (v[i]);
-}
-
/* Emit late debugging information (post compilation) for all global
declarations in VEC. */
@@ -59,8 +59,7 @@ extern void announce_function (tree);
extern void wrapup_global_declaration_1 (tree);
extern bool wrapup_global_declaration_2 (tree);
extern bool wrapup_global_declarations (tree *, int);
-extern void check_global_declaration_1 (tree);
-extern void check_global_declarations (tree *, int);
+extern void check_global_declaration (tree);
extern void emit_debug_global_declarations (tree *, int);