How to instantiate Clang templates?

I use Clang as a library to compile some boilerplate code:

template<typename T> T getSevenTemplated() { return 7; } int getSeven() { return getSevenTemplated<int>(); } 

Unfortunately, the compiled LLVM IR does not actually contain the implementation of getSevenTemplated<int> :

 ; ModuleID = './test.cpp' source_filename = "./test.cpp" target datalayout = "em:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.12.0" ; Function Attrs: ssp uwtable define i32 @_Z8getSevenv() #0 { entry: %call = call i32 @_Z17getSevenTemplatedIiET_v() ret i32 %call } declare i32 @_Z17getSevenTemplatedIiET_v() #1 attributes #0 = { ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"PIC Level", i32 2} !1 = !{!"clang version 5.0.0 (trunk 292778)"} 

Here is the code I use to create the LLVM module:

 auto* context = new llvm::LLVMContext(); // TODO: Fix leak auto codeGenerator = std::shared_ptr<clang::CodeGenerator>( clang::CreateLLVMCodeGen( compilerInstance.getDiagnostics(), filePath, compilerInstance.getHeaderSearchOpts(), preprocessor.getPreprocessorOpts(), compilerInstance.getCodeGenOpts(), *context, nullptr)); codeGenerator->Initialize(compilerInstance.getASTContext()); // declGroups are found by calling ParseAST with a special ASTConsumer earlier for (auto declGroup : declGroups) { codeGenerator->HandleTopLevelDecl(declGroup); } codeGenerator->HandleTranslationUnit(compilerInstance.getASTContext()); 

To investigate the reason, I looked at the source code and I found that CodeGenerator has a certain logic for processing templates: it seems to skip instances of function templates! I suppose it handles the generated functions instead, but I don't know how this works.

My questions:

  • At a high level, how is Klang talking about creating templates and passing them to ASTConsumer to generate the code?
  • Are there any special tricks to generate function bodies for the created templates? What am I missing in the code above?
+7
c ++ templates clang llvm
source share
1 answer

The problem was that I turned on incremental parsing. If this parameter is enabled, the ParseAST function ParseAST not call clang::Sema::ActOnEndOfTranslationUnit , which starts the creation of templates.

The trick is to add this call after processing your ads:

 // This triggers the instantiation of templated functions sema.ActOnEndOfTranslationUnit(); 
+3
source share

All Articles