G++ Compiler bug with compiling variadic function? - c++

I have encountered a very weird issue when trying to compile this code:
#include <iostream>
struct A
{
int get()
{
return 5;
}
};
static void requestWork(A& program,size_t bytes)
{
}
template<typename T, typename... Args>
static void requestWork( A& program,size_t bytes,T t1, Args... args)
{
std::cout << t1 << "\n";
if (program.get() == bytes)
{
requestWork(program,bytes + sizeof(t1),args...);
}
else
{
requestWork(program,bytes + sizeof(t1), args...); //this line gets complaints
}
}
int main(int args, char* argsc[])
{
A a;
requestWork(a,0,0,0,0,0);
return 0;
}
This code doesn't actually do anything; it's a simplified version of some code I had written previously. For some reason, I get an error on the first requestWork recursive call:
recursively required from 'void requestWork(A&, size_t, T, Args ...) [with T = int; Args = {int, int}; size_t = long long unsigned int]'
I can't find anything online about this error and the weirdest part is that my code compiles fine; if I press build + run again (my IDE was Code::Blocks, I then migrated to CodeLite and ran into the same issue) the code runs fine. Anyone know anything about this?
I initially thought it was Code::Blocks being weird again but upon switching to CodeLite, I ran into the same issue, so I'm fairly certain it's a compiler issue. I'm using g++ 12.2.0. It came with my installation of Mingw-w64.

Related

Segmentation fault on gcc caused by lambda wrapper over variadic template function call

I've spent quite a few hours today trying to understand why this code segfaults on g++6.2 and g++7.0, while happily working as intended on clang++3.9 (and 4.0).
I reduced the issue to a 85 lines self-contained code snippet, which does not segfault upon normal execution, but always reports an error under UBSAN.
The issue is reproducible on wandbox, by compiling with g++7, enabling optimizations and passing -fsanitize=undefined as an extra flag.
This is what UBSAN reports:
prog.cc: In function 'int main()':
prog.cc:61:49: warning: 'ns#0' is used uninitialized in this function [-Wuninitialized]
([&] { ([&] { n.execute(ns...); })(); })();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
prog.cc:28:10: note: 'ns#0' was declared here
auto execute(TNode& n, TNodes&... ns)
^~~~~~~
prog.cc:30:9: runtime error: member call on null pointer of type 'struct node_then'
g++ claims that ns#0 is uninitialized inside the "lambda gibberish" (which simulates the for_tuple from the original snippet). Now, some very interesting things occur:
If I remove the "lambda gibberish", transforming line 61 into
n.execute(ns...);
then UBSAN stops complaining.
If I change the capture list from [&] to [&n, &ns...], UBSAN stops complaining as well:
([&](auto) { ([&n, &ns...] { n.execute(ns...); })(); })(0);
...wait what? How is that different from [&]?
Applying the above discoveries to the original code snippet fixes the segfaults.
Is this a g++ bug? Or is there any undefined behavior in my code?
This has nothing to do with temporaries: it's a gcc7.0 optimizer bug. This is a simpler reproducer:
#include <utility>
struct root
{
template <typename TNode, typename... TNodes>
void start(TNode n, TNodes... ns)
{
n->execute(ns...);
}
};
template <typename TParent>
struct node_then
{
TParent *_p;
node_then(TParent *p) : _p{ p }
{
}
auto execute()
{
}
template <typename TNode, typename... TNodes>
auto execute(TNode n, TNodes... ns)
{
n->execute(ns...);
}
template <typename... TNodes>
auto start(TNodes... ns)
{
_p->start(this, ns...);
}
};
template <typename TParent>
struct node_wait_all
{
TParent *_p;
node_wait_all(TParent *p) : _p{ p }
{
}
template <typename TNode, typename... TNodes>
auto execute(TNode n, TNodes... ns)
{
([&] { ([&] { n->execute(ns...); })(); })();
}
template <typename... TNodes>
auto start(TNodes... ns)
{
_p->start(this, ns...);
}
};
int main()
{
//node_wait_all<root> obj(new root());
//node_then<node_wait_all<root>> obj2(new node_wait_all<root>(new root()));
node_then<node_then<node_wait_all<root>>> obj3(new node_then<node_wait_all<root>>(new node_wait_all<root>(new root())));
obj3.start();
}
Output:
prog.cc: In function 'int main()':
prog.cc:67:1: internal compiler error: in visit_ref_for_mod_analysis, at ipa-prop.c:2308
}
^
0x96c4d6 visit_ref_for_mod_analysis
/home/heads/gcc/gcc-source/gcc/ipa-prop.c:2308
0x8f615d walk_stmt_load_store_addr_ops(gimple*, void*, bool (*)(gimple*, tree_node*, tree_node*, void*), bool (*)(gimple*, tree_node*, tree_node*, void*), bool (*)(gimple*, tree_node*, tree_node*, void*))
/home/heads/gcc/gcc-source/gcc/gimple-walk.c:817
0x9761a2 ipa_analyze_params_uses_in_bb
/home/heads/gcc/gcc-source/gcc/ipa-prop.c:2335
0x9761a2 analysis_dom_walker::before_dom_children(basic_block_def*)
/home/heads/gcc/gcc-source/gcc/ipa-prop.c:2415
0x10c8472 dom_walker::walk(basic_block_def*)
/home/heads/gcc/gcc-source/gcc/domwalk.c:265
0x977ceb ipa_analyze_node(cgraph_node*)
/home/heads/gcc/gcc-source/gcc/ipa-prop.c:2486
0x1108f0a ipcp_generate_summary
/home/heads/gcc/gcc-source/gcc/ipa-cp.c:5036
0xa4759c execute_ipa_summary_passes(ipa_opt_pass_d*)
/home/heads/gcc/gcc-source/gcc/passes.c:2167
0x7d6b45 ipa_passes
/home/heads/gcc/gcc-source/gcc/cgraphunit.c:2311
0x7d6b45 symbol_table::compile()
/home/heads/gcc/gcc-source/gcc/cgraphunit.c:2425
0x7d8616 symbol_table::compile()
/home/heads/gcc/gcc-source/gcc/cgraphunit.c:2587
0x7d8616 symbol_table::finalize_compilation_unit()
/home/heads/gcc/gcc-source/gcc/cgraphunit.c:2584
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
Link: http://melpon.org/wandbox/permlink/E11fOumFJda6OW6m
To aid in this code's comprehension I'm using a powerful debugging tool: paint.exe

