Ælex
Ælex

Reputation: 14839

gcc 4.7.3 internal compiler error when using make_shared with a constructor

I understand where the problem is, I'm just not sure why am I not getting any error output from gcc.

The lines in question which generate the issue are:

std::string type,rel,pred;
std::tie( type, rel, pred ) = tuple;
auto supertype = std::make_shared<Node>( Token( type ) ); // This
auto predicate = std::make_shared<Node>( Token( pred ) ); // and this

FYI, Node Ctor is:

Node ( Token & token )

If I do this, I get no error:

auto type_token = Token( type );
auto pred_token = Token( pred );
auto supertype = std::make_shared<Node>( type_token );
auto predicate = std::make_shared<Node>( pred_token );

My GCC is:

posix gcc version 4.7.3 (Debian 4.7.3-8)

The actual error is:

> Internal compiler error: Error reporting routines re-entered. Please
> submit a full bug report, with preprocessed source if appropriate. See
> <file:///usr/share/doc/gcc-4.7/README.Bugs> for instructions.

Funnily enough, this directory above doesn't even exist.

What's wrong with constructing an object within the make_shared constructor?

Upvotes: 2

Views: 1157

Answers (1)

Casey
Casey

Reputation: 42554

A temporary object cannot bind to a non-const lvalue reference. You therefore cannot pass one to the specified Node constructor. The compiler should reject:

Node node1(Token(type));
Node node2(Token(pred));

The same is true for trying to get std::make_shared to perform the same initialization internally with your code:

auto supertype = std::make_shared<Node>( Token( type ) );
auto predicate = std::make_shared<Node>( Token( pred ) );

You are trying to get make_shared to pass that temporary object to the non-const lvalue constructor. The compiler should diagnose the program as ill-formed and fail to compile it. That is notably NOT the same thing as crashing with an ICE, which always indicates a compiler bug.

Workaround is to either do as you suggest in your "but this does work" code - pass an lvalue reference to make_shared - or to write an rvalue reference constructor for Node:

Node(Token&&);

EDIT: I think this is GCC bug# 56869 which appears to have been fixed in 4.6.4 and 4.7.4 and was closed on 2013-11-18. If anyone reading this can easily run this testcase in 4.7.4:

#include <memory>
#include <string>

struct Token {
  Token(std::string lex);
};

struct Node {
  Node(Token& token);
};

int main() {
    auto supertype = std::make_shared<Node>(Token{"foo"});
    auto predicate = std::make_shared<Node>(Token{"bar"});
}

please post the results in a comment.

Upvotes: 3

Related Questions