We have an internal contributor that’s looking at fixing c++20 related failures, focusing on aggregate initialization issues. See [test] Fix aggregate initialization incompatible with c++20 · llvm/llvm-project@f039a2c · GitHub for a related change. They ran into this one in flang (with flang/CMakeLists.txt
modified to use set(CMAKE_CXX_STANDARD 20)
):
FAILED: tools/flang/lib/Parser/CMakeFiles/obj.FortranParser.dir/openmp-parsers.cpp.o
/home/rupprecht/installs/llvm-src/bin/clang++ -DFLANG_INCLUDE_TESTS=1 -DFLANG_LITTLE_ENDIAN=1 -DGTEST_HAS_RTTI=0 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/rupprecht/src/llvm-build/dev/tools/flang/lib/Parser -I/home/rupprecht/src/llvm-project/flang/lib/Parser -I/home/rupprecht/src/llvm-project/flang/include -I/home/rupprecht/src/llvm-build/dev/tools/flang/include -I/home/rupprecht/src/llvm-build/dev/include -I/home/rupprecht/src/llvm-project/llvm/include -isystem /home/rupprecht/src/llvm-project/llvm/../mlir/include -isystem /home/rupprecht/src/llvm-build/dev/tools/mlir/include -isystem /home/rupprecht/src/llvm-build/dev/tools/clang/include -isystem /home/rupprecht/src/llvm-project/llvm/../clang/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -Wno-deprecated-copy -Wno-string-conversion -Wno-ctad-maybe-unsupported -Wno-unused-command-line-argument -Wstring-conversion -Wcovered-switch-default -Wno-nested-anon-types -g -DDEBUGF18 -fno-exceptions -fno-rtti -gsplit-dwarf -std=c++20 -MD -MT tools/flang/lib/Parser/CMakeFiles/obj.FortranParser.dir/openmp-parsers.cpp.o -MF tools/flang/lib/Parser/CMakeFiles/obj.FortranParser.dir/openmp-parsers.cpp.o.d -o tools/flang/lib/Parser/CMakeFiles/obj.FortranParser.dir/openmp-parsers.cpp.o -c /home/rupprecht/src/llvm-project/flang/lib/Parser/openmp-parsers.cpp
In file included from /home/rupprecht/src/llvm-project/flang/lib/Parser/openmp-parsers.cpp:12:
/home/rupprecht/src/llvm-project/flang/lib/Parser/basic-parsers.h:754:16: error: call to deleted constructor of 'Fortran::parser::Verbatim'
return RESULT{};
^ ~~
/home/rupprecht/src/llvm-project/flang/lib/Parser/basic-parsers.h:737:16: note: in instantiation of member function 'Fortran::parser::ApplyConstructor<Fortran::parser::Verbatim, Fortran::parser::TokenStringMatch<false, false>>::ParseOne' requested here
return ParseOne(state);
^
/home/rupprecht/src/llvm-project/flang/lib/Parser/basic-parsers.h:920:25: note: in instantiation of member function 'Fortran::parser::ApplyConstructor<Fortran::parser::Verbatim, Fortran::parser::TokenStringMatch<false, false>>::Parse' requested here
auto result{parser_.Parse(state)};
^
/home/rupprecht/src/llvm-project/flang/lib/Parser/basic-parsers.h:598:49: note: in instantiation of member function 'Fortran::parser::SourcedParser<Fortran::parser::ApplyConstructor<Fortran::parser::Verbatim, Fortran::parser::TokenStringMatch<false, false>>>::Parse' requested here
(std::get<J>(args) = std::get<J>(parsers).Parse(state),
^
/home/rupprecht/src/llvm-project/flang/lib/Parser/basic-parsers.h:741:13: note: in instantiation of function template specialization 'Fortran::parser::ApplyHelperArgs<Fortran::parser::SourcedParser<Fortran::parser::ApplyConstructor<Fortran::parser::Verbatim, Fortran::parser::TokenStringMatch<false, false>>>, Fortran::parser::Parser<Fortran::parser::OmpCancelType>, 0UL, 1UL>' requested here
if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
^
/home/rupprecht/src/llvm-project/flang/lib/Parser/basic-parsers.h:920:25: note: in instantiation of member function 'Fortran::parser::ApplyConstructor<Fortran::parser::OpenMPCancellationPointConstruct, Fortran::parser::SourcedParser<Fortran::parser::ApplyConstructor<Fortran::parser::Verbatim, Fortran::parser::TokenStringMatch<false, false>>>, Fortran::parser::Parser<Fortran::parser::OmpCancelType>>::Parse' requested here
auto result{parser_.Parse(state)};
^
/home/rupprecht/src/llvm-project/flang/lib/Parser/openmp-parsers.cpp:350:1: note: in instantiation of member function 'Fortran::parser::SourcedParser<Fortran::parser::ApplyConstructor<Fortran::parser::OpenMPCancellationPointConstruct, Fortran::parser::SourcedParser<Fortran::parser::ApplyConstructor<Fortran::parser::Verbatim, Fortran::parser::TokenStringMatch<false, false>>>, Fortran::parser::Parser<Fortran::parser::OmpCancelType>>>::Parse' requested here
TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
^
/home/rupprecht/src/llvm-project/flang/lib/Parser/type-parser-implementation.h:29:19: note: expanded from macro 'TYPE_PARSER'
return parser.Parse(state); \
^
/home/rupprecht/src/llvm-project/flang/include/flang/Parser/parse-tree.h:273:15: note: 'Verbatim' has been explicitly marked deleted here
BOILERPLATE(Verbatim);
^
1 error generated.
The issue is that in c++20, declaring (or deleting) constructors makes them no longer constructible with aggregate initialization. The straightforward fix is to just make it a plain struct, and don’t delete any constuctors. That way, we can construct this either as Verbatim{}
for the no-op case or Verbatim{.source=...}
for the 1-arg case:
struct Verbatim {
BOILERPLATE(Verbatim); // <-- delete this line
using EmptyTrait = std::true_type;
CharBlock source;
};
However, parse-tree.h
also has this cautionary comment that all these constructors should be deleted:
// Parse tree node class types do not have default constructors. They
// explicitly declare "T() {} = delete;" to make this clear. This restriction
// prevents the introduction of what would be a viral requirement to include
// std::monostate among most std::variant<> discriminated union members.
// Parse tree node class types do not have copy constructors or copy assignment
// operators. They are explicitly declared "= delete;" to make this clear,
// although a C++ compiler wouldn't default them anyway due to the presence
// of explicitly defaulted move constructors and move assignments.
This comment makes it clear that the default constructor is not desired, but that seems to be effectively side stepped when invoking RESULT{}
(where RESULT
expands to Verbatim
in this case). With c++20, this workaround is no longer valid. So while c++20 isn’t necessarily something flang needs to agree on supporting, it also seems that c++20 is just pointing out an existing issue with the code.
Is anyone familiar with this structure to advise on the best fix to make for this?