Mixing -frtti (application) and -fno-rtti (LLVM)

Any code using the CommandLine library fails to link if libLLVMSupport was compiled with -fno-rtti and the application code is compiled with -frtti (the application uses features that need RTTI). I know I can build LLVM with RTTI enabled but is this strictly necessary? I saw an old llvm-dev thread where it seems to suggest that LLVM compiled with -fno-rtti may work with code compiled with -frtti. Is this really true? At least I am not able to get the following simple code using llvm::cl to link:

#include "llvm/Support/CommandLine.h"

static llvm::cl::opt<bool> Flag("flag", llvm::cl::value_desc("My flag"));

int main(int argc, char *argv[]) {
  llvm::cl::ParseCommandLineOptions(argc, argv);
  llvm::outs() << Flag << "\n";
  return 0;
}

If I don’t use -fno-rtti for the above program, I get:

/tmp/ccl-69aa34.o:(.rodata._ZTIN4llvm2cl15OptionValueCopyIbEE[_ZTIN4llvm2cl15OptionValueCopyIbEE]+0x10): undefined reference to `typeinfo for llvm::cl::GenericOptionValue'

If I need to build an application that needs -frtti, and even if I am not using any RTTI features with the LLVM classes, is it necessary that LLVM be compiled with -frtti?

I wonder if the above error with cl is caused by missing anchor functions in a few classes in CommandLine.h.

Or maybe it is not the anchor… there are some intermediate templates like OptionValueBase and OptionValueCopy that do not have explicit instantiation declarations (extern template class ...; but their derived classes have extern template class ...;.

I think each of the intermediate base classes also need extern template class ...; declaration in CommandLine.h and explicit instantiation definitions (template class ...; in CommandLine.cpp. If this is done, then a CommandLine.o compiled with -fno-rtti can be linked with application code including CommandLine.h but compiled with -frtti.

Any comments on this? Should this be fixed? Or is the recommendation to always build LLVM with RTTI enabled if it is going to be used in an application using RTTI? I don’t know if cl is the only place where this issue can crop up. But in a large application, using -frtti, the only undefined symbol I got when linking with LLVM was typeinfo for GenericOptionValue.

Would it be possible for you to isolate the code of your application that needs to use LLVM into a small library/component that can be built without RTTI while the rest of your application can be built with it?

Yes, it is possible and is probably the preferable solution in the long run. I would have liked if -frtti could be avoided altogether in the application but it is a lot of legacy code :frowning: and the difficulty of untangling the dependency on RTTI is unclear. Not using -fno-rtti for the LLVM build is a quick fix but isn’t a very appealing solution as it does make the LLVM libraries bigger.

I played around with anchor and extern template class etc. While it can be made to work in many situations, with the use of both templates and virtual functions, as is the case in CommandLine.h, it is hard or maybe even impossible to make it work in general. In other words, including CommandLine.h in a file compiled with -frtti whereas CommandLine.cpp is compiled with -fno-rtti does not seem to work in general (will result in the linker complaining about an undefined vtable or typeinfo for some class in CommandLine.h.

I don’t know how g++ and clang++ handle -frtti and -fno-rtti. They seem to be consistent with each other though. Maybe this is a question for the clang folks.

I don’t think LLVM should do anything to make -fno-rtti (see llvm/cmake/modules/AddLLVM.cmake) build work with -frtti users. This will put substantial burden to LLVM to override some files with -frtti (and there are differences among at least GNU/MSVC/IBM XL) and are very difficult to get right.

Mehdi’s solution is recommended. If you have -frtti needs that can be fixed by isolating your LLVM code due to legacy reason, build LLVM with -frtti. Note that many Linux distributions build LLVM with -frtti to help such users.

rg 'void anchor' llvm/include/llvm -l => 60 files.

I wasn’t suggesting that LLVM override any files with -frrti. I don’t think it is a good idea.

Yes, Mehdi’s solution is what I would prefer as well. In fact, I had already been exploring that even before I started this thread. It is a non-trivial amount of work, though (the goal is a desirable one in the long term).

I want to point out that there is some inconsistency in following the anchor rule of the LLVM Coding Standards in CommandLine.h. Some classes with virtual methods do not have an out of body anchor method. My understanding of the rule is that every class (with virtual methods, of course) including derived classes should provide an out-of-body definition or an override of the anchor method. I don’t know if we want to fix that for the Coding Standards’ sake.

The only reason the above is related to -frtti is because it exposed these missing anchors. I found that in the context of -frtti applications, the missing anchor sometimes caused a vtable or typeinfo to become undefined at link time for a class in CommandLine.h. But in general, it seems to be very hard to get the mixing of -fno-rtti and -frtti work right (I agree with you on that point). This is not always due to the missing anchor. The externally instantiated or partially specialized templates also cause problems. clang and gcc seem to behave consistently, though, but I have not figured out all the details.