Explicit specialization of Member after instantiation - Only in Xcode - c++

I have a software which I am compiling, that compiles and works fine on Windows 10 with VS2015 and Ubuntu 16.04 with g++ 5.4. But on the latest version of Xcode, it does not.
I have a header class with the following:
template<typename Dtype>
string device_type_name() const;
virtual string device_type_name_void() const = 0;
virtual string device_type_name_bool() const = 0;
And I have the implementation as such:
template<>
string DeviceProgram::device_type_name<void>() const {
return device_type_name_void();
}
template<>
string DeviceProgram::device_type_name<bool>() const {
return device_type_name_bool();
}
Unfortunately, only on osx I get the error:
device_program.cpp:410: error: explicit specialization of 'device_type_name<bool>' after instantiation
I tried to remove the string device_type_name() const; etc. instantiation line, but if I do that, then I get the errors:
device_program.cpp:409: error: extraneous 'template<>' in declaration of variable 'device_type_name'
device_program.cpp:410: error: redefinition of 'device_type_name'
Furthermore, I am unable to do things like:
this->device_type_name<Dtype>()
Please help

Related

Opaque error message for Hello World LLVM pass in C++

I wrote a simple Hello World LLVM pass using the new pass manager.
It is important to note that I did not obtain the entire LLVM source and write the pass somewhere in this source tree.
Instead I installed llvm with
sudo apt install llvm
However when I want to compile my pass code to a dynamic library to run it with opt as a plugin I get the following error message (and yes, later on I will also use cmake for this but it gave me a similar error):
$ clang -shared -I/usr/include/llvm-13 -I/usr/include/llvm-c-13 -o libpass_test.so pass_test.cpp
In file included from pass_test.cpp:1:
In file included from /usr/include/llvm-13/llvm/IR/PassManager.h:48:
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:85:16: error: member reference base type 'bool (llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)' is not a structure or union
return Pass.run(IR, AM, ExtraArgs...);
~~~~^~~~
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:67:12: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run' requested here
explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
^
/usr/include/llvm-13/llvm/IR/PassManager.h:547:29: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::PassModel' requested here
Passes.emplace_back(new PassModelT(std::forward<PassT>(Pass)));
^
pass_test.cpp:29:6: note: in instantiation of function template specialization 'llvm::PassManager<llvm::Function>::addPass<bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)>' requested here
FPM.addPass(passHook);
^
In file included from pass_test.cpp:1:
In file included from /usr/include/llvm-13/llvm/IR/PassManager.h:48:
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:88:44: error: type 'bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)' cannot be used prior to '::' because it has no members
StringRef name() const override { return PassT::name(); }
^
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:67:12: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::name' requested here
explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
^
/usr/include/llvm-13/llvm/IR/PassManager.h:547:29: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::PassModel' requested here
Passes.emplace_back(new PassModelT(std::forward<PassT>(Pass)));
^
pass_test.cpp:29:6: note: in instantiation of function template specialization 'llvm::PassManager<llvm::Function>::addPass<bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)>' requested here
FPM.addPass(passHook);
^
2 errors generated.
The source code is this:
pass_test.h:
#ifndef PASS_TEST_H
#define PASS_TEST_H
using namespace llvm;
class PassTest : public PassInfoMixin<PassTest> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
#endif
pass_test.cpp:
#include <llvm/IR/PassManager.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Passes/PassPlugin.h>
#include <llvm/Support/raw_ostream.h>
#include "pass_test.h"
//------------------------------------------------------------------------------
// The pass functionality
//------------------------------------------------------------------------------
PreservedAnalyses PassTest::run(Function &F, FunctionAnalysisManager &AM)
{
errs() << F.getName() << "\n";
return PreservedAnalyses::all();
}
//------------------------------------------------------------------------------
// Register the pass as a plugin for opt
//------------------------------------------------------------------------------
// the hook of my pass for opt
bool passHook(StringRef Name, FunctionPassManager &FPM,
ArrayRef<PassBuilder::PipelineElement>)
{
if (Name != "pass_test")
return false;
FPM.addPass(passHook);
return true;
}
// the pass builder hook using my pass hook
void builderHook(PassBuilder &PB)
{
PB.registerPipelineParsingCallback(passHook);
}
// information for this specific pass
llvm::PassPluginLibraryInfo getPassTestPluginInfo()
{
return {LLVM_PLUGIN_API_VERSION, "pass_test",
LLVM_VERSION_STRING, builderHook};
}
// public entry for my pass
extern "C" LLVM_ATTRIBUTE_WEAK llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo()
{
return getPassTestPluginInfo();
}
I am happy for any hint what the actual problem is because I don't understand what exactly this error message is telling me.

