re PR c++/42844 (const variable requires initializer / no explicitly declared default constructor)

PR c++/42844
	* decl.c (check_for_uninitialized_const_var): Handle classes that need
	constructing, too.
	(check_initializer): Call it for classes that need constructing, too.
	* class.c (in_class_defaulted_default_constructor): New.
	* cp-tree.h: Declare it.

Co-Authored-By: Jason Merrill <jason@redhat.com>

From-SVN: r158797
This commit is contained in:
Fabien Chêne 2010-04-27 18:56:13 +00:00 committed by Jason Merrill
parent 78b41ae280
commit 6ad86a5b26
14 changed files with 198 additions and 12 deletions

View File

@ -1,3 +1,13 @@
2010-04-27 Fabien Chêne <fabien.chene@gmail.com>
Jason Merrill <jason@redhat.com>
PR c++/42844
* decl.c (check_for_uninitialized_const_var): Handle classes that need
constructing, too.
(check_initializer): Call it for classes that need constructing, too.
* class.c (in_class_defaulted_default_constructor): New.
* cp-tree.h: Declare it.
2010-04-20 Jason Merrill <jason@redhat.com>
PR c++/9335

View File

@ -1,6 +1,6 @@
/* Functions related to building classes and their related objects.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@ -4177,6 +4177,34 @@ type_has_user_nondefault_constructor (tree t)
return false;
}
/* Returns the defaulted constructor if T has one. Otherwise, returns
NULL_TREE. */
tree
in_class_defaulted_default_constructor (tree t)
{
tree fns, args;
if (!TYPE_HAS_USER_CONSTRUCTOR (t))
return NULL_TREE;
for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (DECL_DEFAULTED_IN_CLASS_P (fn))
{
args = FUNCTION_FIRST_USER_PARMTYPE (fn);
while (args && TREE_PURPOSE (args))
args = TREE_CHAIN (args);
if (!args || args == void_list_node)
return fn;
}
}
return NULL_TREE;
}
/* Returns true iff FN is a user-provided function, i.e. user-declared
and not defaulted at its first declaration; or explicit, private,
protected, or non-const. */

View File

@ -4611,6 +4611,7 @@ extern void check_for_override (tree, tree);
extern void push_class_stack (void);
extern void pop_class_stack (void);
extern bool type_has_user_nondefault_constructor (tree);
extern tree in_class_defaulted_default_constructor (tree);
extern bool user_provided_p (tree);
extern bool type_has_user_provided_constructor (tree);
extern bool type_has_user_provided_default_constructor (tree);

View File

