Reputation: 574
I have a library (both as source and compiled) and I'm writing a program (not linked to this library) that needs to know if some type in the library is e.g. trivially copyable or not.
I could make my program write the following into file.cpp:
#include "mylibrary.hpp"
int main()
{
std::cout << std::is_trivially_copyable<A>::value << '\n';
std::cout << std::is_trivially_copyable<B>::value << '\n';
std::cout << std::is_trivially_copyable<C>::value << '\n';
std::cout << std::is_trivially_copyable<D>::value << '\n';
}
then compile and run this code and parse the output. Is there a better way to get this information? (performance is important). Can libclang do that?
UPDATE because of comments:
Regarding the XY problem: What I'm trying to do, is write a program (called rust-bindgen) in rust, that gets the path of a C++ header file as am argument and generates rust-c++ bindings for that header file. I need to generating the bindings differently depending on whether the type is trivially copyable/relocatable.
So I have a path to a C++ header file and I need to know whether a given type that is defined in that header file is trivially copyable. The approach above works, but is slow, because it involves compiling file.cpp.
TLDR: How can I write a fast rust function, that takes two strings as an argument and returns a bool: The first string is the path to a C++ header file, the second string is the name of a type defined in said header file. It should return a bool that says whether the type is trivially copyable or not.
Upvotes: 1
Views: 110
Reputation: 157374
You are going to need to compile the code, at least to IR. This is because the triviality of a C++ class can depend on an arbitrarily complicated computation whose inputs may include platform attributes, available headers, preprocessor defines, compiler options etc., which can thus only be carried out by a C++ compiler.
If you are invoking clang as a binary the option to emit IR is clang -S -emit-llvm
and you will then want to parse the LLVM IR output; for example for
#include <type_traits>
struct A {};
struct B { B(B const&); };
struct C { ~C(); };
struct D { D(D const&) = default; };
int a = std::is_trivially_copyable<A>::value;
int b = std::is_trivially_copyable<B>::value;
int c = std::is_trivially_copyable<C>::value;
int d = std::is_trivially_copyable<D>::value;
the IR is:
@a = dso_local local_unnamed_addr global i32 1, align 4, !dbg !0
@b = dso_local local_unnamed_addr global i32 0, align 4, !dbg !6
@c = dso_local local_unnamed_addr global i32 0, align 4, !dbg !10
@d = dso_local local_unnamed_addr global i32 1, align 4, !dbg !12
^ variable name ^ initializer
If you want to use libclang, you will need to invoke EmitLLVMOnlyAction giving a Module which you can then extract the GlobalVariable definitions from. See: Method to create LLVM IR
Upvotes: 2