Possible gcc bug with C++14 polymorphic lambdas?

I've found a strange behavior using polymorphic C++14 lambdas (lambdas with auto in their parameters):
Snippet 0:
#include <iostream>
template<typename T> void doLambda(T&& mFn)
{
std::forward<T>(mFn)(int{0});
}
template<typename T> void test(T&& mV)
{
doLambda([&mV](auto mE)
{
std::forward<decltype(mV)>(mV);
});
}
int main() { test(int{0}); return 0; }
clang++ 3.5.1: the snippet compiles and runs successfully.
g++ 4.9.2: the snippet fails to compile:
example.cpp: In instantiation of 'test(T&&)::<lambda(auto:1)> [with auto:1 = int; T = int]':
5 : required from 'void doLambda(T&&) [with T = test(T&&) [with T = int]::]'
13 : required from 'void test(T&&) [with T = int]'
18 : required from here
12 : error: 'mV' was not declared in this scope
std::forward<decltype(mV)>(mV);
^
Compilation failed
Snippet 1:
The only difference from snippet 0 is that the auto inside the lambda was replaced to int.
#include <iostream>
template<typename T> void doLambda(T&& mFn)
{
std::forward<T>(mFn)(int{0});
}
template<typename T> void test(T&& mV)
{
doLambda([&mV](int mE)
{
std::forward<decltype(mV)>(mV);
});
}
int main() { test(int{0}); return 0; }
clang++ 3.5.1: the snippet compiles and runs successfully.
g++ 4.9.2: the snippet compiles and runs successfully.
Snippet 3:
The lambda is now called in-place. auto is still used.
#include <iostream>
template<typename T> void test(T&& mV)
{
[&mV](auto mE)
{
std::forward<decltype(mV)>(mV);
}(int{0});
}
int main() { test(int{0}); return 0; }
clang++ 3.5.1: the snippet compiles and runs successfully.
g++ 4.9.2: the snippet compiles and runs successfully.
Why is g++ complaining about snippet 0? Is there anything wrong in my code? Is this a known bug or should I submit this?
As stated in the comments, this behavior is indeed a gcc bug.

