https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82565

            Bug ID: 82565
           Summary: Concept and lambda return type deduction cause
                    compilation to crash with "mmap: Cannot allocate
                    memory"
           Product: gcc
           Version: 7.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: haaawk at gmail dot com
  Target Milestone: ---

Created attachment 42378
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42378&action=edit
file that crashes compilation "g++ -fconcepts crash.cpp"

The file I attached crashes the following compilation:

g++ -fconcepts crash.cpp

both on GCC 7.1.1 and GCC 7.2.

GCC 7.1.1 gives the following result:

crash.cpp: In instantiation of ‘run_test()::<lambda(auto:1&)> [with auto:1 =
const std::__cxx11::basic_string<char>]’:
crash.cpp:9:12:   required from here
crash.cpp:49:58: internal compiler error: Segmentation fault
     return object.visit([] (auto& x) { return x.empty(); });

GCC 7.2 gives the following result:

crash.cpp: In instantiation of 'run_test()::<lambda(auto:1&)> [with auto:1 =
const std::__cxx11::basic_string<char>]':
crash.cpp:9:12:   required from here
crash.cpp:49:58: internal compiler error: Segmentation fault
     return object.visit([] (auto& x) { return x.empty(); });
                                                          ^
mmap: Cannot allocate memory

The file compiles correctly after commenting out line 31 which applies Concept
to visit method:

requires Concept<Visitor,
decltype(std::declval<Visitor>()(std::declval<std::string&>()))>()

or after explicit declaration of the return type to "-> bool" on lambda in line
49:

return object.visit([] (auto& x) -> bool { return x.empty(); });

Below I'm pasting the content of the crash.cpp file:

#include<vector>
#include<string>
#include<memory>
#include<iostream>

template<typename T, typename ReturnType>
concept bool Concept() {
    return requires(T t, const std::string& s, const std::vector<int>& v) {
        { t(s) } -> ReturnType;
        { t(v) } -> ReturnType;
    };
}

struct test {
    enum class kind {
        string, vector
    };
    struct data {
        data() { }
        ~data() { }

        union {
            std::string _str;
            std::vector<int> _v;
        };
    };
    kind _kind;
    std::unique_ptr<data> _data;

    template<typename Visitor>
        requires Concept<Visitor,
decltype(std::declval<Visitor>()(std::declval<std::string&>()))>()
    decltype(auto) visit(Visitor&& visitor) const {
        switch (_kind) {
        case kind::string:
            return visitor(_data->_str);
        case kind::vector:
            return visitor(_data->_v);
        }
        abort();
    }

};

bool run_test() {
    test object;
    object._kind = test::kind::string;
    object._data = std::make_unique<test::data>();
    new (&object._data->_str) std::string("hello test");
    return object.visit([] (auto& x) { return x.empty(); });
}

int main() {
    std::cout << run_test() << std::endl;
    return 0;
}

Reply via email to