This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch] Fix c++/PR42844
On 04/19/2010 01:41 AM, Fabien CHÊNE wrote:
2010-04-18 Fabien Chêne<fabien.chene@gmail.com>
PR c++/42844
* decl.c (check_for_missing_ctor): New.
(diagnose_missing_ctor): New.
(check_initializer): Check for uninitialized const variable, where
the constructor is missing.
* class.c (in_class_defaulted_default_constructor): New.
* cp-tree.h (in_class_defaulted_default_constructor): Declare it.
It seemed to me that check_for_missing_ctor was redundant with
check_for_uninitialized_const_var, so I combined them. Here's the
version I'm committing:
commit ac113d888315b4035329fc0f2a6d19275ba0722c
Author: Fabien Chêne <fabien.chene@gmail.com>
Date: Wed Apr 21 21:24:32 2010 -0400
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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1bab07d..26da21b 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 2605904..a7ed134 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 580f6f8..346b7b4 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/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
index ea06d92..ad3274a 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 0000000..5af4ff2
--- /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 0000000..7b423cc
--- /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 <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> ();
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr27549.C b/gcc/testsuite/g++.dg/tree-ssa/pr27549.C
index 2dc98a2..cd5944d 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 65542b8..e2c5a2d 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/src/future.cc b/libstdc++-v3/src/future.cc
index 967012a..d928948 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 2144801..be6af3b 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 c9f5e47..c2bfed7 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
{