This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 
     { 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]