re PR c++/14401 (Uninitialized reference error not reported.)

PR c++/14401
	* class.c (check_field_decls): Complain about non-static data
	members of reference type in unions.  Propagate
	CLASSTYPE_REF_FIELDS_NEED_INIT and
	CLASSTYPE_READONLY_FIELDS_NEED_INIT from the types of non-static
	data members.
	* init.c (perform_member_init): Complain about mbmers with const
	type that are not explicitly initialized.

	PR c++/14401
	* g++.dg/init/ctor3.C: New test.
	* g++.dg/init/union1.C: New test.
	* g++.dg/ext/anon-struct4.C: New test.

From-SVN: r79158
This commit is contained in:
Mark Mitchell 2004-03-09 08:16:49 +00:00 committed by Mark Mitchell
parent f1c4ca32d0
commit 58ec3cc5c0
21 changed files with 146 additions and 162 deletions

View File

@ -1,3 +1,44 @@
2004-03-08 Mark Mitchell <mark@codesourcery.com>
PR c++/14401
* class.c (check_field_decls): Complain about non-static data
members of reference type in unions. Propagate
CLASSTYPE_REF_FIELDS_NEED_INIT and
CLASSTYPE_READONLY_FIELDS_NEED_INIT from the types of non-static
data members.
* init.c (perform_member_init): Complain about mbmers with const
type that are not explicitly initialized.
2004-03-08 Mark Mitchell <mark@codesourcery.com>
* class.c (check_methods): Don't use IDENTIFIER_ERROR_LOCUS.
* cp-tree.h (DECL_INVALID_OVERRIDER_P): New macro.
(lang_identifier): Remove implicit_decl and error_locus.
(IDENTIFIER_IMPLICIT_DECL): Remove.
(SET_IDENTIFIER_IMPLICTI_DECL): Likewise.
(IDENTIFIER_ERROR_LOCUS): Likewise.
(SET_IDENTIFIER_ERROR_LOCUS): Likewise.
(TYPE_ASSEMBLER_NAME_STRING): Likewise.
(TYPE_ASSEMBLER_NAME_LENGTH): Likewise.
(implicitly_declare): Remove.
* decl.c (warn_extern_redeclared_static): Remove check of
IDENTIFIER_IMPLICIT_DECL.
(duplicate_decls): Don't check IDENTIFIER_ERROR_LOCUS.
(implicitly_declare): Remove.
(grok_ctor_properties): Don't set IDENTIFIER_ERROR_LOCUS.
(start_function): Don't check IDENTIFIER_IMPLICIT_DECL.
(start_method): Don't check IDENTIFIER_ERROR_LOCUS.
* lex.c (unqualified_name_lookup_error): Create a dummy VAR_DECL
in the innermost scope, rather than at namespace scope.
* name-lookup.c (push_local_binding): Give it external linkage.
(pushdecl): Remove dead code.
* name-lookup.h (push_local_binding): Declare it.
* ptree.c (cxx_print_identifier): Don't print
IDENTIFIER_IMPLICIT_DECL or IDENTIFIER_ERROR_LOCUS.
* search.c (check_final_overrider): Use DECL_INVALID_OVERRIDER_P,
not IDENTIFIER_ERROR_LOCUS.
* typeck.c (build_function_call): Remove dead code.
2004-03-08 Jason Merrill <jason@redhat.com>
PR c++/13170

View File

