Bug 38233 - [4.4 Regression] 'map' value type + new uninitted const member warnings causes error
Summary: [4.4 Regression] 'map' value type + new uninitted const member warnings cause...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: 4.4.0
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2008-11-23 08:46 UTC by Chris Demetriou
Modified: 2008-11-28 23:39 UTC (History)
5 users (show)

See Also:
Host: i686-linux
Target: i686-linux
Build: i686-linux
Known to work: 4.3.2
Known to fail:
Last reconfirmed: 2008-11-26 20:10:57


Attachments
preprocessed source from test case in bug report. (16.57 KB, text/plain)
2008-11-23 08:48 UTC, Chris Demetriou
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Demetriou 2008-11-23 08:46:34 UTC
Consider the code:

#include <map>

class a {
 public:
  a();
};

class b {
 public:
  // implicit default ctor
  bool operator<(const b& rhs) const;

 private:
  a a_val;
};

typedef std::map<b, int> my_map;

void func() {
  my_map::value_type x;
}


That compiled correctly with 4.3.2.  It fails to compile with pre-4.4 trunk:

Using built-in specs.
Target: i686-linux
Configured with: ../trunk/configure --enable-languages=c,c++ --build=i686-linux --host=i686-linux --target=i686-linux --prefix=/g/users/cgd/proj/gcc-trunk/bld/../inst
Thread model: posix
gcc version 4.4.0 20081123 (experimental) (GCC) 

with the error:

In file included from [...]/bin/../lib/gcc/i686-linux/4.4.0/../../../../include/c++/4.4.0/bits/stl_algobase.h:71,
                 from [...]/bin/../lib/gcc/i686-linux/4.4.0/../../../../include/c++/4.4.0/bits/stl_tree.h:67,
                 from [...]/bin/../lib/gcc/i686-linux/4.4.0/../../../../include/c++/4.4.0/map:65,
                 from test2.cc:1:
[...]/bin/../lib/gcc/i686-linux/4.4.0/../../../../include/c++/4.4.0/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair() [with _T1 = const b, _T2 = int]':
test2.cc:20:   instantiated from here
[...]/bin/../lib/gcc/i686-linux/4.4.0/../../../../include/c++/4.4.0/bits/stl_pair.h:84: error: uninitialized member 'std::pair<const b, int>::first' with 'const' type 'const b'


Looking at the preprocessed source (which i'll attach shortly), I see that pair's default ctor is:

      pair()
      : first(), second() { }

I don't know if that's "right," but the C++98 std says that:

"Initializes its members as if implemented: pair() : first(T1()), second(T2()) {}"

(20.2.2, paragraph 2.)

If I change the pair() ctor to be:

      pair()
      : first(_T1()), second(_T2()) { }

(by hacking the preprocessed source), the result compiles correctly.

(I'm *so* far from an expert on STL that I'm not 100% sure that sample code is actually valid, but on its face it seems reasonable at least, and 4.3.x accepted it, and Comeau's test drive accepts it as well.)
Comment 1 Chris Demetriou 2008-11-23 08:48:13 UTC
Created attachment 16750 [details]
preprocessed source from test case in bug report.
Comment 2 Andrew Pinski 2008-11-23 14:41:42 UTC
There is a defect report which changed C++98 dealing with default initialization which might be causing this issue, see DR178.
Comment 3 Paolo Carlini 2008-11-24 11:10:29 UTC
The default constructor of pair just implements DR 265, this is *very* old:

  http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#265

This is possibly a C++ front-end issue, because lately nothing changed in the library in this area. I'll CC Jason.
Comment 4 Paolo Carlini 2008-11-26 09:39:18 UTC
The below is a pure C++ testcase, which EDG accepts and mainline rejects. Jason can you look a bit into it? Thanks in advance!

////////////////

template<class _T1, class _T2>
  struct pair
  {
    _T1 first;
    _T2 second;

    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // 265.  std::pair::pair() effects overly restrictive
    /** The default constructor creates @c first and @c second using their
     *  respective default constructors.  */
    pair()
    : first(), second() { }
};

class a {
 public:
  a();
};

class b {
 public:
  // implicit default ctor
  bool operator<(const b& rhs) const;

 private:
  a a_val;
};

typedef pair<const b, int> my_pair;

void func() {
  my_pair x;
}
Comment 5 Jason Merrill 2008-11-28 23:36:58 UTC
Subject: Bug 38233

Author: jason
Date: Fri Nov 28 23:35:37 2008
New Revision: 142265

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=142265
Log:
        PR c++/38233
        * init.c (perform_member_init): Fix value-initialization.
        (build_value_init_1): Add assert to catch cases that will break
        in the gimplifier.
        (build_default_init): Remove.
        * cp-tree.h: Remove its prototype.
        * pt.c (tsubst_expr) [DECL_EXPR]: Use build_value_init for
        value-initialization.

Added:
    trunk/gcc/testsuite/g++.dg/init/array25.C
    trunk/gcc/testsuite/g++.dg/init/value4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/init.c
    trunk/gcc/cp/pt.c
    trunk/gcc/testsuite/ChangeLog

Comment 6 Jason Merrill 2008-11-28 23:39:17 UTC
Fixed.