@ -1,6 +1,6 @@
/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@ -4692,7 +4692,7 @@ maybe_commonize_var (tree decl)
static void
check_for_uninitialized_const_var (tree decl)
{
tree type = TREE_TYPE (decl);
tree type = strip_array_types (TREE_TYPE (decl));
if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl)
&& DECL_INITIAL (decl) == NULL)
@ -4704,11 +4704,28 @@ check_for_uninitialized_const_var (tree decl)
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
&& (!TYPE_NEEDS_CONSTRUCTING (type)
|| !type_has_user_provided_default_constructor (type))
&& !DECL_INITIAL (decl))
error ("uninitialized const %qD", decl);
}
{
permerror (DECL_SOURCE_LOCATION (decl),
"uninitialized const %qD", decl);
if (CLASS_TYPE_P (type)
&& !type_has_user_provided_default_constructor (type))
{
tree defaulted_ctor;
inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
"%q#T has no user-provided default constructor", type);
defaulted_ctor = in_class_defaulted_default_constructor (type);
if (defaulted_ctor)
inform (DECL_SOURCE_LOCATION (defaulted_ctor),
"constructor is not user-provided because it is "
"explicitly defaulted in the class body");
}
}
}
/* Structure holding the current initializer being processed by reshape_init.
CUR is a pointer to the current element being processed, END is a pointer
@ -5261,7 +5278,10 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
else if (DECL_EXTERNAL (decl))
;
else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
return build_aggr_init_full_exprs (decl, init, flags);
{
check_for_uninitialized_const_var (decl);
return build_aggr_init_full_exprs (decl, init, flags);
}
else if (MAYBE_CLASS_TYPE_P (type))
{
tree core_type = strip_array_types (type);

View File

@ -1,3 +1,11 @@
2010-04-27 Fabien Chêne <fabien.chene@gmail.com>
* g++.dg/init/pr42844.C: New.
* g++.dg/cpp0x/pr42844-2.C: New.
* g++.dg/cpp0x/defaulted2.C: Adjust.
* g++.dg/tree-ssa/pr27549.C: Likewise.
* g++.old-deja/g++.mike/dyncast8.C: Likewise.
2010-04-27 Tobias Burnus <burnus@net-b.de>
PR fortran/18918

View File

@ -15,9 +15,9 @@ A::A() = default; // { dg-error "redefinition" }
void g() {} // { dg-error "previous" }
void g() = delete; // { dg-error "redefinition" }
struct B
struct B // { dg-message "user-provided default constructor" }
{
B() = default;
B() = default; // { dg-message "not user-provided" }
};
const B b; // { dg-error "uninitialized const" }

View File

@ -0,0 +1,38 @@
// PR c++/42844
// { dg-do compile }
// { dg-options "-std=c++0x" }
struct A // { dg-message "user-provided default constructor" }
{
A() = default; // { dg-message "not user-provided" }
};
struct Base
{
Base() {}
};
struct Derived : Base // { dg-message "user-provided default constructor" }
{
Derived() = default; // { dg-message "not user-provided" }
};
struct Derived2 : Base // { dg-message "user-provided default constructor" }
{
Derived2() = default; // { dg-message "not user-provided" }
Derived2( Derived2 const& ) = default;
};
struct Derived3 : Base // { dg-message "user-provided default constructor" }
{
Derived3( Derived3 const& ) = default;
Derived3() = default; // { dg-message "not user-provided" }
};
void f()
{
const A a; // { dg-error "uninitialized const" }
const Derived d; // { dg-error "uninitialized const" }
const Derived2 d2; // { dg-error "uninitialized const" }
const Derived3 d3; // { dg-error "uninitialized const" }
}

View File

@ -0,0 +1,56 @@
// PR c++/42844
// { dg-do compile }
struct A
{
A(){}
};
struct B : A {}; // { dg-message "user-provided default constructor" }
struct C : A {}; // { dg-message "user-provided default constructor" }
struct D : B { D() {} };
struct E {}; // { dg-message "user-provided default constructor" }
template <class T>
struct F : A {}; // { dg-message "user-provided default constructor" }
template <class T>
struct G {}; // { dg-message "user-provided default constructor" }
void f ()
{
B const b; // { dg-error "uninitialized const" }
extern B const bext;
C const c[ 1 ]; // { dg-error "uninitialized const" }
extern C const cext[ 1 ];
D const d;
extern D const dext;
E const e; // { dg-error "uninitialized const" }
extern E const eext;
F<int> const f; // { dg-error "uninitialized const" }
extern F<int> const fext;
G<int> const g; // { dg-error "uninitialized const" }
extern G<int> const gext;
}
struct H {}; // { dg-message "user-provided default constructor" }
struct I : A {}; // { dg-message "user-provided default constructor" }
template <class T>
void g ()
{
T const t; // { dg-error "uninitialized const" }
extern T const text;
}
template void g<H> ();
template void g<I> ();

View File

@ -13,6 +13,7 @@ struct E
struct F : public E
{
F () {}
virtual ~F () {}
virtual size_t e () const { return 0; }
virtual void f (char *x) const { *x = '\0'; }

View File

@ -7,7 +7,11 @@ public:
virtual ~Base() { }
};
class Derived : public Base { };
class Derived : public Base
{
public:
Derived() {}
};
int main()
{

View File

@ -1,3 +1,13 @@
2010-04-27 Fabien Chêne <fabien.chene@gmail.com>
* testsuite/util/testsuite_error.h: Add empty default constructor
to __gnu_test::test_category and
__gnu_test::test_derived_category.
* src/future.cc: Add empty default constructor to
future_error_category.
* src/system_error.cc: Add default ctor to generic_error_category
and system_error_category.
2010-04-27 Alexander Monakov <amonakov@ispras.ru>
* testsuite/22_locale/codecvt/unshift/char/1.c (test01): Clarify size

View File

@ -1,6 +1,6 @@
// future -*- C++ -*-
// Copyright (C) 2009 Free Software Foundation, Inc.
// Copyright (C) 2009, 2010 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@ -28,6 +28,8 @@ namespace
{
struct future_error_category : public std::error_category
{
future_error_category() {}
virtual const char*
name() const
{ return "future"; }

View File

@ -34,6 +34,8 @@ namespace
struct generic_error_category : public std::error_category
{
generic_error_category() {}
virtual const char*
name() const
{ return "generic"; }
@ -49,6 +51,8 @@ namespace
struct system_error_category : public std::error_category
{
system_error_category() {}
virtual const char*
name() const
{ return "system"; }

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
// Error handling utils for the C++ library testsuite.
//
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@ -29,6 +29,8 @@ namespace __gnu_test
{
struct test_category : public std::error_category
{
test_category() {}
virtual const char*
name() const
{
@ -43,6 +45,8 @@ namespace __gnu_test
struct test_derived_category : public test_category
{
test_derived_category() {}
virtual const char*
name() const
{