clang++ generates code that crashes at runtime for constructor with empty initializer list

Originator:evan
Number:rdar://19510408 Date Originated:
Status: Resolved:
Product:Developer Tools Product Version:
Classification: Reproducible:
 
Description:
The attached code contains a List<T> wrapper for std::vector<T> and two constructors, one default constructor and one that takes a std::initializer_list<T>.

Steps:
1. Compile attached file using "clang++ -std=c++11 main.cpp"
2. Run the attached file using "MallocScribble=1 ./a.out"

Expected:
I expect that "auto keys = new List<std::string>({});" and "auto keys = new List<std::string>();" both create an empty list and both do not crash. Each one can be tested by commenting that one in and commenting the other one out.

Actual:
The code for the default constructor runs fine but the code for the initializer list constructor crashes at runtime. It appears the compiler is generating incorrect code for the initializer list constructor. Poking around the Xcode debugger reveals that the __begin_ std::vector member is 0 but the __end_ std::vector member is 24, which is sizeof(std::string). The size() method returns 1 but get(0) crashes.

This code is a reduced test case from a real app. The real app crashes without any debug options but the reduced code needs MallocScribble=1 to trigger the crash.

Configuration:
clang++ --version:
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

Version:
Xcode Version/Build: Version 6.1.1 (6A2008a)
OS X Version/Build: 10.9.5 (13F34)







Attachment: main.cpp

#include <cassert>
#include <initializer_list>
#include <string>
#include <unordered_map>
#include <vector>

template <typename T>
struct List {
  List() {}
  List(std::initializer_list<T> list) : _data(list) {}

  int size() {
    return _data.size();
  }

  void push(T value) {
    _data.push_back(value);
  }

  T get(int index) {
    assert(index >= 0 && index < size());
    return _data[index];
  }

  std::vector<T> _data;
};

template <typename T>
struct StringMap {
  void set(std::string key, T value) {
    _table[key] = value;
  }

  List<std::string> *keys() {
    auto keys = new List<std::string>({});
    // auto keys = new List<std::string>();
    for (auto &it : _table) {
      keys->push(it.first);
    }
    return keys;
  }

  std::unordered_map<std::string, T> _table;
};

int main() {
  auto map = new StringMap<bool>();
  map->set("foo", false);

  auto keys = map->keys();
  assert(keys->size() == 1);
  assert(keys->get(0) == "foo");
}

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!