Error binding properties and functions in emscripten

I'm trying to use emscripten to compile a c++ class and expose bindings. I'm running into an error from the compiler.
#include <emscripten/bind.h>
#include <emscripten/emscripten.h>
using namespace emscripten;
class MyClass {
private:
int _year;
int _month;
int _day;
public:
MyClass() { }
MyClass(int year, int month, int day);
int getMonth();
void setMonth(int);
int getYear();
void setYear(int);
int getDay();
void setDay(int);
bool isLeapYear();
int daysInMonth();
void increment();
void decrement();
};
EMSCRIPTEN_BINDINGS(my_sample_class) {
class_<MyClass>("MyClass")
.constructor<>()
.constructor<int, int, int>()
.function("getMonth", &MyClass::getMonth)
.function("increment", &MyClass::increment)
.function("decrement", &MyClass::decrement)
.property("year",&MyClass::getYear, &MyClass::setYear )
//.property("month", &MyClass::getMonth, &MyClass::setMonth )
//.property("day",&MyClass::getDay, &MyClass::setDay )
;
}
The compiler has no problems with the constructors or the function binding. I run into a problem with the property binding. I only have one uncommented to minimize the errors that I get back (they are just repeats of the same error but for different lines). Here are the errors that I'm getting back.
In file included from MyDate.cpp:1:
In file included from ./MyDate.h:2:
emscripten/bind.h:1393:26: error: implicit instantiation of undefined template 'emscripten::internal::GetterPolicy<int (MyClass::*)()>'
auto gter = &GP::template get<ClassType>;
^
./MyDate.h:37:6: note: in instantiation of function template specialization 'emscripten::class_<MyClass, emscripten::internal::NoBaseClass>::property<int (MyClass::*)(), void (MyClass::*)(int)>' requested here
.property("year",&MyClass::getYear, &MyClass::setYear )
^
emscripten/bind.h:569:16: note: template is declared here
struct GetterPolicy;
^
emscripten/bind.h:1399:33: error: implicit instantiation of undefined template 'emscripten::internal::GetterPolicy<int (MyClass::*)()>'
TypeID<typename GP::ReturnType>::get(),
^
emscripten\1.38.21\system\include\emscripten/bind.h:569:16: note: template is declared here
struct GetterPolicy;
^
2 errors generated.
shared:ERROR: compiler frontend failed to generate LLVM bitcode, halting
I've looked up binding examples and it appears I'm using the right syntax. Does any one have any idea of what I might be doing wrong?
Found the problem!
The getter functions must be marked as const to avoid these errors.
EX:
int getMonth() const;

tr1::functional error with g++ 4.8.1

Code:
#include <tr1/functional>
class Test
{
public:
Test() { ; }
virtual void foo() = 0;
};
void someFunc(Test& j)
{
j.foo();
}
void func(Test& j)
{
std::tr1::bind(someFunc, std::tr1::ref(j));
}
Using g++ 4.8.1 on Linux, compiling with --std=c++11 I get:
In file included from foo.cpp:1:0:
/usr/include/c++/4.8.1/tr1/functional: In instantiation of ‘class std::tr1::reference_wrapper<Test>’:
foo.cpp:17:44: required from here
/usr/include/c++/4.8.1/tr1/functional:495:9: error: cannot allocate an object of abstract type ‘Test’
operator()(_Args&... __args) const
^
foo.cpp:3:7: note: because the following virtual functions are pure within ‘Test’:
class Test
^
foo.cpp:7:18: note: virtual void Test::foo()
virtual void foo() = 0;
^
This doesn't seem to make any sense. Using the corresponding boost classes works fine. Can someone confirm this is a TR1 bug in G++ 4.8.1?
The libstdc++ tr1::reference_wrapper implementation has this:
template<typename... _Args>
typename result_of<_M_func_type(_Args...)>::type
operator()(_Args&... __args) const
{
return __invoke(get(), __args...);
}
The result_of expression uses a by-value _M_func_type parameter (which is the template parameter of the reference_wrapper i.e. Test), so it tries to form the function type Test(), which uses a by-value Test return type, which is invalid for an incomplete or abstract type. I think I fixed this for std::reference_wrapper ages ago, it needs to use result_of<_M_func_type&(Args...)>.
The TR1 implementation in libstdc++ is not really maintained any longer - TR1 served its purpose but its time has passed.

