diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6dec7c38cad..a996461cca0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2010-04-27 Fabien Chêne + Jason Merrill + + 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 PR c++/9335 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1bab07dd42c..26da21b8c82 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 26059046468..a7ed134a52d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 580f6f820fb..346b7b43646 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2924689dce..21d9e0d1756 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2010-04-27 Fabien Chêne + + * 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 PR fortran/18918 diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C index ea06d92530f..ad3274a2ea9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C new file mode 100644 index 00000000000..5af4ff217f3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C @@ -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" } +} diff --git a/gcc/testsuite/g++.dg/init/pr42844.C b/gcc/testsuite/g++.dg/init/pr42844.C new file mode 100644 index 00000000000..7b423ccb64b --- /dev/null +++ b/gcc/testsuite/g++.dg/init/pr42844.C @@ -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 +struct F : A {}; // { dg-message "user-provided default constructor" } + +template +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 const f; // { dg-error "uninitialized const" } + extern F const fext; + + G const g; // { dg-error "uninitialized const" } + extern G const gext; +} + +struct H {}; // { dg-message "user-provided default constructor" } + +struct I : A {}; // { dg-message "user-provided default constructor" } + +template +void g () +{ + T const t; // { dg-error "uninitialized const" } + extern T const text; +} + +template void g (); +template void g (); diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr27549.C b/gcc/testsuite/g++.dg/tree-ssa/pr27549.C index 2dc98a22019..cd5944d2439 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr27549.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr27549.C @@ -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'; } diff --git a/gcc/testsuite/g++.old-deja/g++.mike/dyncast8.C b/gcc/testsuite/g++.old-deja/g++.mike/dyncast8.C index 65542b89535..e2c5a2df9a6 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/dyncast8.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/dyncast8.C @@ -7,7 +7,11 @@ public: virtual ~Base() { } }; -class Derived : public Base { }; +class Derived : public Base +{ +public: + Derived() {} +}; int main() { diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 501037e790a..5ff9d83f1c8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2010-04-27 Fabien Chêne + + * 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 * testsuite/22_locale/codecvt/unshift/char/1.c (test01): Clarify size diff --git a/libstdc++-v3/src/future.cc b/libstdc++-v3/src/future.cc index 967012a8ca6..d9289487bab 100644 --- a/libstdc++-v3/src/future.cc +++ b/libstdc++-v3/src/future.cc @@ -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"; } diff --git a/libstdc++-v3/src/system_error.cc b/libstdc++-v3/src/system_error.cc index 21448018204..be6af3bced8 100644 --- a/libstdc++-v3/src/system_error.cc +++ b/libstdc++-v3/src/system_error.cc @@ -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"; } diff --git a/libstdc++-v3/testsuite/util/testsuite_error.h b/libstdc++-v3/testsuite/util/testsuite_error.h index c9f5e47f24d..c2bfed737da 100644 --- a/libstdc++-v3/testsuite/util/testsuite_error.h +++ b/libstdc++-v3/testsuite/util/testsuite_error.h @@ -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 {