@ -2923,9 +2923,30 @@ check_field_decls (tree t, tree *access_decls,
/* If we've gotten this far, it's a data member, possibly static,
or an enumerator. */
DECL_CONTEXT (x) = t;
/* When this goes into scope, it will be a non-local reference. */
DECL_NONLOCAL (x) = 1;
if (TREE_CODE (t) == UNION_TYPE)
{
/* [class.union]
If a union contains a static data member, or a member of
reference type, the program is ill-formed. */
if (TREE_CODE (x) == VAR_DECL)
{
cp_error_at ("`%D' may not be static because it is a member of a union", x);
continue;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
cp_error_at ("`%D' may not have reference type `%T' because it is a member of a union",
x, type);
continue;
}
}
/* ``A local class cannot have static data members.'' ARM 9.4 */
if (current_function_decl && TREE_STATIC (x))
cp_error_at ("field `%D' in local class cannot be static", x);
@ -2949,21 +2970,9 @@ check_field_decls (tree t, tree *access_decls,
if (type == error_mark_node)
continue;
/* When this goes into scope, it will be a non-local reference. */
DECL_NONLOCAL (x) = 1;
if (TREE_CODE (x) == CONST_DECL)
if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
continue;
if (TREE_CODE (x) == VAR_DECL)
{
if (TREE_CODE (t) == UNION_TYPE)
/* Unions cannot have static members. */
cp_error_at ("field `%D' declared static in union", x);
continue;
}
/* Now it can only be a FIELD_DECL. */
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
@ -2994,6 +3003,14 @@ check_field_decls (tree t, tree *access_decls,
if (TYPE_PTR_P (type))
has_pointers = 1;
if (CLASS_TYPE_P (type))
{
if (CLASSTYPE_REF_FIELDS_NEED_INIT (type))
SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
}
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
CLASSTYPE_HAS_MUTABLE (t) = 1;
@ -3683,11 +3700,6 @@ check_methods (tree t)
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
/* If this was an evil function, don't keep it in class. */
if (DECL_ASSEMBLER_NAME_SET_P (x)
&& IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue;
check_for_override (x, t);
if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
cp_error_at ("initializer specified for non-virtual method `%D'", x);

View File

@ -100,6 +100,7 @@ struct diagnostic_context;
4: DECL_C_BIT_FIELD (in a FIELD_DECL)
DECL_VAR_MARKED_P (in a VAR_DECL)
DECL_SELF_REFERENCE_P (in a TYPE_DECL)
DECL_INVALID_OVERRIRDER_P (in a FUNCTION_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
@ -224,8 +225,6 @@ struct lang_identifier GTY(())
tree class_value;
tree class_template_info;
tree label_value;
tree implicit_decl;
tree error_locus;
};
/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
@ -399,16 +398,6 @@ typedef enum cp_id_kind
#define SET_IDENTIFIER_LABEL_VALUE(NODE, VALUE) \
IDENTIFIER_LABEL_VALUE (NODE) = (VALUE)
#define IDENTIFIER_IMPLICIT_DECL(NODE) \
(LANG_IDENTIFIER_CAST (NODE)->implicit_decl)
#define SET_IDENTIFIER_IMPLICIT_DECL(NODE, VALUE) \
IDENTIFIER_IMPLICIT_DECL (NODE) = (VALUE)
#define IDENTIFIER_ERROR_LOCUS(NODE) \
(LANG_IDENTIFIER_CAST (NODE)->error_locus)
#define SET_IDENTIFIER_ERROR_LOCUS(NODE, VALUE) \
IDENTIFIER_ERROR_LOCUS (NODE) = (VALUE)
/* Nonzero if this identifier is used as a virtual function name somewhere
(optimizes searches). */
#define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1 (NODE)
@ -888,11 +877,6 @@ enum languages { lang_c, lang_cplusplus, lang_java };
#define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE)))
#define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE)))
#define TYPE_ASSEMBLER_NAME_STRING(NODE) \
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
#define TYPE_ASSEMBLER_NAME_LENGTH(NODE) \
(IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
/* Nonzero if NODE has no name for linkage purposes. */
#define TYPE_ANONYMOUS_P(NODE) \
(TAGGED_TYPE_P (NODE) && ANON_AGGRNAME_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
@ -1951,6 +1935,13 @@ struct lang_decl GTY(())
#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.needs_final_overrider)
/* True (in a FUNCTION_DECL) if NODE is a virtual function that is an
invalid overrider for a function from a base class. Once we have
complained about an invalid overrider we avoid complaining about it
again. */
#define DECL_INVALID_OVERRIDER_P(NODE) \
(DECL_LANG_FLAG_4 (NODE))
/* The thunks associated with NODE, a FUNCTION_DECL. */
#define DECL_THUNKS(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.f.context)
@ -3614,7 +3605,6 @@ extern tree duplicate_decls (tree, tree);
extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree);
extern tree push_using_decl (tree, tree);
extern tree implicitly_declare (tree);
extern tree declare_local_label (tree);
extern tree define_label (location_t, tree);
extern void check_goto (tree);

View File

@ -1097,11 +1097,6 @@ decls_match (tree newdecl, tree olddecl)
void
warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
static const char *const explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
static const char *const implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
tree name;
if (TREE_CODE (newdecl) == TYPE_DECL
@ -1127,9 +1122,7 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
return;
name = DECL_ASSEMBLER_NAME (newdecl);
pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
pedwarn ("`%D' was declared `extern' and later `static'", newdecl);
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
@ -1373,10 +1366,7 @@ duplicate_decls (tree newdecl, tree olddecl)
else
return NULL_TREE;
}
/* Already complained about this, so don't do so again. */
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
else
{
error ("conflicting declaration '%#D'", newdecl);
cp_error_at ("'%D' has a previous declaration as `%#D'",
@ -1943,39 +1933,6 @@ duplicate_decls (tree newdecl, tree olddecl)
return olddecl;
}
/* Generate an implicit declaration for identifier FUNCTIONID
as a function of type int (). Print a warning if appropriate. */
tree
implicitly_declare (tree functionid)
{
tree decl;
/* We used to reuse an old implicit decl here,
but this loses with inline functions because it can clobber
the saved decl chains. */
decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
/* ISO standard says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
pushdecl (decl);
rest_of_decl_compilation (decl, NULL, 0, 0);
if (warn_implicit
/* Only one warning per identifier. */
&& IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
{
pedwarn ("implicit declaration of function `%#D'", decl);
}
SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
return decl;
}
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
@ -8844,7 +8801,6 @@ grok_ctor_properties (tree ctype, tree decl)
instantiated, but that's hard to forestall. */
error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
return 0;
}
@ -10154,12 +10110,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
ctype = NULL_TREE;
}
/* Warn if function was previously implicitly declared
(but not if we warned then). */
if (! warn_implicit
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
if (ctype)
@ -10929,13 +10879,10 @@ start_method (tree declspecs, tree declarator, tree attrlist)
if (DECL_IN_AGGR_P (fndecl))
{
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
error ("`%D' is already defined in class `%T'", fndecl,
DECL_CONTEXT (fndecl));
}
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
error ("`%D' is already defined in class `%T'", fndecl,
DECL_CONTEXT (fndecl));
return void_type_node;
}

View File

@ -371,6 +371,9 @@ perform_member_init (tree member, tree init)
/* member traversal: note it leaves init NULL */
else if (TREE_CODE (type) == REFERENCE_TYPE)
pedwarn ("uninitialized reference member `%D'", member);
else if (CP_TYPE_CONST_P (type))
pedwarn ("uninitialized mber `%D' with `const' type `%T'",
member, type);
}
else if (TREE_CODE (init) == TREE_LIST)
/* There was an explicit member initialization. Do some work

View File

@ -627,26 +627,18 @@ unqualified_name_lookup_error (tree name)
if (name != ansi_opname (ERROR_MARK))
error ("`%D' not defined", name);
}
else if (current_function_decl == 0)
error ("`%D' was not declared in this scope", name);
else
{
if (IDENTIFIER_NAMESPACE_VALUE (name) != error_mark_node
|| IDENTIFIER_ERROR_LOCUS (name) != current_function_decl)
error ("`%D' was not declared in this scope", name);
/* Prevent repeated error messages by creating a VAR_DECL with
this NAME in the innermost block scope. */
if (current_function_decl)
{
static int undeclared_variable_notice;
error ("`%D' undeclared (first use this function)", name);
if (! undeclared_variable_notice)
{
error ("(Each undeclared identifier is reported only once for each function it appears in.)");
undeclared_variable_notice = 1;
}
tree decl;
decl = build_decl (VAR_DECL, name, error_mark_node);
DECL_CONTEXT (decl) = current_function_decl;
push_local_binding (name, decl, 0);
}
/* Prevent repeated error messages. */
SET_IDENTIFIER_NAMESPACE_VALUE (name, error_mark_node);
SET_IDENTIFIER_ERROR_LOCUS (name, current_function_decl);
}
return error_mark_node;

View File

@ -36,7 +36,6 @@ static cxx_scope *innermost_nonclass_level (void);
static tree select_decl (cxx_binding *, int);
static cxx_binding *binding_for_name (cxx_scope *, tree);
static tree lookup_name_current_level (tree);
static void push_local_binding (tree, tree, int);
static tree push_overloaded_decl (tree, int);
static bool lookup_using_namespace (tree, cxx_binding *, tree,
tree, int);
@ -647,13 +646,7 @@ pushdecl (tree x)
t = NULL_TREE;
}
if (t == error_mark_node)
{
/* error_mark_node is 0 for a while during initialization! */
t = NULL_TREE;
cp_error_at ("`%#D' used prior to declaration", x);
}
else if (t != NULL_TREE)
if (t && t != error_mark_node)
{
if (different_binding_level)
{
@ -830,24 +823,6 @@ pushdecl (tree x)
|| TREE_CODE (x) == TEMPLATE_DECL))
SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
/* Don't forget if the function was used via an implicit decl. */
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_USED (x) = 1;
/* Don't forget if its address was taken in that way. */
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_ADDRESSABLE (x) = 1;
/* Warn about mismatches against previous implicit decl. */
if (IDENTIFIER_IMPLICIT_DECL (name) != NULL_TREE
/* If this real decl matches the implicit, don't complain. */
&& ! (TREE_CODE (x) == FUNCTION_DECL
&& TREE_TYPE (TREE_TYPE (x)) == integer_type_node))
warning
("`%D' was previously implicitly declared to return `int'", x);
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
@ -1035,7 +1010,7 @@ maybe_push_decl (tree decl)
doesn't really belong to this binding level, that it got here
through a using-declaration. */
static void
void
push_local_binding (tree id, tree decl, int flags)
{
struct cp_binding_level *b;

View File

@ -287,6 +287,7 @@ extern tree lookup_namespace_name (tree, tree);
extern tree lookup_qualified_name (tree, tree, bool, bool);
extern tree lookup_name_nonclass (tree);
extern tree lookup_function_nonclass (tree, tree);
extern void push_local_binding (tree, tree, int);
extern int push_class_binding (tree, tree);
extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level (tree);

View File

@ -157,8 +157,6 @@ cxx_print_identifier (FILE *file, tree node, int indent)
cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
}
void

View File

@ -1703,7 +1703,10 @@ check_final_overrider (tree overrider, tree basefn)
tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
int fail = 0;
if (DECL_INVALID_OVERRIDER_P (overrider))
return 0;
if (same_type_p (base_return, over_return))
/* OK */;
else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
@ -1753,8 +1756,6 @@ check_final_overrider (tree overrider, tree basefn)
fail = 2;
if (!fail)
/* OK */;
else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
return 0;
else
{
if (fail == 1)
@ -1768,21 +1769,16 @@ check_final_overrider (tree overrider, tree basefn)
overrider);
cp_error_at (" overriding `%#D'", basefn);
}
SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
DECL_CONTEXT (overrider));
DECL_INVALID_OVERRIDER_P (overrider) = 1;
return 0;
}
/* Check throw specifier is at least as strict. */
if (!comp_except_specs (base_throw, over_throw, 0))
{
if (!IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
{
cp_error_at ("looser throw specifier for `%#F'", overrider);
cp_error_at (" overriding `%#F'", basefn);
SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
DECL_CONTEXT (overrider));
}
cp_error_at ("looser throw specifier for `%#F'", overrider);
cp_error_at (" overriding `%#F'", basefn);
DECL_INVALID_OVERRIDER_P (overrider) = 1;
return 0;
}