Compiler error when using constexpr and lambda

I encountered a problem when using constexpr functions together with lambdas.
The following code is a minimal version which reproduces the error:
#include <iostream>
constexpr unsigned bar(unsigned q) {
return q;
}
template<unsigned N>
unsigned foo() {
return N;
}
template<typename F>
void print(F f) {
std::cout << f() << std::endl;
}
template<unsigned Q>
int stuff() {
constexpr unsigned n = bar(Q);
print([]() { return foo<n>(); });
}
int main() {
stuff<13>();
}
When compiling with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) there are the following compiler errors:
constexpr_template.cpp: In lambda function:
constexpr_template.cpp:24:9: instantiated from ‘stuff() [with unsigned int Q = 13u]::<lambda()>’
constexpr_template.cpp:24:2: instantiated from ‘int stuff() [with unsigned int Q = 13u]’
constexpr_template.cpp:29:12: instantiated from here
constexpr_template.cpp:24:32: error: no matching function for call to ‘foo()’
constexpr_template.cpp:24:32: note: candidate is:
constexpr_template.cpp:9:10: note: template<unsigned int N> unsigned int foo()
Now the strange part is, if constexpr unsigned n = bar(Q); is changed into constexpr unsigned n = Q; it works.
What is also working is print([]() { return foo<bar(Q)>(); });...
Is this a bug in GCC or what am I doing wrong?
Gcc 4.6 was the first version to support constexpr, and it is not unusual for minor bugs to be present upon release of such features. You can verify from this Live Example on Coliru that gcc 4.8.1 and Clang 3.4 SVN correctly parse your code. You probably should upgrade your compiler accordingly.

Weird error when instantiating template function

I have the following template function:
template <std::size_t first, std::size_t last, typename T>
bool in_range(T& in)
{
for(auto i = in.begin(); i!=in.end(); ++i)
if(*i<first || *i>last)
return false;
return true;
}
but when I try to use it as such:
std::vector<int> test;
test.push_back(1);
test.push_back(5);
test.push_back(6);
std::cout<<in_range<4,7>(test);
I get this weird error:
main.cpp: In instantiation of 'bool in_range(T&) [with long long unsigned int first = 4ull; long long unsigned int last = 7ull; T = std::vector<int>]':
main.cpp:31:34: required from here
What am I doing wrong?
EDIT: full build log: http://pastebin.com/Cwemq2Hk
If I build that with C++11 support enabled, then it compiles. Here is a demonstation.
Before C++11, auto had a different meaning, and so auto i = ... was invalid - it declared a variable with no type.
I guess you're using GCC; depending on the version, you'll need to specify either -std=c++0x or -std=c++11 as a command-line option.

How to fix 'expected primary-expression before' error in C++ template code?

Here's yet another VC9 vs. GCC 4.2 compile error problem. The following code compiles fine with VC9 (Microsoft Visual C++ 2008 SP1) but not with GCC 4.2 on Mac:
struct C
{
template< typename T >
static bool big() { return sizeof( T ) > 8; }
};
template< typename X >
struct UseBig
{
static bool test()
{
return X::big< char >(); // ERROR: expected primary-expression
} // before 'char'
};
int main()
{
C::big< char >();
UseBig< C >::test();
return 0;
}
Any ideas how I can fix this?
That should be
return X::template big< char >();
Dependent names from templates are taken to not be types unless you specify that they are via typename and assumed to not be templates unless specified via template.