llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.24k stars 12.07k forks source link

Differences of lifetime of temporary objects during list-initialization with g++,MSVS and icpc #29450

Open llvmbot opened 8 years ago

llvmbot commented 8 years ago
Bugzilla Link 29080
Version 3.8
OS Linux
Reporter LLVM Bugzilla Contributor
CC @DougGregor,@ecatmur,@pogo59

Extended Description

Following this stackoverflow discussion http://stackoverflow.com/questions/39025342/lifetime-of-temporary-objects-during-list-initialization

The behaviour of clang differs from the behaviour of other compilers for this code:

#include <iostream>
#include <vector>

struct ID{ 
  static int cnt;
  // the number of living object of class ID at the moment of creation:  
  int id;

  ID():id(++cnt){}

  ~ID(){
     cnt--;
  }
};

int ID::cnt=0;

int main(){
  int arr[]{ID().id, ID().id};

  std::cout<<" Array: "<<arr[0]<<", "<<arr[1]<<"\n";
}

The clang compiled program prints out 1, 2, but programs produced by other compilers give 1, 1.

Actually, I don't know what the right behaviour should be, but because other compilers seem to agree, I report the bug here.

ecatmur commented 7 years ago

This is DR core issue 1343 "Sequencing of non-class initialization". Clang is conformant to P0570R0 (and thus to C++17).

llvmbot commented 8 years ago

The problem seems to be the aggregate initialization:

  struct S{
      int a;
      int b;
  } s{ID().id, ID().id};
  std::cout<<" Struct: "<<s.a<<", "<<s.b<<"\n";

yields Struct 1, 2 but it should be Struct 1, 1 - because the temporaries should be destructed at the end of the full-expression - in this case ID().id.