View File

@ -2380,7 +2380,7 @@ build_function_call (tree function, tree params)
tree fntype, fndecl;
tree coerced_params;
tree result;
tree name = NULL_TREE, assembler_name = NULL_TREE;
tree name = NULL_TREE;
int is_method;
tree original = function;
@ -2393,7 +2393,6 @@ build_function_call (tree function, tree params)
if (TREE_CODE (function) == FUNCTION_DECL)
{
name = DECL_NAME (function);
assembler_name = DECL_ASSEMBLER_NAME (function);
mark_used (function);
fndecl = function;

View File

@ -1,3 +1,19 @@
2004-03-08 Mark Mitchell <mark@codesourcery.com>
PR c++/14401
* g++.dg/init/ctor3.C: New test.
* g++.dg/init/union1.C: New test.
* g++.dg/ext/anon-struct4.C: New test.
2004-03-08 Mark Mitchell <mark@codesourcery.com>
* g++.dg/lookup/koenig1.C: Tweak error messages.
* g++.dg/lookup/used-before-declaration.C: Likewise.
* g++.dg/other/do1.C: Likewise.
* g++.dg/overload/koenig1.C: Likewise.
* g++.dg/parse/crash13.C: Likewise.
* g++.dg/template/instantiate3.C: Likewise.
2004-03-08 Eric Christopher <echristo@redhat.com>
* * lib/target-supports.exp: Enable libiconv in test

View File

@ -0,0 +1,3 @@
// PR c++/14401
struct { struct { int& i ; } bar ; } foo ; // { dg-error "" }

View File

@ -0,0 +1,6 @@
// PR c++/14401
struct S {
S() {} // { dg-error "" }
const int i;
};

View File

@ -0,0 +1,5 @@
// PR c++/14401
union U {
int& i; // { dg-error "" }
};

View File

@ -9,5 +9,5 @@ class X;
void foo() {
X x(1); // { dg-error "incomplete type" "" }
bar(x); // { dg-error "undeclared" "" }
bar(x); // { dg-error "not declared" "" }
}

View File

@ -1,5 +1,5 @@
// Copyroght (C) 2003 Free Software Foundation
// Origin: PR/12832, Jonathan Wakely <redi@gcc.gnu.org>
void f() { g(); } // { dg-error "undeclared" "" }
void g() { } // { dg-error "used" "" }
void f() { g(); } // { dg-error "not declared" "" }
void g() { }

View File

@ -8,6 +8,6 @@
void init ()
{
do { } while (0)
obj = 0; // { dg-error "expected|undeclared" "" }
obj = 0; // { dg-error "expected|not declared" "" }
}

View File

@ -13,6 +13,6 @@ void g ()
{
B *bp;
N::A *ap;
f (bp); // { dg-error "undeclared" }
f (bp); // { dg-error "not declared" }
f (ap);
}

View File

@ -18,5 +18,5 @@ void func(A<T>::B* ) // { dg-error "variable|template|expression" }
int main()
{
func<void>(0); // { dg-error "undeclared|expression|;" }
func<void>(0); // { dg-error "not declared|expression|;" }
}

View File

@ -10,7 +10,7 @@ template <class TYPE>
struct ACE_Cleanup_Adapter
{
TYPE &object ()
{ return object_; } // { dg-error "undeclared|reported" }
{ return object_; } // { dg-error "not declared|reported" }
TYPE object_; // { dg-error "incomplete type" }
};