Symbol not found in debugger only, when having templated template argument - c++

Given the following code as test.cpp,
Building using clang++ -c test.cpp -o test.o -g; clang++ test.o -g -all_load, setting breakpoint at return a.getValue(); and attempting to p a.getValue() from lldb:
Running llvm 3.8.0 on unix - works perfectly
Running xcode or llvm 8.1.0 on OSX - I get the following error:
error: Couldn't lookup symbols:
__ZNK4Test7MyClassILi2ELi3EE8getValueEv
Two interesting facts:
If I remove the last template argument - all works well
If I build directly without going through the .o file (clang++ test.cpp) = all goes well
Anyone has a clue what is going on, and how can it be fixed?
namespace Test{
template<class T>
class BLA{
public:
T getBlaValue() const{return 3;}
};
template <int N1, int N2, template<class T>class Impl = BLA>
class MyClass {
private:
public:
__attribute__((used))
int getValue() const
{
return 3;
}
};
}
int main()
{
Test::MyClass<2, 3> a;
return a.getValue();
}

Related

gcc 4.8 failed to check type conversion in c++ template

I'm trying to update a c++ project's compiler from 4.8.4 to 7.5.0.
The codes can be well compiled with g++4.8.4. However, when I try to compile it with newer g++ 7.5.0. Lots of Werror=conversion errors are triggered.
Here is the demo code abstracted from my project:
// main.cc
template <typename T>
int Hello(T obj) {
float arg = 1.0;
// return obj.func(arg); // good, error detected for both g++ 4.8.4 and 7.5.0
return obj.func(arg) * 2; // failed to detect conversion error for 4.8.4, success for 7.5.0
}
class A {
public:
int func(int a) {
return a;
}
};
int main() {
A a;
Hello(a);
return 0;
}
build:
g++ main.cc -Werror=conversion
As commented above, in a c++ template function, g++4.8 failed to detect the type conversion error when it's in a expression. But it will sucess if it is alone.
I'm very curious about this.
My Question:
Is this a bug of g++4.8? Why does expression matter?

Why does g++ accept a reference type with missing underlying type?

I was meaning to add a copy constructor to a class but forgot to add the type. g++ 5.4.0 compiled the class successfully.
Here's a minimal program that g++ 5.4.0 compiles and builds successfully.
struct Foo
{
Foo(const&) {}
Foo() {}
};
int main()
{
Foo f1;
Foo f2 = f1;
}
Why does g++ not report Foo(const&) {} as an error?
This seems to be a defect in my installation of g++ 5.4.0.
It fails to compile using g++ 6.3 at https://ideone.com/D0vGrw.
I have used the same block of code.
struct Foo
{
Foo(const&) {}
Foo() {}
};
int main()
{
Foo f1;
Foo f2 = f1;
}
It also fails to compile using g++ 5.4.0 at Wandbox.

Program compiles using clang++, but g++ exhausts the RAM and fails

I considered the C++11-based enum bitset introduced here. I came up with some sample program:
#include <bitset>
#include <type_traits>
#include <limits>
template <typename TENUM>
class FlagSet {
private:
using TUNDER = typename std::underlying_type<TENUM>::type;
std::bitset<std::numeric_limits<TUNDER>::max()> m_flags;
public:
FlagSet() = default;
FlagSet(const FlagSet& other) = default;
};
enum class Test
{
FIRST,
SECOND
};
int main(int argc, char *argv[])
{
FlagSet<Test> testFlags;
return 0;
}
The program compiles just fine using clang++ (clang version 3.8.1 (tags/RELEASE_381/final)) via clang++ -std=c++11 -o main main.cc.
However, if I use g++ (g++ (GCC) 6.2.1 20160830) via g++ -std=c++11 -o main main.cc instead, the compiler eventually exhausts system memory. Is this an issue with g++ or is this code somehow not compliant with the standard?
std::bitset<std::numeric_limits<TUNDER>::max()> is 256 MiB in size (assuming 32-bit int). It's great that clang successfully compiles it, but it's not particularly surprising that gcc runs out of memory.
If you're intending to use the enumerators as bitset indices you'll have to pass the largest enumerator in as a separate template parameter; there is as yet (Max and min values in a C++ enum) no way to find the range of an enumeration.
Example:
template <typename TENUM, TENUM MAX>
class FlagSet {
private:
std::bitset<MAX + 1> m_flags;
public:
FlagSet() = default;
FlagSet(const FlagSet& other) = default;
};
enum class Test
{
FIRST,
SECOND,
MAX = SECOND
};
FlagSet<Test, Test::MAX> testFlags;