parsing error invoking static function on object instance?

I'm wondering if the following code should be considered valid c++, gcc and clang both choke on it while Microsoft and the embedded compiler (green hills) our project uses seem to parse this without problems. This line of code gives gcc and clang trouble:
foo().Bar<int>();
It appears gcc thinks the < is a less than operator instead of specifying a template argument. If Bar is changed to not be a template function gcc accepts it.
class Test1
{
public:
template<typename U>
static void Bar() {}
};
template<typename T>
class Test2
{
public:
Test2()
{
foo().Bar<int>();
}
Test1 foo() { return t; }
Test1 t;
};
int main()
{
Test2<int> t;
}
From my research calling a static member function on an object instance is valid c++. So what are you thoughts? Here is gcc's error:
Error.cpp: In constructor ‘Test2<T>::Test2()’:
Error.cpp:14:17: error: expected primary-expression before ‘int’
foo().Bar<int>();
^
Error.cpp:14:17: error: expected ‘;’ before ‘int’
The correct syntax is:
foo().template Bar<int>();
(Adding to #Dieter answer)
Otherwise you have to use a temporary:
Test1 tt = foo();
tt.Bar<int>();
(in this case you could have simply used t instead of tt, but that was not the point, of course).

g++ 4.1.2 compiler error

I have the following code (stripped down version from actual project to reproduce
the issue) that results in a compiler error on RHEL5 (g++ version 4.1.2):
----------- driver (test.cpp)--------------
#include <iostream>
#include <classa.hpp>
#include <func.hpp>
namespace globals {
static int kth(const A& a) {
return kth(a.ival());
}
}
using namespace globals;
int main() {
A a;
std::cout << func(a) << std::endl;
return 0;
}
----------class A (classa.hpp)------------
class A {
public:
A():val(0){}
const int ival() const {return val;}
private:
int val;
};
------- namespace globals (func.hpp) ------
namespace globals {
int kth(const int& c) {
return c;
}
template <class T>
int func(const T& key) {
return kth(key);
}
}
--------------------------------------------
Compiling it using g++ 4.1.2 gives me the following error:
func.hpp: In function ‘int globals::func(const T&) [with T = A]’:
test.cpp:15: instantiated from here
func.hpp:8: error: invalid initialization of reference of type ‘const int&’ from
expression of type ‘const A’
func.hpp:2: error: in passing argument 1 of ‘int globals::kth(const int&)’
Same code compiles and runs perfectly fine on RHEL4 (g++ version 3.4.6)! Any explanations/ideas/suggestions on how to resolve this error(?) on RHEL5 will
be much appreciated!
Edit:
Thanks Sergey. That is the obvious solution that I am aware of already. But I forgot to add that the restriction is that func.hpp cannot be edited (for e.g., its 3rd party write-protected). Any workarounds?
Here's what happens. When the function func() is defined, the compiler doesn't know about the function kth(const A&) yet because it is defined later in the code. So when it encounters a reference to kth() inside func(), it assumes that it is a reference to kth(const int&). Now when func() is actually instantiated, it fails to compile it because T is A, not int. I am not sure why it works in another version of the compiler, but I think it is because it actually starts resolving references when a template function is instantiated, not when it is declared. But this looks like a bug in the older version because with such behavior a function definition changes depending on where it is instantiated from, which is very confusing.
The only way to fix your code that it works with any compiler would be to put the definition of kth(const A&) between kth(const int&) and func() or a forward declaration of kth(const A&) somewhere above func().
Update
With the restriction of not editing func.hpp the best workaround I can think of is to create a custom header file with something like this:
#include <classa.hpp>
namespace globals {
static int kth(const A& a); // defined later, but used by func.hpp
}
#include <func.hpp>
I also don't see why kth(const A&) is defined as static, but used by a global header. I'd rather put it into the classa.cpp and its declaration into the classa.hpp. But this may be some design feature or artifact I am not aware of.