Can't compile program with clang

I`am trying to compile code bellow. GCC compile it, but clang not.
Error: no member named 'sa' in 'A' static void sf() {A::sa('j');}
What's problem?
test.cpp:
template<typename T>
class A
{
private:
public:
void f() {this->a('j');}
static void sf() {A::sa('j');}
#ifdef U
void a(char x) {}
static void sa(char x) {}
#endif
};
UPD:
I use compilers, that included in Android NDK r10c
gcc 4.9:
cd C:\Tools\android-ndk-r10c\toolchains\x86-4.9\prebuilt\windows-x86_64\bin
clang++.exe -c C:\Users\Barkov_V\Desktop\test.cpp
clang 3.5:
cd C:\Tools\android-ndk-r10c\toolchains\llvm-3.5\prebuilt\windows-x86_64\bin
i686-linux-android-gcc-4.9.exe -c C:\Users\Barkov_V\Desktop\test.cpp

Forcing template function instantiation in class

I have a function that is declared like:
template<typename T>
void MyFunction();
And a class:
template<typename T>
class MyClass
{
public:
typedef void (*Function_T)();
Function_T m_Func;
void DoSomething()
{
m_Func = &MyFunction<T>;
}
}
When I use the class, I undefined symbols error on MyFunction<T>.
If I change DoSomething to
void DoSomething()
{
m_Func = &MyFunction<T>;
return;
MyFunction<T>();
}
Everything works, but that looks like a workaround and will probably not work with optimization.
I cannot add
template void MyFunction<T>;
to the class because it says it cannot be in class. Is there any other way I can force instantiation of the function?
Edit:
I was able to write a test that fails, but in g++ it has a different message and actually a compiler error: http://ideone.com/RbMnh
Your code will work with optimization as well. Although, I don't know why simply m_Func = &MyFunction<T> doesn't work. GCC 4.3.4 compiles it fine. Which compiler you're using?
And you can also do this:
void DoSomething()
{
if ( false) MyFunction<T>();
m_Func = &MyFunction<T>;
return;
}
By the way, the function pointer type is incorrectly defined. It should be this:
typedef void (*Function_T)();
// ^^ put this!
Your code compiles fine for me using GCC, so I'm not sure if this solution solves your particular problem, but you can explicitly instantiate template functions like so:
// Template function defined:
template <typename T>
void MyFunction() {
// body
}
// Template function instantiated:
template void MyFunction<int>();
The issue can be either a compiler bug, or an error in the parts of the code that you are not showing. Try to build a minimal example that reproduces the problem, this is the minimal example that I have been able to produce, and compiles fine with both clang++ 2.8 and g++ 4.4/4.5:
drodriguez#drodriguez-desktop:/tmp$ cat test.cpp
#include <iostream>
template <typename T>
void function() {
}
template <typename T>
struct type {
typedef void (*Func)();
Func _f;
void f() {
_f = &function<T>;
}
};
int main() {
type<int> t;
t.f();
std::cout << t._f << std::endl;
}
drodriguez#drodriguez-desktop:/tmp$ /usr/bin/clang++ --version
clang version 2.8 (branches/release_28)
Target: x86_64-pc-linux-gnu
Thread model: posix
drodriguez#drodriguez-desktop:/tmp$ /usr/bin/clang++ -o test test.cpp && ./test
1
drodriguez#drodriguez-desktop:/tmp$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
drodriguez#drodriguez-desktop:/tmp$ g++-4.4 -o test test.cpp && ./test
1