12#include "rootclingCommandLineOptionsHelp.h"
14#include "RConfigure.h"
33#include <unordered_map>
34#include <unordered_set>
46#define PATH_MAX _MAX_PATH
54#include <mach-o/dyld.h>
63#include "cling/Interpreter/Interpreter.h"
64#include "cling/Interpreter/InterpreterCallbacks.h"
65#include "cling/Interpreter/LookupHelper.h"
66#include "cling/Interpreter/Value.h"
67#include "clang/AST/CXXInheritance.h"
68#include "clang/Basic/Diagnostic.h"
69#include "clang/Frontend/CompilerInstance.h"
70#include "clang/Frontend/FrontendActions.h"
71#include "clang/Frontend/FrontendDiagnostic.h"
72#include "clang/Lex/HeaderSearch.h"
73#include "clang/Lex/Preprocessor.h"
74#include "clang/Lex/ModuleMap.h"
75#include "clang/Lex/Pragma.h"
76#include "clang/Sema/Sema.h"
77#include "clang/Serialization/ASTWriter.h"
78#include "cling/Utils/AST.h"
80#include "llvm/ADT/StringRef.h"
82#include "llvm/Support/CommandLine.h"
83#include "llvm/Support/Path.h"
84#include "llvm/Support/PrettyStackTrace.h"
85#include "llvm/Support/Signals.h"
109#include <mach-o/dyld.h>
114#define strcasecmp _stricmp
115#define strncasecmp _strnicmp
141static llvm::cl::opt<bool>
143 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
144When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
164static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
168 for (
const auto td : tdvec)
171static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
175 for (
const auto en : enumvec) {
177 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
178 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
179 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
189 static std::string exepath;
192 exepath = _dyld_get_image_name(0);
194#if defined(__linux) || defined(__linux__)
195 char linkname[PATH_MAX];
201 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
202 int ret = readlink(linkname, buf, 1024);
203 if (ret > 0 && ret < 1024) {
209 char *buf =
new char[MAX_MODULE_NAME32 + 1];
210 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
212 while ((p = strchr(p,
'\\')))
218 return exepath.c_str();
224 const cling::Interpreter &interp)
232 const std::list<VariableSelectionRule> &fieldSelRules)
240 if (fieldSelRules.empty())
return;
242 clang::ASTContext &C = decl.getASTContext();
243 clang::SourceRange commentRange;
245 const std::string declName(decl.getNameAsString());
247 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
248 it != fieldSelRules.end(); ++it) {
249 if (! it->GetAttributeValue(propNames::name, varName))
continue;
250 if (declName == varName) {
253 BaseSelectionRule::AttributesMap_t::iterator iter;
254 std::string userDefinedProperty;
255 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
256 const std::string &
name = iter->first;
257 const std::string &value = iter->second;
259 if (
name == propNames::name)
continue;
264 if (
name == propNames::iotype &&
265 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
266 const char *msg =
"Data member \"%s\" is an array or a pointer. "
267 "It is not possible to assign to it the iotype \"%s\". "
268 "This transformation is possible only with data members "
269 "which are not pointers or arrays.\n";
271 msg, varName.c_str(), value.c_str());
279 if (
name == propNames::comment) {
280 decl.addAttr(
new(C) clang::AnnotateAttr(commentRange, C, value, 0));
284 if ((
name == propNames::transient && value ==
"true") ||
285 (
name == propNames::persistent && value ==
"false")) {
286 userDefinedProperty = propNames::comment + propNames::separator +
"!";
290 decl.addAttr(
new(C) clang::AnnotateAttr(commentRange, C,
"!", 0));
295 userDefinedProperty =
name + propNames::separator + value;
298 decl.addAttr(
new(C) clang::AnnotateAttr(commentRange, C, userDefinedProperty, 0));
309 cling::Interpreter &interpreter,
317 using namespace clang;
318 SourceLocation commentSLoc;
319 llvm::StringRef comment;
321 ASTContext &C = CXXRD.getASTContext();
322 Sema &S = interpreter.getCI()->getSema();
324 SourceRange commentRange;
327 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
328 auto declSelRulePair = declSelRulesMap.
find(declBaseClassPtr->getCanonicalDecl());
329 if (declSelRulePair == declSelRulesMap.end()){
330 const std::string thisClassName(CXXRD.getName());
331 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
336 if (thisClassBaseSelectionRule) {
339 BaseSelectionRule::AttributesMap_t::iterator iter;
340 std::string userDefinedProperty;
341 for (
auto const & attr : thisClassBaseSelectionRule->
GetAttributes()) {
342 const std::string &
name = attr.first;
344 const std::string &value = attr.second;
347 CXXRD.addAttr(
new(C) AnnotateAttr(commentRange, C, userDefinedProperty, 0));
354 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
355 E = CXXRD.decls_end();
I != E; ++
I) {
359 if (!(*I)->isImplicit()
360 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
364 SourceLocation maybeMacroLoc = (*I)->getLocation();
365 bool isClassDefMacro = maybeMacroLoc.isMacroID() && S.findMacroSpelling(maybeMacroLoc,
"ClassDef");
366 if (isClassDefMacro) {
367 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
373 if (comment.size()) {
376 commentRange = SourceRange(commentSLoc, commentSLoc.getLocWithOffset(comment.size()));
378 if (isClassDefMacro) {
379 CXXRD.addAttr(
new(C) AnnotateAttr(commentRange, C, comment.str(), 0));
380 }
else if (!isGenreflex) {
386 (*I)->addAttr(
new(C) AnnotateAttr(commentRange, C, comment.str(), 0));
391 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
395 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
409 llvm::APInt len = arrayType->getSize();
410 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
411 len *= subArrayType->getSize();
412 arrayType = subArrayType;
414 return len.getLimitedValue();
420 const cling::Interpreter &interp)
422 static const clang::CXXRecordDecl *TObject_decl
425 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
432 const cling::Interpreter &interp)
434 static const clang::CXXRecordDecl *TObject_decl
444 size_t len = strlen(filename);
446 if (strlen(filename) >= xmllen) {
447 return (0 == strcasecmp(filename + (len - xmllen),
".xml"));
473 if (exepath && *exepath) {
475 char *ep =
new char[PATH_MAX];
476 if (!realpath(exepath, ep)) {
477 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
478 strlcpy(ep, exepath, PATH_MAX);
481 int nche = strlen(exepath) + 1;
482 char *ep =
new char[nche];
483 strlcpy(ep, exepath, nche);
487 if ((s = strrchr(ep,
'/'))) {
489 int removesubdirs = 2;
490 if (!strncmp(s + 1,
"rootcling_stage1.exe", 20)) {
494 }
else if (!strncmp(s + 1,
"rootcling_stage1", 16)) {
499 for (
int i = 1; s && i < removesubdirs; ++i) {
501 s = strrchr(ep,
'/');
515 int ncha = strlen(ep) + 10;
516 char *env =
new char[ncha];
517 snprintf(env, ncha,
"ROOTSYS=%s", ep);
538 const char *expectedTokens[],
539 size_t *end =
nullptr)
542 if (
line[0] !=
'#')
return false;
544 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
545 while (isspace(
line[pos])) ++pos;
546 size_t lenToken = strlen(*iToken);
547 if (
line.compare(pos, lenToken, *iToken)) {
566 if (recordDecl->hasOwningModule()) {
567 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
570 std::string qual_name;
576 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
585 if (classname.find(
':') == std::string::npos)
return;
588 int slen = classname.size();
589 for (
int k = 0; k < slen; ++k) {
590 if (classname[k] ==
':') {
591 if (k + 1 >= slen || classname[k + 1] !=
':') {
596 string base = classname.substr(0, k);
601 autoloads[base] =
"";
605 }
else if (classname[k] ==
'<') {
617 std::string classname;
621 if (
line.find(
"Library.") != 0)
continue;
623 int pos =
line.find(
":", 8);
624 classname =
line.substr(8, pos - 8);
630 while (
line[0] ==
' ')
line.replace(0, 1,
"");
634 if (classname ==
"ROOT::TImpProxy") {
638 autoloads[classname] =
line;
653 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
656 if (
line ==
"{ decls }") {
658 if (
line[0] ==
'[')
break;
661 const char firstChar =
line[0];
662 if (firstChar ==
'[') {
664 libs =
line.substr(1,
line.find(
']') - 1);
665 while (libs[0] ==
' ') libs.replace(0, 1,
"");
666 }
else if (0 != keyLenMap.count(firstChar)) {
667 unsigned int keyLen = keyLenMap.at(firstChar);
668 keyname =
line.substr(keyLen,
line.length() - keyLen);
670 autoloads[keyname] = libs;
680void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
682 std::ifstream filelist(fileListName.c_str());
684 std::string filename;
687 while (filelist >> filename) {
689 if (llvm::sys::fs::is_directory(filename))
continue;
691 ifstream
file(filename.c_str());
695 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
697 file.seekg(0, std::ios::beg);
718 const string &fullname,
719 const clang::RecordDecl *cl,
720 cling::Interpreter &interp)
723 const clang::FunctionDecl *method
728 clang::TranslationUnitDecl *TU =
729 cl->getASTContext().getTranslationUnitDecl();
733 bool has_input_error =
false;
734 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
736 if (strstr(filename.c_str(),
"TBuffer.h") !=
nullptr ||
737 strstr(filename.c_str(),
"Rtypes.h") !=
nullptr) {
739 has_input_error =
true;
742 has_input_error =
true;
744 if (has_input_error) {
746 const char *maybeconst =
"";
747 const char *mayberef =
"&";
748 if (
what[strlen(
what) - 1] ==
'<') {
749 maybeconst =
"const ";
753 "in this version of ROOT, the option '!' used in a linkdef file\n"
754 " implies the actual existence of customized operators.\n"
755 " The following declaration is now required:\n"
756 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
758 return has_input_error;
770 int ncha = fullname.length() + 13;
771 char *
proto =
new char[ncha];
783 return has_input_error;
789bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
795 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
799 bool isAbstract = clxx->isAbstract();
802 std::string qualName;
804 const char *qualName_c = qualName.c_str();
806 "because it inherits from TObject but does not "
807 "have its own ClassDef.\n",
820 if (
m.getType().isConstQualified()) {
821 string ret =
"const_cast< ";
824 if (type_name.substr(0,6)==
"const ") {
825 ret += type_name.c_str()+6;
831 ret +=
m.getName().str();
835 return prefix +
m.getName().str();
845 const cling::Interpreter &interp,
847 std::ostream &dictStream)
850 std::string mTypename;
863 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
865 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
866 if (!tmplt_specialization)
return 0;
872 string fulName1, fulName2;
873 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
874 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
875 clang::QualType ti = arg0.getAsType();
879 fulName1 = ti.getAsString();
882 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
883 clang::QualType tmplti = arg1.getAsType();
886 fulName2 = tmplti.getAsString();
893 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
899 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
903 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
905 }
else if (
m.getType()->isPointerType()) {
910 dictStream <<
" {" << std::endl;
912 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
917 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
920 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
923 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
924 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
925 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
928 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
929 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
930 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
934 dictStream <<
" R__stl.clear();" << std::endl;
937 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
938 <<
" if (R__tcl1==0) {" << std::endl
939 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
940 << fulName1.c_str() <<
"!\");" << std::endl
941 <<
" return;" << std::endl
942 <<
" }" << std::endl;
945 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
946 <<
" if (R__tcl2==0) {" << std::endl
947 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
948 << fulName2.c_str() <<
"!\");" << std::endl
949 <<
" return;" << std::endl
950 <<
" }" << std::endl;
953 dictStream <<
" int R__i, R__n;" << std::endl
954 <<
" R__b >> R__n;" << std::endl;
957 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
959 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
963 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
983 std::string keyName(ti.getAsString());
984 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
985 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
986 <<
" R__stl.insert(R__t3);" << std::endl;
994 dictStream <<
" R__stl.insert(R__t);" << std::endl;
999 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1002 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1007 dictStream <<
" }" << std::endl
1008 <<
" }" << std::endl;
1009 if (isArr) dictStream <<
" }" << std::endl;
1015 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
1017 dictStream <<
" {" << std::endl;
1020 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1023 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1026 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1029 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1033 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1034 <<
" R__b << R__n;" << std::endl
1035 <<
" if(R__n) {" << std::endl;
1038 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1039 <<
" if (R__tcl1==0) {" << std::endl
1040 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1041 << fulName1.c_str() <<
"!\");" << std::endl
1042 <<
" return;" << std::endl
1043 <<
" }" << std::endl;
1046 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1047 <<
" if (R__tcl2==0) {" << std::endl
1048 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1049 <<
" return;" << std::endl
1050 <<
" }" << std::endl;
1053 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1054 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1056 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1057 clang::QualType tmplti = arg1.getAsType();
1064 dictStream <<
" }" << std::endl
1065 <<
" }" << std::endl
1066 <<
" }" << std::endl;
1067 if (isArr) dictStream <<
" }" << std::endl;
1079 std::string mTypenameStr;
1083 if (!strcmp(mTypeName,
"string")) {
1085 std::string fieldname =
m.getName().str();
1088 if (
m.getType()->isConstantArrayType()) {
1089 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1090 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1092 std::stringstream fullIdx;
1093 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1096 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1097 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1098 fullIdx <<
"[R__i" << dim <<
"]";
1099 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1102 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1103 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1106 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1107 if (
m.getType()->isPointerType())
1108 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1109 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1111 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1115 if (
m.getType()->isPointerType())
1116 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1117 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1118 else if (
m.getType()->isConstantArrayType()) {
1119 std::stringstream fullIdx;
1120 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1123 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1124 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1125 fullIdx <<
"[R__i" << dim <<
"]";
1126 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1129 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1131 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1142 if (
m.getType()->isPointerType()) {
1143 if (
m.getType()->getPointeeType()->isPointerType()) {
1155 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1157 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1159 dictStream <<
"[0]";
1160 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1175 int enclSpaceNesting = 0;
1182 dictStream <<
"#include \"TInterpreter.h\"\n";
1184 dictStream <<
"//_______________________________________"
1185 <<
"_______________________________________" << std::endl;
1186 if (add_template_keyword) dictStream <<
"template <> ";
1187 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1190 <<
"//_______________________________________"
1191 <<
"_______________________________________" << std::endl;
1192 if (add_template_keyword) dictStream <<
"template <> ";
1193 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1194 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1196 dictStream <<
"//_______________________________________"
1197 <<
"_______________________________________" << std::endl;
1198 if (add_template_keyword) dictStream <<
"template <> ";
1199 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1200 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1201 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1203 <<
"//_______________________________________"
1204 <<
"_______________________________________" << std::endl;
1205 if (add_template_keyword) dictStream <<
"template <> ";
1206 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1207 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1208 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1210 <<
"//_______________________________________"
1211 <<
"_______________________________________" << std::endl;
1212 if (add_template_keyword) dictStream <<
"template <> ";
1213 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1217 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1218 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1219 <<
"*)nullptr)->GetClass();" << std::endl
1220 <<
" return fgIsA;\n"
1221 <<
"}" << std::endl << std::endl
1223 <<
"//_______________________________________"
1224 <<
"_______________________________________" << std::endl;
1225 if (add_template_keyword) dictStream <<
"template <> ";
1226 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1228 dictStream <<
" Dictionary();\n";
1230 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1231 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1233 dictStream <<
" return fgIsA;" << std::endl
1234 <<
"}" << std::endl << std::endl;
1236 while (enclSpaceNesting) {
1237 dictStream <<
"} // namespace " << nsname << std::endl;
1246 cling::Interpreter &interp,
1247 std::ostream &dictStream)
1249 if (cl->isAnonymousNamespace()) {
1261 if (classname !=
"ROOT") {
1265 dictStream <<
" namespace ROOTDict {" << std::endl;
1268 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1272 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1273 dictStream << std::endl
1275 <<
" // Function generating the singleton type initializer" << std::endl
1278 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1279 <<
" {" << std::endl
1281 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1282 <<
" {" << std::endl
1285 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1287 <<
" instance(\"" << classname.c_str() <<
"\", ";
1290 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1292 dictStream <<
"0 /*version*/, ";
1296 for (
unsigned int i = 0; i < filename.length(); i++) {
1297 if (filename[i] ==
'\\') filename[i] =
'/';
1300 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1304 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1306 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1309 dictStream << 0 <<
");" << std::endl
1311 <<
" return &instance;" << std::endl
1312 <<
" }" << std::endl
1313 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1314 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1315 <<
" // Static variable to force the class initialization" << std::endl
1317 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1318 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1321 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1322 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1323 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1324 <<
" }" << std::endl << std::endl;
1327 dictStream <<
" }" << std::endl;
1329 dictStream <<
"}" << std::endl;
1331 dictStream << std::endl;
1340llvm::StringRef
GrabIndex(
const clang::FieldDecl &member,
int printError)
1343 llvm::StringRef where;
1346 if (index.size() == 0 && printError) {
1347 const char *errorstring;
1350 errorstring =
"is not an integer";
1353 errorstring =
"has not been defined before the array";
1356 errorstring =
"is a private member of a parent class";
1359 errorstring =
"is not known";
1362 errorstring =
"UNKNOWN ERROR!!!!";
1365 if (where.size() == 0) {
1367 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1370 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1379 const cling::Interpreter &interp,
1381 std::ostream &dictStream)
1383 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1384 if (clxx ==
nullptr)
return;
1391 int enclSpaceNesting = 0;
1397 dictStream <<
"//_______________________________________"
1398 <<
"_______________________________________" << std::endl;
1399 if (add_template_keyword) dictStream <<
"template <> ";
1400 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1401 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1409 int basestreamer = 0;
1410 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1414 string base_fullname;
1417 if (strstr(base_fullname.c_str(),
"::")) {
1419 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1420 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1421 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1423 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1428 if (!basestreamer) {
1429 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1430 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1432 dictStream <<
"}" << std::endl << std::endl;
1433 while (enclSpaceNesting) {
1434 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1441 string classname = fullname;
1442 if (strstr(fullname.c_str(),
"::")) {
1444 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1445 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1446 classname =
"thisClass";
1448 for (
int i = 0; i < 2; i++) {
1453 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1454 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1455 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1457 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1458 dictStream <<
" } else {" << std::endl;
1459 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1464 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1468 string base_fullname;
1471 if (strstr(base_fullname.c_str(),
"::")) {
1473 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1474 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1475 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1478 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1484 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1489 clang::QualType
type = field_iter->getType();
1490 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1500 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1504 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1507 if (strncmp(comment,
"!", 1)) {
1510 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1511 if (
type.getTypePtr()->isConstantArrayType() &&
1512 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1513 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1517 dictStream <<
" int R__i;" << std::endl;
1520 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1522 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: array of pointers to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1523 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1525 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1527 }
else if (
type.getTypePtr()->isPointerType()) {
1528 llvm::StringRef indexvar =
GrabIndex(**field_iter, i == 0);
1529 if (indexvar.size() == 0) {
1531 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1532 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1534 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1538 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1543 <<
"," << indexvar.str() <<
");" << std::endl;
1544 }
else if (isDouble32) {
1546 <<
"," << indexvar.str() <<
");" << std::endl;
1549 <<
"," << indexvar.str() <<
");" << std::endl;
1553 dictStream <<
" R__b.WriteFastArrayFloat16("
1554 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1555 }
else if (isDouble32) {
1556 dictStream <<
" R__b.WriteFastArrayDouble32("
1557 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1559 dictStream <<
" R__b.WriteFastArray("
1560 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1564 }
else if (
type.getTypePtr()->isArrayType()) {
1566 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1567 if (underling_type->isEnumeralType())
1568 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1572 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1573 }
else if (isDouble32) {
1575 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1578 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1582 if (underling_type->isEnumeralType()) {
1583 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1586 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1587 }
else if (isDouble32) {
1588 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1591 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1596 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1599 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1600 if (underling_type->isEnumeralType())
1601 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1602 << s <<
");" << std::endl;
1603 else if (isFloat16) {
1605 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1606 }
else if (isDouble32) {
1608 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1611 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1614 if (underling_type->isEnumeralType())
1615 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1616 else if (isFloat16) {
1617 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1618 }
else if (isDouble32) {
1619 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1621 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1625 }
else if (underling_type->isEnumeralType()) {
1627 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1628 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1630 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1635 <<
"=Float16_t(R_Dummy);}" << std::endl;
1638 }
else if (isDouble32) {
1641 <<
"=Double32_t(R_Dummy);}" << std::endl;
1663 if (
type.getTypePtr()->isConstantArrayType() &&
1664 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1665 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1669 dictStream <<
" int R__i;" << std::endl;
1672 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1677 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1682 dictStream <<
"[R__i];" << std::endl;
1683 }
else if (
type.getTypePtr()->isPointerType()) {
1691 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1692 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1694 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1698 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1712 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1718 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1722 dictStream <<
" int R__i;" << std::endl;
1725 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1726 std::string mTypeNameStr;
1728 const char *mTypeName = mTypeNameStr.c_str();
1729 const char *constwd =
"const ";
1730 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1731 mTypeName += strlen(constwd);
1732 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1734 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1738 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1744 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1745 << field_iter->getName().str() <<
"));" << std::endl;
1756 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1757 <<
" }" << std::endl
1758 <<
"}" << std::endl << std::endl;
1760 while (enclSpaceNesting) {
1761 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1769 const cling::Interpreter &interp,
1771 std::ostream &dictStream)
1775 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1776 if (clxx ==
nullptr)
return;
1781 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1793 int enclSpaceNesting = 0;
1799 dictStream <<
"//_______________________________________"
1800 <<
"_______________________________________" << std::endl;
1801 if (add_template_keyword) dictStream <<
"template <> ";
1802 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1804 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1805 <<
" if (R__b.IsReading()) {" << std::endl
1806 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1807 <<
" } else {" << std::endl
1808 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1809 <<
" }" << std::endl
1810 <<
"}" << std::endl << std::endl;
1812 while (enclSpaceNesting) {
1813 dictStream <<
"} // namespace " << nsname << std::endl;
1821 const cling::Interpreter &interp,
1823 std::ostream &dictStream,
1824 bool isAutoStreamer)
1826 if (isAutoStreamer) {
1836 std::string &code_for_parser)
1838 code_for_parser +=
"#ifdef __CINT__\n\n";
1839 code_for_parser +=
"#pragma link off all globals;\n";
1840 code_for_parser +=
"#pragma link off all classes;\n";
1841 code_for_parser +=
"#pragma link off all functions;\n\n";
1843 for (std::string& arg : InputFiles) {
1845 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1846 for (
int j = 0; j < 3; j++) {
1847 if (arg[
l] ==
'-') {
1852 if (arg[
l] ==
'!') {
1857 if (arg[
l] ==
'+') {
1863 if (nostr || noinp) {
1865 if (nostr) strlcat(trail,
"-", 3);
1866 if (noinp) strlcat(trail,
"!", 3);
1869 strlcpy(trail,
"+", 3);
1873 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1874 llvm::sys::path::replace_extension(filestem,
"");
1876 code_for_parser +=
"#pragma link C++ class ";
1877 code_for_parser += filestem.str().str();
1878 if (nostr || noinp || bcnt)
1879 code_for_parser += trail;
1880 code_for_parser +=
";\n";
1883 code_for_parser +=
"\n#endif\n";
1891bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1896 static const char *fopenopts =
"rb";
1898 static const char *fopenopts =
"r";
1902 fp = fopen(pname.c_str(), fopenopts);
1908 llvm::SmallVector<std::string, 10> includePaths;
1910 interp.GetIncludePaths(includePaths,
false,
false);
1912 const size_t nPaths = includePaths.size();
1913 for (
size_t i = 0; i < nPaths; i += 1 ) {
1917 fp = fopen(pname.c_str(), fopenopts);
1939 const char *inc = strstr(original,
"\\inc\\");
1941 inc = strstr(original,
"/inc/");
1942 if (inc && strlen(inc) > 5)
1962 cling::Interpreter &interp,
1965 std::ostringstream out;
1970 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1971 const std::string &hdrName
1989static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
1990 llvm::StringRef iSysRoot,
1991 clang::Module *module =
nullptr)
1994 llvm::SmallVector<char, 128> buffer;
1995 llvm::BitstreamWriter stream(buffer);
1996 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
1997 std::unique_ptr<llvm::raw_ostream> out =
1998 compilerInstance->createOutputFile(fileName,
true,
2007 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2009 writer.WriteAST(compilerInstance->getSema(), fileName, module, iSysRoot);
2012 out->write(&buffer.front(), buffer.size());
2024 const std::string ¤tDirectory)
2026 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2028 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2036static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2039 if (headers.empty())
2043 std::stringstream includes;
2044 for (
const std::string &header : headers) {
2045 includes <<
"#include \"" << header <<
"\"\n";
2047 std::string includeListStr = includes.str();
2048 auto result = interpreter.declare(includeListStr);
2049 return result == cling::Interpreter::CompilationResult::kSuccess;
2057 char platformDefines[64] = {0};
2058#ifdef __INTEL_COMPILER
2059 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2060 clingArgs.push_back(platformDefines);
2063 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2064 clingArgs.push_back(platformDefines);
2067 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2068 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2069 clingArgs.push_back(platformDefines);
2071#ifdef __GNUC_MINOR__
2072 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2073 clingArgs.push_back(platformDefines);
2076 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2077 clingArgs.push_back(platformDefines);
2080 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2081 clingArgs.push_back(platformDefines);
2084 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2085 clingArgs.push_back(platformDefines);
2087#ifdef _STLPORT_VERSION
2089 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2090 clingArgs.push_back(platformDefines);
2093 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2094 clingArgs.push_back(platformDefines);
2097 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2098 clingArgs.push_back(platformDefines);
2101 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2102 clingArgs.push_back(platformDefines);
2105 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2106 clingArgs.push_back(platformDefines);
2109 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2110 clingArgs.push_back(platformDefines);
2113 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2114 clingArgs.push_back(platformDefines);
2118 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
2119 clingArgs.push_back(platformDefines);
2122 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2123 clingArgs.push_back(platformDefines);
2124 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2125 clingArgs.push_back(platformDefines);
2134 return llvm::sys::path::filename(path);
2144 if (std::string::npos != pos) {
2145 dirname.assign(path.begin(), path.begin() + pos + 1);
2156 std::string dictLocation;
2158 return !dictLocation.empty();
2164 std::string &rootmapLibName)
2168 if (rootmapFileName.empty()) {
2170 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2171 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2172 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2174 rootmapLibName.c_str(),
2175 rootmapFileName.c_str());
2184 std::string &ctxtName,
2185 const cling::Interpreter &interpreter,
2186 bool treatParent =
true)
2188 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2190 if (!outerCtxt)
return;
2192 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2202 std::string &ctxtName,
2203 const cling::Interpreter &interpreter)
2205 const clang::DeclContext *theContext = theDecl.getDeclContext();
2213 const cling::Interpreter &interp)
2215 if (!decls.empty()) {
2216 std::string autoLoadKey;
2217 for (
auto &
d : decls) {
2221 if (autoLoadKey.empty()) {
2222 names.push_back(
d->getQualifiedNameAsString());
2240 const std::string &rootmapLibName,
2241 const std::list<std::string> &classesDefsList,
2242 const std::list<std::string> &classesNames,
2243 const std::list<std::string> &nsNames,
2244 const std::list<std::string> &tdNames,
2245 const std::list<std::string> &enNames,
2246 const std::list<std::string> &varNames,
2248 const std::unordered_set<std::string> headersToIgnore)
2251 std::ofstream rootmapFile(rootmapFileName.c_str());
2259 std::unordered_set<std::string> classesKeys;
2263 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2264 !enNames.empty() || !varNames.empty()) {
2267 if (!classesDefsList.empty()) {
2268 rootmapFile <<
"{ decls }\n";
2269 for (
auto & classDef : classesDefsList) {
2270 rootmapFile << classDef << std::endl;
2272 rootmapFile <<
"\n";
2274 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2277 if (!classesNames.empty()) {
2278 rootmapFile <<
"# List of selected classes\n";
2279 for (
auto & className : classesNames) {
2280 rootmapFile <<
"class " << className << std::endl;
2281 classesKeys.insert(className);
2284 std::unordered_set<std::string> treatedHeaders;
2285 for (
auto & className : classesNames) {
2287 if (className.find(
"<") != std::string::npos)
continue;
2288 if (headersClassesMap.count(className)) {
2289 auto &headers = headersClassesMap.at(className);
2290 if (!headers.empty()){
2291 auto &header = headers.front();
2292 if (treatedHeaders.insert(header).second &&
2293 headersToIgnore.find(header) == headersToIgnore.end() &&
2295 rootmapFile <<
"header " << header << std::endl;
2303 if (!nsNames.empty()) {
2304 rootmapFile <<
"# List of selected namespaces\n";
2305 for (
auto & nsName : nsNames) {
2306 rootmapFile <<
"namespace " << nsName << std::endl;
2311 if (!tdNames.empty()) {
2312 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2313 for (
const auto & autoloadKey : tdNames)
2314 if (classesKeys.insert(autoloadKey).second)
2315 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2320 if (!enNames.empty()){
2321 rootmapFile <<
"# List of selected enums and outer classes\n";
2322 for (
const auto & autoloadKey : enNames)
2323 if (classesKeys.insert(autoloadKey).second)
2324 rootmapFile <<
"enum " << autoloadKey << std::endl;
2328 if (!varNames.empty()){
2329 rootmapFile <<
"# List of selected vars\n";
2330 for (
const auto & autoloadKey : varNames)
2331 if (classesKeys.insert(autoloadKey).second)
2332 rootmapFile <<
"var " << autoloadKey << std::endl;
2346 auto nsPattern =
'{';
auto nsPatternLength = 1;
2347 auto foundNsPos =
line.find_last_of(nsPattern);
2348 if (foundNsPos == std::string::npos)
return {
"",
""};
2349 foundNsPos+=nsPatternLength;
2350 auto extNs =
line.substr(0,foundNsPos);
2352 auto nsEndPattern =
'}';
2353 auto foundEndNsPos =
line.find(nsEndPattern);
2354 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2356 return {extNs, contained};
2372 std::map<std::string, std::string> nsEntitiesMap;
2373 std::list<std::string> optFwdDeclList;
2374 for (
auto const & fwdDecl : fwdDeclarationsList){
2377 if (extNsAndEntities.first.empty()) {
2379 optFwdDeclList.push_front(fwdDecl);
2381 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2382 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2386 std::string optFwdDecl;
2387 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2388 optFwdDecl = extNsAndEntities.first;
2389 optFwdDecl += extNsAndEntities.second;
2390 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2393 optFwdDeclList.push_front(optFwdDecl);
2396 return optFwdDeclList;
2404 std::list<std::string> &el_list,
2405 std::unordered_set<std::string> &el_set)
2407 std::stringstream elStream(el);
2410 while (getline(elStream, tmp,
'\n')) {
2412 if (el_set.insert(tmp).second && !tmp.empty()) {
2413 el_list.push_back(tmp);
2424 std::list<std::string> &classesList,
2425 std::list<std::string> &classesListForRootmap,
2426 std::list<std::string> &fwdDeclarationsList,
2427 const cling::Interpreter &interpreter)
2435 std::unordered_set<std::string> classesSet;
2436 std::unordered_set<std::string> outerMostClassesSet;
2438 std::string attrName, attrValue;
2439 bool isClassSelected;
2440 std::unordered_set<std::string> availableFwdDecls;
2441 std::string fwdDeclaration;
2443 fwdDeclaration =
"";
2449 fwdDeclaration =
"";
2456 isClassSelected =
true;
2457 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2458 std::string normalizedName;
2459 normalizedName = selClass.GetNormalizedName();
2460 if (!normalizedName.empty() &&
2461 !classesSet.insert(normalizedName).second &&
2462 outerMostClassesSet.count(normalizedName) == 0) {
2463 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2464 <<
" was already selected. This means that two different instances of"
2465 <<
" clang::RecordDecl had the same name, which is not possible."
2466 <<
" This can be a hint of a serious problem in the class selection."
2467 <<
" In addition, the generated dictionary would not even compile.\n";
2470 classesList.push_back(normalizedName);
2473 const char *reqName(selClass.GetRequestedName());
2476 fwdDeclaration =
"";
2481 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2482 fwdDeclaration =
"";
2485 std::string fwdDeclarationTemplateSpec;
2487 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2495 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2497 attrName ==
"rootmap" &&
2498 attrValue ==
"false") {
2499 attrName = attrValue =
"";
2500 isClassSelected =
false;
2504 if (isClassSelected) {
2520 std::string outerMostClassName;
2522 if (!outerMostClassName.empty() &&
2523 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2524 classesSet.insert(outerMostClassName).second &&
2525 outerMostClassesSet.insert(outerMostClassName).second) {
2526 classesListForRootmap.push_back(outerMostClassName);
2528 classesListForRootmap.push_back(normalizedName);
2529 if (reqName && reqName[0] && reqName != normalizedName) {
2530 classesListForRootmap.push_back(reqName);
2535 std::string demangledName = selClass.GetDemangledTypeInfo();
2536 if (!demangledName.empty()) {
2541 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2543 classesListForRootmap.push_back(demangledName);
2549 classesListForRootmap.sort();
2562 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2577 if (clang::CXXRecordDecl *CXXRD =
2578 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2590 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2593 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2596 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2612 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2613 "#include \"TFile.h\"\n"
2614 "#include \"TObjArray.h\"\n"
2615 "#include \"TVirtualArray.h\"\n"
2616 "#include \"TStreamerElement.h\"\n"
2617 "#include \"TProtoClass.h\"\n"
2618 "#include \"TBaseClass.h\"\n"
2619 "#include \"TListOfDataMembers.h\"\n"
2620 "#include \"TListOfEnums.h\"\n"
2621 "#include \"TListOfEnumsWithLock.h\"\n"
2622 "#include \"TDataMember.h\"\n"
2623 "#include \"TEnum.h\"\n"
2624 "#include \"TEnumConstant.h\"\n"
2625 "#include \"TDictAttributeMap.h\"\n"
2626 "#include \"TMessageHandler.h\"\n"
2627 "#include \"TArray.h\"\n"
2628 "#include \"TRefArray.h\"\n"
2629 "#include \"root_std_complex.h\"\n")
2630 != cling::Interpreter::kSuccess)
2641 cling::Interpreter &interp,
2646 bool writeEmptyRootPCM)
2650 bool needsCollectionProxy =
false;
2672 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2673 if (nsName.find(
"(anonymous)") == std::string::npos)
2678 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2682 if (selClass.RequestOnlyTClass()) {
2690 if (clang::CXXRecordDecl *CXXRD =
2691 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2695 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2703 }
else if (CRD->getName() ==
"RVec") {
2704 static const clang::DeclContext *vecOpsDC =
nullptr;
2706 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2707 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2708 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2716 needsCollectionProxy);
2731 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2735 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2747 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2751 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2756 needsCollectionProxy);
2785 if (finRetCode != 0)
return finRetCode;
2795 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2796 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2799 <<
"#define R__NO_DEPRECATION" << std::endl
2804 <<
"\n/*******************************************************************/\n"
2805 <<
"#include <stddef.h>\n"
2806 <<
"#include <stdio.h>\n"
2807 <<
"#include <stdlib.h>\n"
2808 <<
"#include <string.h>\n"
2809 <<
"#include <assert.h>\n"
2810 <<
"#define G__DICTIONARY\n"
2811 <<
"#include \"RConfig.h\"\n"
2812 <<
"#include \"TClass.h\"\n"
2813 <<
"#include \"TDictAttributeMap.h\"\n"
2814 <<
"#include \"TInterpreter.h\"\n"
2815 <<
"#include \"TROOT.h\"\n"
2816 <<
"#include \"TBuffer.h\"\n"
2817 <<
"#include \"TMemberInspector.h\"\n"
2818 <<
"#include \"TInterpreter.h\"\n"
2819 <<
"#include \"TVirtualMutex.h\"\n"
2820 <<
"#include \"TError.h\"\n\n"
2821 <<
"#ifndef G__ROOT\n"
2822 <<
"#define G__ROOT\n"
2824 <<
"#include \"RtypesImp.h\"\n"
2825 <<
"#include \"TIsAProxy.h\"\n"
2826 <<
"#include \"TFileMergeInfo.h\"\n"
2827 <<
"#include <algorithm>\n"
2828 <<
"#include \"TCollectionProxyInfo.h\"\n"
2829 <<
"/*******************************************************************/\n\n"
2830 <<
"#include \"TDataMember.h\"\n\n";
2837 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2838 <<
"namespace std {} using namespace std;\n\n";
2844 const std::string &includeForSource,
2845 const std::string &extraIncludes)
2847 dictStream <<
"// Header files passed as explicit arguments\n"
2848 << includeForSource << std::endl
2849 <<
"// Header files passed via #pragma extra_include\n"
2850 << extraIncludes << std::endl;
2856#if defined(R__IOSSIM) || defined(R__IOS)
2881 return filename +
"_tmp_" + std::to_string(getpid());
2888 if (nameStr.empty())
return;
2890 std::string tmpNameStr(getTmpFileName(nameStr));
2893 const char *
name(nameStr.c_str());
2894 const char *tmpName(tmpNameStr.c_str());
2896 m_names.push_back(nameStr);
2897 m_tempNames.push_back(tmpNameStr);
2901 if (0 == std::rename(
name , tmpName)) {
2906 nameStr = tmpNameStr;
2917 for (
unsigned int i = 0; i < m_size; ++i) {
2918 const char *tmpName = m_tempNames[i].c_str();
2920 std::ifstream ifile(tmpName);
2925 if (ifile.is_open())
2927 if (0 != std::remove(tmpName)) {
2940 for (
unsigned int i = 0; i < m_size; ++i) {
2941 const char *tmpName = m_tempNames[i].c_str();
2942 const char *
name = m_names[i].c_str();
2944 std::ifstream ifile(tmpName);
2949 if (ifile.is_open())
2955 if (0 != std::rename(tmpName ,
name)) {
2956 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2957 llvm::sys::fs::remove(tmpName);
2961 if (0 != std::rename(tmpName ,
name)) {
2973 size_t i = std::distance(m_tempNames.begin(),
2974 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2975 if (i == m_tempNames.size())
return m_emptyString;
2982 std::cout <<
"Restoring files in temporary file catalog:\n";
2983 for (
unsigned int i = 0; i < m_size; ++i) {
2984 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3001 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
3002 const size_t dotPos = splitDictName.find_last_of(
".");
3003 splitDictName.insert(dotPos,
"_classdef");
3005 return new std::ofstream(splitDictName.c_str());
3014 std::list<std::string> &diagnosticPragmas)
3016 static const std::string pattern(
"-Wno-");
3018 if (arg.find(pattern) != 0)
3020 if (arg ==
"-Wno-noexcept-type") {
3027 diagnosticPragmas.push_back(arg);
3033 cling::Interpreter &interp)
3036 std::string fwdDecl;
3037 std::string initStr(
"{");
3039 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3040 auto &clTemplDecl = *strigNargsToKeepPair.first;
3041 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3044 + std::to_string(strigNargsToKeepPair.second)
3047 if (!fwdDeclnArgsToSkipColl.empty())
3058 if (qt.isNull())
return qt;
3059 clang::QualType thisQt(qt);
3060 while (thisQt->isPointerType() ||
3061 thisQt->isReferenceType()) {
3062 thisQt = thisQt->getPointeeType();
3072 const cling::Interpreter &interp,
3073 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3075 std::list<std::string> headers;
3078 cling::Interpreter::PushTransactionRAII RAII(&interp);
3081 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3085 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3088 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3089 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3091 if (tArgQualType.isNull())
continue;
3092 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3093 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3100 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3102 if (baseQualType.isNull())
continue;
3103 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3104 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3109 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3110 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3112 if (fieldQualType.isNull()) continue ;
3113 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3114 if (fieldCxxRcd->hasDefinition())
3115 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3121 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3123 for (
auto & fPar : methodIt->parameters()) {
3125 if (fParQualType.isNull())
continue;
3126 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3127 if (fParCxxRcd->hasDefinition())
3128 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3133 if (retQualType.isNull())
continue;
3134 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3135 if (retCxxRcd->hasDefinition())
3144 headers.emplace_back(header);
3157 if (
auto dclCtxt= rcd.getDeclContext()){
3158 if (! dclCtxt->isStdNamespace()){
3167 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3168 if (!clAsTmplSpecDecl)
return false;
3173 auto& astCtxt = rcd.getASTContext();
3174 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3175 for (
auto&& arg : templInstArgs.asArray()){
3177 auto argKind = arg.getKind();
3178 if (argKind != clang::TemplateArgument::Type){
3179 if (argKind == clang::TemplateArgument::Integral)
continue;
3183 auto argQualType = arg.getAsType();
3184 auto isPOD = argQualType.isPODType(astCtxt);
3186 if (isPOD)
continue;
3188 auto argType = argQualType.getTypePtr();
3189 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3192 if (isArgGoodForAutoParseMap)
continue;
3211 const cling::Interpreter &interp)
3213 std::set<const clang::CXXRecordDecl *> visitedDecls;
3214 std::unordered_set<std::string> buffer;
3215 std::string autoParseKey;
3218 for (
auto & annotatedRcd : annotatedRcds) {
3219 if (
const clang::CXXRecordDecl *cxxRcd =
3220 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3222 visitedDecls.clear();
3226 headers.remove_if([&buffer](
const std::string & s) {
3227 return !buffer.insert(s).second;
3230 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3232 headersDeclsMap[autoParseKey] = headers;
3233 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3235 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3240 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3241 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3242 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3248 for (
auto & tDef : tDefDecls) {
3249 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3251 visitedDecls.clear();
3256 headers.remove_if([&buffer](
const std::string & s) {
3257 return !buffer.insert(s).second;
3260 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3261 headersDeclsMap[autoParseKey] = headers;
3266 for (
auto & func : funcDecls) {
3272 for (
auto & var : varDecls) {
3278 for (
auto & en : enumDecls) {
3288 const cling::Interpreter &interp)
3290 std::string newFwdDeclString;
3294 std::string fwdDeclString;
3296 std::unordered_set<std::string> fwdDecls;
3317 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3322 selectedDecls.begin(),
3326 selectedDecls.push_back(TD);
3331 std::string fwdDeclLogs;
3339 std::cout <<
"Logs from forward decl printer: \n"
3356 if (fwdDeclString.empty()) fwdDeclString =
"";
3357 return fwdDeclString;
3364 const std::string &detectedUmbrella,
3365 bool payLoadOnly =
false)
3367 std::string headerName;
3370 std::cout <<
"Class-headers Mapping:\n";
3371 std::string headersClassesMapString =
"";
3372 for (
auto const & classHeaders : headersClassesMap) {
3374 std::cout <<
" o " << classHeaders.first <<
" --> ";
3375 headersClassesMapString +=
"\"";
3376 headersClassesMapString += classHeaders.first +
"\"";
3377 for (
auto const & header : classHeaders.second) {
3378 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3379 headersClassesMapString +=
", " + headerName;
3381 std::cout <<
", " << headerName;
3386 std::cout << std::endl;
3387 headersClassesMapString +=
", \"@\",\n";
3389 headersClassesMapString +=
"nullptr";
3390 return headersClassesMapString;
3413 static const std::vector<std::string> namePrfxes {
3416 auto pos = find_if(namePrfxes.begin(),
3418 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3419 return namePrfxes.end() == pos;
3426 static const std::vector<std::string> uclNamePrfxes {
3430 static const std::set<std::string> unsupportedClassesNormNames{
3433 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3434 auto pos = find_if(uclNamePrfxes.begin(),
3435 uclNamePrfxes.end(),
3436 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3437 return uclNamePrfxes.end() == pos;
3447 for (
auto&& aRcd : annotatedRcds){
3448 auto clName = aRcd.GetNormalizedName();
3450 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3451 <<
"currently the support for its I/O is not yet available. Note that "
3452 << clName <<
", even if not selected, will be available for "
3453 <<
"interpreted code.\n";
3457 std::cerr <<
"Error: It is not necessary to explicitly select class "
3458 << clName <<
". I/O is supported for it transparently.\n";
3470 bool isLocked =
false;
3473 InterpreterCallbacks(interp),
3474 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3479 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3480 const clang::FileEntry * , llvm::StringRef ,
3481 llvm::StringRef ,
const clang::Module * ,
3482 clang::SrcMgr::CharacteristicKind )
3484 if (isLocked)
return;
3485 if (IsAngled)
return;
3486 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3487 auto curLexer = PP.getCurrentFileLexer();
3488 if (!curLexer)
return;
3489 auto fileEntry = curLexer->getFileEntry();
3490 if (!fileEntry)
return;
3491 auto thisFileName = fileEntry->getName();
3492 auto fileNameAsString = FileName.str();
3494 if (isThisLinkdef) {
3496 if (isTheIncludedLinkdef) {
3497 fFilesIncludedByLinkdef.clear();
3500 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3514 clang::SourceLocation ImportLoc,
3517 using namespace clang;
3518 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3519 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3520 HeaderSearch& HS = PP.getHeaderSearchInfo();
3522 Module* CoreModule = HS.lookupModule(
"Core",
false);
3523 assert(M &&
"Must have module Core");
3524 PP.makeModuleVisible(CoreModule, ImportLoc);
3529static llvm::cl::list<std::string>
3532 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3535static llvm::cl::opt<std::string>
3537 llvm::cl::desc(
"<output dictionary file>"),
3557 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3569 using namespace clang::diag;
3575 std::string moduleName;
3576 const clang::Module *module =
nullptr;
3579 const auto &ID =
Info.getID();
3580 if (ID == remark_module_build || ID == remark_module_build_done) {
3581 moduleName =
Info.getArgStdStr(0);
3582 module = fMap.findModule(moduleName);
3588 "Couldn't find module %s in the available modulemaps. This"
3589 "prevents us from correctly diagnosing wrongly built modules.\n",
3590 moduleName.c_str());
3603 bool isByproductModule
3605 if (!isByproductModule)
3606 fChild->HandleDiagnostic(DiagLevel,
Info);
3608 if (ID == remark_module_build && !isByproductModule) {
3610 "Building module '%s' implicitly. If '%s' requires a \n"
3611 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3612 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3614 moduleName.c_str(), moduleName.c_str());
3622 DiagnosticConsumer::clear();
3625 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3627 fChild->BeginSourceFile(LangOpts, PP);
3628 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3633 fChild->EndSourceFile();
3634 DiagnosticConsumer::EndSourceFile();
3640 DiagnosticConsumer::finish();
3647#if defined(_WIN32) && defined(_MSC_VER)
3651 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3652 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3653 ::_set_error_mode(_OUT_TO_STDERR);
3654 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3655 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3656 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3657 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3658 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3659 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3664static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3666static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3677static llvm::cl::opt<VerboseLevel>
3679 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3680 clEnumVal(
v0,
"Show only fatal errors."),
3681 clEnumVal(
v1,
"Show errors (the same as -v)."),
3682 clEnumVal(
v2,
"Show warnings (default)."),
3683 clEnumVal(
v3,
"Show notes."),
3684 clEnumVal(
v4,
"Show information.")),
3688static llvm::cl::opt<bool>
3689gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3692static llvm::cl::opt<bool>
3693gOptReflex(
"reflex", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3696static llvm::cl::opt<bool>
3697gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3700static llvm::cl::opt<std::string>
3702 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3705static llvm::cl::opt<bool>
3707 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3710static llvm::cl::opt<bool>
3711gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3713static llvm::cl::opt<bool>
3714gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3716static llvm::cl::list<std::string>
3718 llvm::cl::desc(
"Generate rootmap file."),
3720static llvm::cl::opt<std::string>
3722 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3724static llvm::cl::opt<bool>
3726 llvm::cl::desc(
"Generate a C++ module."),
3728static llvm::cl::list<std::string>
3730 llvm::cl::desc(
"Specify a C++ modulemap file."),
3733static llvm::cl::opt<bool>
3735 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3737static llvm::cl::opt<bool>
3739 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3741static llvm::cl::opt<bool>
3743 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3745static llvm::cl::opt<bool>
3747 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3749static llvm::cl::opt<bool>
3751 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3752information and another the interactivity support."),
3754static llvm::cl::opt<bool>
3757 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3759static llvm::cl::opt<std::string>
3761 llvm::cl::desc(
"The path to the library of the built dictionary."),
3763static llvm::cl::list<std::string>
3765 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3767static llvm::cl::list<std::string>
3769 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3773static llvm::cl::opt<bool>
3775 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3783static llvm::cl::opt<bool>
3786 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3788static llvm::cl::opt<bool>
3790 llvm::cl::desc(
"Check the selection syntax only."),
3792static llvm::cl::opt<bool>
3794 llvm::cl::desc(
"Fail if there are warnings."),
3796static llvm::cl::opt<bool>
3798 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3800static llvm::cl::opt<std::string>
3802 llvm::cl::desc(
"Specify an isysroot."),
3804 llvm::cl::init(
"-"));
3805static llvm::cl::list<std::string>
3807 llvm::cl::desc(
"Specify an include path."),
3809static llvm::cl::list<std::string>
3811 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3813static llvm::cl::list<std::string>
3815 llvm::cl::desc(
"Specify a system include path."),
3817static llvm::cl::list<std::string>
3819 llvm::cl::desc(
"Specify defined macros."),
3821static llvm::cl::list<std::string>
3823 llvm::cl::desc(
"Specify undefined macros."),
3825static llvm::cl::list<std::string>
3827 llvm::cl::desc(
"Specify compiler diagnostics options."),
3830static llvm::cl::list<std::string>
3832 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file>"),
3834static llvm::cl::list<std::string>
3836 llvm::cl::desc(
"Consumes all unrecognized options."),
3839static llvm::cl::SubCommand
3842static llvm::cl::list<std::string>
3844 llvm::cl::desc(
"Consumes options and sends them to cling."),
3854 std::vector<std::string> &missingHeaders)
3857 std::vector<clang::Module::Header> moduleHeaders;
3859 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3861 bool foundAllHeaders =
true;
3866 for (
const std::string &header : modGen.
GetHeaders()) {
3867 bool headerFound =
false;
3868 for (
const clang::Module::Header &moduleHeader : moduleHeaders) {
3869 if (header == moduleHeader.NameAsWritten) {
3875 missingHeaders.push_back(header);
3876 foundAllHeaders =
false;
3879 return foundAllHeaders;
3885 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3887 clang::CompilerInstance *CI = interpreter.getCI();
3888 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3889 headerSearch.loadTopLevelSystemModules();
3892 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3897 moduleName.c_str());
3904 std::vector<std::string> missingHeaders;
3907 std::stringstream msgStream;
3908 msgStream <<
"warning: Couldn't find in "
3909 << module->PresumedModuleMapFile
3910 <<
" the following specified headers in "
3911 <<
"the module " << module->Name <<
":\n";
3912 for (
auto &
H : missingHeaders) {
3913 msgStream <<
" " <<
H <<
"\n";
3915 std::string warningMessage = msgStream.str();
3917 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3928 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3929 warningMessage.c_str(),
3938 module->Name.c_str());
3948 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
3949 moduleName.consume_front(
"lib");
3950 moduleName.consume_back(
".pcm");
3951 moduleName.consume_back(
"_rdict");
3959 bool isGenreflex =
false)
3962 auto &opts = llvm::cl::getRegisteredOptions();
3963 auto &optHelp = *opts[
"help"];
3964 llvm::cl::alias optHelpAlias1(
"h",
3965 llvm::cl::desc(
"Alias for -help"),
3966 llvm::cl::aliasopt(optHelp));
3967 llvm::cl::alias optHelpAlias2(
"?",
3968 llvm::cl::desc(
"Alias for -help"),
3969 llvm::cl::aliasopt(optHelp));
3980 const char *executableFileName = argv[0];
3982 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
3983 llvm::PrettyStackTraceProgram X(argc, argv);
3986#if defined(R__WIN32) && !defined(R__WINGCC)
3991 for (
int iic = 1 ; iic < argc; ++iic) {
3992 std::string iiarg(argv[iic]);
3994 size_t len = iiarg.length();
3996 char *argviic =
new char[len + 1];
3997 strlcpy(argviic, iiarg.c_str(), len + 1);
3998 argv[iic] = argviic;
4006 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
4010 std::vector<const char *> clingArgsC;
4011 clingArgsC.push_back(executableFileName);
4013 clingArgsC.push_back(
"-I");
4020 clingArgsC.push_back(Opt.c_str());
4022 auto interp = llvm::make_unique<cling::Interpreter>(clingArgsC.size(),
4024 llvmResourceDir.c_str());
4027 return interp->getDiagnostics().hasFatalErrorOccurred();
4030 std::string dictname;
4044 llvm::cl::PrintHelpMessage();
4059 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
4060 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4087 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4088 llvm::cl::PrintHelpMessage();
4092 std::vector<std::string> clingArgs;
4093 clingArgs.push_back(executableFileName);
4094 clingArgs.push_back(
"-iquote.");
4100 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4106 if (GetErrorIgnoreLevel() >
kWarning)
4108 GetWarningsAreErrors() =
true;
4122 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4127 clingArgs.push_back(std::string(
"-D") + PPDefine);
4130 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4133 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4140 clingArgs.push_back(
"-isystem");
4141 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4145 for (
const std::string &WDiag :
gOptWDiags) {
4146 const std::string FullWDiag = std::string(
"-W") + WDiag;
4150 clingArgs.push_back(FullWDiag);
4154 clingArgs.push_back(std::string(
"-I") + includeDir);
4156 std::vector<std::string> pcmArgs;
4157 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4158 auto thisArg = clingArgs[parg];
4160 if (thisArg ==
"-c" ||
4164 unsigned int offset = 2;
4165 char c = thisArg[offset];
4166 while (
c ==
' ')
c = thisArg[++offset];
4170 [&](
const std::string& path){
4171 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4172 if (excludePathsEnd != excludePathPos)
continue;
4174 pcmArgs.push_back(thisArg);
4181 clingArgs.push_back(
"-D__ROOTCLING__");
4184 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4185#elif defined(R__WIN32)
4186 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4189 clingArgs.push_back(
"-D_XKEYCHECK_H");
4191 clingArgs.push_back(
"-DNOMINMAX");
4193 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4196 clingArgs.push_back(
"-fsyntax-only");
4198 clingArgs.push_back(
"-fPIC");
4200 clingArgs.push_back(
"-Xclang");
4201 clingArgs.push_back(
"-fmodules-embed-all-files");
4202 clingArgs.push_back(
"-Xclang");
4203 clingArgs.push_back(
"-main-file-name");
4204 clingArgs.push_back(
"-Xclang");
4205 clingArgs.push_back((dictname +
".h").c_str());
4213 std::string outputFile;
4215 llvm::StringRef moduleName;
4220 auto clingArgsInterpreter = clingArgs;
4229 clingArgsInterpreter.push_back(
"-fmodules");
4230 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4233 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4235 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4237 "/module.modulemap");
4239 if (llvm::sys::fs::exists(ModuleMapCWD))
4240 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4247 clingArgsInterpreter.push_back(
"-fmodule-name");
4248 clingArgsInterpreter.push_back(moduleName.str());
4258 if (moduleName ==
"Core") {
4260 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4261 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4262 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4263 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4265 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4266 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4270 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4272 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4274 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4275 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4276 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4277 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4278 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4279 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4280 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4281 }
else if (moduleName ==
"MathCore") {
4282 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4287 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4291 clingArgsInterpreter.push_back(
"-v");
4294 std::vector<const char *> clingArgsC;
4295 for (
auto const &clingArg : clingArgsInterpreter) {
4297 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4298 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4301 clingArgsC.push_back(clingArg.c_str());
4305 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4306 cling::Interpreter* interpPtr =
nullptr;
4308 std::list<std::string> filesIncludedByLinkdef;
4312 clingArgsC.push_back(
"-ffast-math");
4315 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4316 llvmResourceDir.c_str()));
4317 interpPtr = owningInterpPtr.get();
4320 clingArgsC.push_back(
"-resource-dir");
4321 clingArgsC.push_back(llvmResourceDir.c_str());
4322 clingArgsC.push_back(
nullptr);
4324 extraArgs = &clingArgsC[1];
4327 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4328 interpPtr->setCallbacks(std::move(callBacks));
4331 cling::Interpreter &interp = *interpPtr;
4332 clang::CompilerInstance *CI = interp.getCI();
4334 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4335 CI->getSourceManager().setAllFilesAreTransient(
true);
4337 clang::Preprocessor &PP = CI->getPreprocessor();
4338 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4339 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4340 auto &diags = interp.getDiagnostics();
4347 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4352 diags.setClient(recordingClient,
true);
4358 interp.DumpIncludePath();
4363 interp.printIncludedFiles(llvm::outs());
4364 llvm::outs() <<
"\n\n";
4365 llvm::outs().flush();
4368 const clang::LangOptions& LangOpts
4369 = interp.getCI()->getASTContext().getLangOpts();
4370#define LANGOPT(Name, Bits, Default, Description) \
4371 ROOT::TMetaUtils::Info(0, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4372#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4373#include "clang/Basic/LangOptions.def"
4377 interp.getOptions().ErrorOut =
true;
4378 interp.enableRawInput(
true);
4382 if (DepMod.endswith(
"_rdict.pcm")) {
4389 cling::Interpreter::PushTransactionRAII RAII(&interp);
4390 if (!interp.loadModule(DepMod,
false)) {
4399 if (interp.declare(
"#include <assert.h>\n"
4400 "#include \"Rtypes.h\"\n"
4401 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4409 if (interp.declare(
"#include <string>\n"
4410 "#include <RtypesCore.h>\n"
4411 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4422 clingArgs.push_back(
"-D__CINT__");
4423 clingArgs.push_back(
"-D__MAKECINT__");
4429 std::string interpPragmaSource;
4430 std::string includeForSource;
4431 std::string interpreterDeclarations;
4432 std::string linkdef;
4438 if (isSelectionFile) {
4440 linkdef = optHeaderFileName;
4443 executableFileName, optHeaderFileName.c_str());
4449 std::string fullheader(optHeaderFileName);
4452 if (fullheader[fullheader.length() - 1] ==
'+') {
4453 fullheader.erase(fullheader.length() - 1);
4458 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4459 if (!isSelectionFile) {
4467 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4468 pcmArgs.push_back(header);
4470 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4475 bool hasSelectionFile = !linkdef.empty();
4476 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4487 if (!newName.empty())
4500 string incCurDir =
"-I";
4501 incCurDir += currentDirectory;
4502 pcmArgs.push_back(incCurDir);
4507 std::stringstream res;
4508 const char* delim=
"\n";
4509 std::copy(diagnosticPragmas.begin(),
4510 diagnosticPragmas.end(),
4511 std::ostream_iterator<std::string>(res, delim));
4512 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4518 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4520 IgnoringPragmaHandler(
const char* pragma):
4521 clang::PragmaNamespace(pragma) {}
4522 void HandlePragma(clang::Preprocessor &PP,
4523 clang::PragmaIntroducer Introducer,
4524 clang::Token &tok) {
4525 PP.DiscardUntilEndOfDirective();
4531 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4532 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4533 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4534 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4536 if (!interpreterDeclarations.empty() &&
4537 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4549 pcmArgs.push_back(linkdef);
4557 interp.AddIncludePath(inclPath);
4559 std::stringstream definesUndefinesStr;
4562 if (!definesUndefinesStr.str().empty()) {
4563 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4564 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4575 if (linkdef.empty()) {
4581 std::ofstream fileout;
4583 std::ostream *splitDictStream =
nullptr;
4584 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4606 splitDeleter.reset(splitDictStream);
4608 splitDictStream = &dictStream;
4611 size_t dh = main_dictname.rfind(
'.');
4612 if (dh != std::string::npos) {
4613 main_dictname.erase(dh);
4616 std::string main_dictname_copy(main_dictname);
4638 string linkdefFilename;
4639 if (linkdef.empty()) {
4640 linkdefFilename =
"in memory";
4642 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4650 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4656 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4658 std::string extraIncludes;
4663 const unsigned int selRulesInitialSize = selectionRules.
Size();
4667 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4671 int rootclingRetCode(0);
4673 if (linkdef.empty()) {
4678 clingArgs.push_back(
"-Ietc/cling/cint");
4680 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4681 llvmResourceDir.c_str())) {
4683 rootclingRetCode += 1;
4693 }
else if (isSelXML) {
4697 std::ifstream
file(linkdefFilename.c_str());
4698 if (
file.is_open()) {
4702 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4715 std::ifstream
file(linkdefFilename.c_str());
4716 if (
file.is_open()) {
4726 clingArgs.push_back(
"-Ietc/cling/cint");
4728 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4729 llvmResourceDir.c_str())) {
4731 rootclingRetCode += 1;
4766 dictStream <<
"#include \"TBuffer.h\"\n"
4767 <<
"#include \"TVirtualObject.h\"\n"
4768 <<
"#include <vector>\n"
4769 <<
"#include \"TSchemaHelper.h\"\n\n";
4771 std::list<std::string> includes;
4773 for (
auto & incFile : includes) {
4774 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4776 dictStream << std::endl;
4781 int scannerVerbLevel = 0;
4784 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4786 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4809 scan.
Scan(CI->getASTContext());
4811 bool has_input_error =
false;
4818 !dictSelRulesPresent &&
4825 if (rootclingRetCode)
return rootclingRetCode;
4832 if (annRcd.RequestNoInputOperator()) {
4844 if (has_input_error) {
4854 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4855 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4883 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4884 constructorTypes.emplace_back(
"__void__", interp);
4885 constructorTypes.emplace_back(
"", interp);
4915 if (rootclingRetCode != 0) {
4916 return rootclingRetCode;
4935 std::string detectedUmbrella;
4936 for (
auto & arg : pcmArgs) {
4938 detectedUmbrella = arg;
4944 headersDeclsMap.clear();
4948 std::string headersClassesMapString =
"\"\"";
4949 std::string fwdDeclsString =
"\"\"";
4965 if (modGen.
IsPCH()) {
4968 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
4978 ofstream outputfile(liblist_filename.c_str(), ios::out);
4981 executableFileName, liblist_filename.c_str());
4983 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4984 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4986 outputfile <<
"# Now the list of classes\n";
4991 outputfile << annRcd.GetNormalizedName() << endl;
4998 if (0 != rootclingRetCode)
return rootclingRetCode;
5004 [](
const std::string &
a,
const std::string &
b) -> std::string {
5005 if (a.empty()) return b;
5006 else return a +
" " + b;
5011 std::list<std::string> classesNames;
5012 std::list<std::string> classesNamesForRootmap;
5013 std::list<std::string> classesDefsList;
5017 classesNamesForRootmap,
5021 std::list<std::string> enumNames;
5026 std::list<std::string> varNames;
5031 if (0 != rootclingRetCode)
return rootclingRetCode;
5034 if (rootMapNeeded) {
5036 std::list<std::string> nsNames;
5045 rootmapLibName.c_str());
5048 std::unordered_set<std::string> headersToIgnore;
5051 headersToIgnore.insert(optHeaderFileName.c_str());
5053 std::list<std::string> typedefsRootmapLines;
5061 classesNamesForRootmap,
5063 typedefsRootmapLines,
5069 if (0 != rootclingRetCode)
return 1;
5079 cling::Interpreter::PushTransactionRAII RAII(&interp);
5080 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5091 if(rootclingRetCode == 0) {
5092 rootclingRetCode += tmpCatalog.
commit();
5097 return rootclingRetCode;
5108 unsigned int numberOfHeaders = 0;
5109 for (std::vector<std::string>::iterator it = headersNames.begin();
5110 it != headersNames.end(); ++it) {
5111 const std::string headername(*it);
5116 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5117 headername.c_str());
5120 return numberOfHeaders;
5126 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5129 unsigned int argvCounter = 0;
5130 for (
int i = 1; i < argc; ++i) {
5133 args.push_back(argv[i]);
5135 }
else if (argvCounter) {
5136 argv[i - argvCounter] = argv[i];
5143 std::cout <<
"Args: \n";
5144 for (std::vector<std::string>::iterator it = args.begin();
5145 it < args.end(); ++it) {
5146 std::cout << i <<
") " << *it << std::endl;
5159 size_t result = filename.find_last_of(
'.');
5160 if (std::string::npos != result) {
5161 filename.erase(result);
5162 filename.append(newExtension);
5172 const unsigned int size(str.size());
5173 char *
a =
new char[
size + 1];
5175 memcpy(
a, str.c_str(),
size);
5191 std::vector<std::string> &ofilesnames)
5193 ofilesnames.reserve(headersNames.size());
5195 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5196 it != headersNames.end(); ++it) {
5197 std::string ofilename(*it);
5199 ofilesnames.push_back(ofilename);
5206 const std::vector<std::string> &argsToBeAdded,
5207 const std::string &optName =
"")
5209 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5210 it != argsToBeAdded.end(); ++it) {
5218 const std::vector<std::string> &argsToBeAdded,
5219 const std::string &optName =
"")
5221 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5222 it != argsToBeAdded.end(); ++it) {
5223 if (optName.length()) {
5233 const std::string &selectionFileName,
5234 const std::string &targetLibName,
5236 const std::vector<std::string> &pcmsNames,
5237 const std::vector<std::string> &includes,
5238 const std::vector<std::string> &preprocDefines,
5239 const std::vector<std::string> &preprocUndefines,
5240 const std::vector<std::string> &warnings,
5241 const std::string &rootmapFileName,
5242 const std::string &rootmapLibName,
5243 bool interpreteronly,
5246 bool writeEmptyRootPCM,
5248 bool noIncludePaths,
5249 bool noGlobalUsingStd,
5250 const std::vector<std::string> &headersNames,
5251 bool failOnWarnings,
5252 const std::string &ofilename)
5256 std::vector<char *> argvVector;
5267 std::string dictLocation;
5273 std::string newRootmapLibName(rootmapLibName);
5274 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5275 if (headersNames.size() != 1) {
5277 "*** genreflex: No rootmap lib and several header specified!\n");
5280 newRootmapLibName =
"lib";
5281 newRootmapLibName += cleanHeaderName;
5287 std::string newRootmapFileName(rootmapFileName);
5288 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5289 newRootmapFileName = dictLocation + newRootmapFileName;
5294 if (!newRootmapFileName.empty()) {
5300 if (!newRootmapLibName.empty()) {
5306 if (interpreteronly)
5314 if (!targetLibName.empty()) {
5324 if (noGlobalUsingStd)
5334 if (writeEmptyRootPCM)
5357 if (!selectionFileName.empty()) {
5361 const int argc = argvVector.size();
5365 std::cout <<
"Rootcling commandline:\n";
5366 for (
int i = 0; i < argc; i++)
5367 std::cout << i <<
") " << argvVector[i] << std::endl;
5370 char **argv = & (argvVector[0]);
5375 for (
int i = 0; i < argc; i++)
5376 delete [] argvVector[i];
5378 return rootclingReturnCode;
5387 const std::string &selectionFileName,
5388 const std::string &targetLibName,
5390 const std::vector<std::string> &pcmsNames,
5391 const std::vector<std::string> &includes,
5392 const std::vector<std::string> &preprocDefines,
5393 const std::vector<std::string> &preprocUndefines,
5394 const std::vector<std::string> &warnings,
5395 const std::string &rootmapFileName,
5396 const std::string &rootmapLibName,
5397 bool interpreteronly,
5400 bool writeEmptyRootPCM,
5402 bool noIncludePaths,
5403 bool noGlobalUsingStd,
5404 const std::vector<std::string> &headersNames,
5405 bool failOnWarnings,
5406 const std::string &outputDirName_const =
"")
5408 std::string outputDirName(outputDirName_const);
5410 std::vector<std::string> ofilesNames;
5417 std::vector<std::string> namesSingleton(1);
5418 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5419 namesSingleton[0] = headersNames[i];
5420 std::string ofilenameFullPath(ofilesNames[i]);
5421 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5422 ofilenameFullPath = outputDirName + ofilenameFullPath;
5444 if (returnCode != 0)
5459 std::vector<std::string> &values)
5462 if (options[oIndex]) {
5463 const int nVals = options[oIndex].count();
5464 values.reserve(nVals);
5465 int optionIndex = 0;
5468 << optionIndex <<
"/" << nVals <<
" "
5469 << opt->arg << std::endl;
5471 values.push_back(opt->arg);
5482 const char *descriptor)
5484 if (options[optionIndex]) {
5486 "*** genereflex: %s is not supported anymore.\n",
5543 enum optionIndex { UNKNOWN,
5574 enum optionTypes { NOTYPE, STRING } ;
5577 const char *genreflexUsage =
5578 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5579 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5582 const char *selectionFilenameUsage =
5583 "-s, --selection_file\tSelection filename\n"
5584 " Class selection file to specify for which classes the dictionary\n"
5585 " will be generated. The final set can be crafted with exclusion and\n"
5586 " exclusion rules.\n"
5587 " Properties can be specified. Some have special meaning:\n"
5588 " - name [string] name of the entity to select with an exact matching\n"
5589 " - pattern [string] name with wildcards (*) to select entities\n"
5590 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5591 " file where the C++ entities reside and not to C++ entities themselves.\n"
5592 " - transient/persistent [string: true/false] The fields to which they are\n"
5593 " applied will not be persistified if requested.\n"
5594 " - comment [string]: what you could write in code after an inline comment\n"
5595 " without \"//\". For example comment=\"!\" or \"||\".\n"
5596 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5597 " Default value is 'false'\n"
5598 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5599 " to 'true'. Default value is 'false'\n"
5603 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5604 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5605 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5606 " [noInputOperator=\"true/false\"] />\n"
5607 " <class name=\"classname\" >\n"
5608 " <field name=\"m_transient\" transient=\"true\"/>\n"
5609 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5610 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5611 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5613 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5614 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5615 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5618 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5619 " <method name=\"unwanted\" />\n"
5624 " If no selection file is specified, the class with the filename without\n"
5625 " extension will be selected, i.e. myClass.h as argument without any\n"
5626 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5628 const char *outputFilenameUsage =
5629 "-o, --output\tOutput filename\n"
5630 " Output file name. If an existing directory is specified instead of a file,\n"
5631 " then a filename will be built using the name of the input file and will\n"
5632 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5633 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5634 " have unique names.\n";
5637 const char *targetLib =
5638 "-l, --library\tTarget library\n"
5639 " The flag -l must be followed by the name of the library that will\n"
5640 " contain the object file corresponding to the dictionary produced by\n"
5641 " this invocation of genreflex.\n"
5642 " The name takes priority over the one specified for the rootmapfile.\n"
5643 " The name influences the name of the created pcm:\n"
5644 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5645 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5646 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5647 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5648 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5650 const char *rootmapUsage =
5651 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5652 " This file lists the autoload keys. For example classes for which the\n"
5653 " reflection information is provided.\n"
5654 " The format of the rootmap is the following:\n"
5655 " - Forward declarations section\n"
5656 " - Libraries sections\n"
5657 " Rootmaps can be concatenated together, for example with the cat util.\n"
5658 " In order for ROOT to pick up the information in the rootmaps, they\n"
5659 " have to be located in the library path and have the .rootmap extension.\n"
5660 " An example rootmap file could be:\n"
5662 " template <class T> class A;\n"
5663 " [ libMyLib.so ]\n"
5664 " class A<double>\n"
5669 const char *rootmapLibUsage =
5670 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5703 "--multiDict\tSupport for many dictionaries in one library\n"
5704 " Form correct pcm names if multiple dictionaries will be in the same\n"
5705 " library (needs target library switch. See its documentation).\n"
5712 "" ,
"noGlobalUsingStd" ,
5714 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5715 " All header files must have sumbols from std:: namespace fully qualified\n"
5721 "s" ,
"selection_file" ,
5723 selectionFilenameUsage
5737 "" ,
"rootmap-lib" ,
5745 "" ,
"interpreteronly",
5747 "--interpreteronly\tDo not generate I/O related information.\n"
5748 " Generate minimal dictionary required for interactivity.\n"
5756 "--split\tSplit the dictionary\n"
5757 " Split in two the dictionary, isolating the part with\n"
5758 " ClassDef related functions in a separate file.\n"
5766 "-m \tPcm file loaded before any header (option can be repeated).\n"
5774 "-v, --verbose\tPrint some debug information.\n"
5782 "--debug\tPrint all debug information.\n"
5790 "--quiet\tPrint only warnings and errors (default).\n"
5798 "--silent\tPrint no information at all.\n"
5804 "" ,
"writeEmptyPCM",
5806 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5814 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5823 "--help\tPrint usage and exit.\n"
5829 "",
"fail_on_warnings",
5831 "--fail_on_warnings\tFail on warnings and errors.\n"
5837 "",
"selSyntaxOnly",
5839 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5845 "" ,
"noIncludePaths",
5847 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5886 "" ,
"no_membertypedefs" ,
5894 "" ,
"no_templatetypedefs" ,
5899 {0, 0,
nullptr,
nullptr,
nullptr,
nullptr}
5902 std::vector<std::string> headersNames;
5903 const int originalArgc = argc;
5905 const int extractedArgs = extractArgs(argc, argv, headersNames);
5907 const int offset = 1;
5908 argc -= offset + extractedArgs;
5913 std::vector<ROOT::option::Option> options(stats.
options_max);
5914 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5920 if (parse.
error()) {
5926 if (options[HELP] || originalArgc == 1) {
5931 int numberOfHeaders = checkHeadersNames(headersNames);
5932 if (0 == numberOfHeaders) {
5943 std::string verbosityOption(
"-v2");
5944 if (options[SILENT]) verbosityOption =
"-v0";
5945 if (options[
VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5946 if (options[
DEBUG]) verbosityOption =
"-v4";
5951 std::string selectionFileName;
5952 if (options[SELECTIONFILENAME]) {
5953 selectionFileName = options[SELECTIONFILENAME].arg;
5956 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
5957 selectionFileName.c_str());
5972 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
5973 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
5976 std::string targetLibName;
5977 if (options[TARGETLIB]) {
5978 targetLibName = options[TARGETLIB].arg;
5981 "Invalid target library extension: filename is %s and extension %s is expected!\n",
5982 targetLibName.c_str(),
5986 if (options[ROOTMAP]) {
5991 bool isCxxmodule = options[CXXMODULE];
5993 bool multidict =
false;
5994 if (options[MULTIDICT]) multidict =
true;
5996 bool noGlobalUsingStd =
false;
5997 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
5999 if (multidict && targetLibName.empty()) {
6001 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
6005 bool interpreteronly =
false;
6006 if (options[INTERPRETERONLY])
6007 interpreteronly =
true;
6009 bool doSplit =
false;
6013 bool writeEmptyRootPCM =
false;
6014 if (options[WRITEEMPTYROOTPCM])
6015 writeEmptyRootPCM =
true;
6017 bool selSyntaxOnly =
false;
6018 if (options[SELSYNTAXONLY]) {
6019 selSyntaxOnly =
true;
6022 bool noIncludePaths =
false;
6023 if (options[NOINCLUDEPATHS]) {
6024 noIncludePaths =
true;
6027 bool failOnWarnings =
false;
6028 if (options[FAILONWARNINGS]) {
6029 failOnWarnings =
true;
6038 std::vector<std::string> pcmsNames;
6042 std::vector<std::string> preprocDefines;
6046 std::vector<std::string> preprocUndefines;
6050 std::vector<std::string> includes;
6054 std::vector<std::string> warnings;
6065 int returnValue = 0;
6066 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6070 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6071 returnValue = invokeRootCling(verbosityOption,
6094 returnValue = invokeManyRootCling(verbosityOption,
6127 assert(!
gDriverConfig &&
"Driver configuration already set!");
6147 if (std::string::npos != exeName.find(
"genreflex"))
6155 ROOT::TMetaUtils::Info(
nullptr,
"Problems have been detected during the generation of the dictionary.\n");
Select classes and assign properties using C++ syntax.
The file contains utilities which are foundational and could be used across the core component of ROO...
This is the only file required to use The Lean Mean C++ Option Parser.
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
const AttributesMap_t & GetAttributes() const
std::unordered_map< std::string, std::string > AttributesMap_t
Custom diag client for clang that verifies that each implicitly build module is a system module.
CheckModuleBuildClient(clang::DiagnosticConsumer *Child, bool OwnsChild, clang::ModuleMap &Map)
clang::DiagnosticConsumer * fChild
~CheckModuleBuildClient()
virtual void BeginSourceFile(const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) override
virtual void finish() override
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
virtual void clear() override
virtual bool IncludeInDiagnosticCounts() const override
virtual void EndSourceFile() override
const std::list< VariableSelectionRule > & GetFieldSelectionRules() const
bool LoadIncludes(std::string &extraInclude)
bool Parse(SelectionRules &sr, llvm::StringRef code, const std::vector< std::string > &parserArgs, const char *llvmdir)
void GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlClass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
void WriteClassInit(std::ostream &strm, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const ROOT::TMetaUtils::RConstructorTypes &, bool &needCollectionProxy, void(*emitStreamerInfo)(const char *))
void WriteUmbrellaHeader(std::ostream &out) const
Write a header file pulling in the content of this module through a series of #defined,...
const std::string & GetUmbrellaName() const
const std::vector< std::string > & GetIncludePaths() const
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes, bool hasCxxModule) const
const std::vector< std::string > & GetHeaders() const
void WriteContentHeader(std::ostream &out) const
Write a header file describing the content of this module through a series of variables inside the na...
int GetErrorCount() const
const std::string & GetModuleFileName() const
std::ostream & WritePPUndefines(std::ostream &out) const
Write #ifdef FOO.
void ParseArgs(const std::vector< std::string > &args)
Parse -I -D -U headers.h SomethingLinkdef.h.
const std::string & GetContentName() const
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO.
A parsed option from the command line together with its argument if it has one.
Option * next()
Returns a pointer to the next element of the linked list or NULL if called on last().
Checks argument vectors for validity and parses them into data structures that are easier to work wit...
bool error()
Returns true if an unrecoverable error occurred while parsing options.
void Scan(const clang::ASTContext &C)
std::vector< ROOT::TMetaUtils::AnnotatedRecordDecl > ClassColl_t
const DeclsSelRulesMap_t & GetDeclsSelRulesMap() const
FunctionColl_t fSelectedFunctions
std::vector< const clang::FunctionDecl * > FunctionColl_t
NamespaceColl_t fSelectedNamespaces
TypedefColl_t fSelectedTypedefs
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
std::map< const clang::Decl *, const BaseSelectionRule * > DeclsSelRulesMap_t
EnumColl_t fSelectedEnums
std::vector< const clang::TypedefNameDecl * > TypedefColl_t
std::vector< const clang::VarDecl * > VariableColl_t
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
VariableColl_t fSelectedVariables
std::vector< const clang::EnumDecl * > EnumColl_t
ClassColl_t fSelectedClasses
RooAbsArg * find(const char *name) const
Find object with given name in list.
The class representing the collection of selection rules.
bool AreAllSelectionRulesUsed() const
bool SearchNames(cling::Interpreter &interp)
void PrintSelectionRules() const
unsigned int Size() const
void SetSelectionFileType(ESelectionFileTypes fileType)
virtual void EnteredSubmodule(clang::Module *M, clang::SourceLocation ImportLoc, bool ForPragma)
virtual void InclusionDirective(clang::SourceLocation, const clang::Token &, llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange, const clang::FileEntry *, llvm::StringRef, llvm::StringRef, const clang::Module *, clang::SrcMgr::CharacteristicKind)
std::list< std::string > & fFilesIncludedByLinkdef
TRootClingCallbacks(cling::Interpreter *interp, std::list< std::string > &filesIncludedByLinkdef)
bool Parse(const std::string &fileName, SelectionRules &out)
Little helper class to bookkeep the files names which we want to make temporary.
void addFileName(std::string &nameStr)
Adds the name and the associated temp name to the catalog.
const std::string & getFileName(const std::string &tmpFileName)
std::vector< std::string > m_names
std::vector< std::string > m_tempNames
const std::string m_emptyString
std::string getTmpFileName(const std::string &filename)
static bool FromCygToNativePath(std::string &path)
std::string GetCurrentDir()
std::string MakePathRelative(const std::string &path, const std::string &base, bool isBuildingROOT=false)
void printUsage(OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN SchemaRuleClassMap_t gReadRules
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
R__EXTERN SchemaRuleClassMap_t gReadRawRules
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
void Init(TClassEdit::TInterpreterLookupHelper *helper)
void header2outputName(std::string &fileName)
Replace the extension with "_rflx.cpp".
void AddToArgVectorSplit(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
void changeExtension(std::string &filename, const std::string &newExtension)
int invokeRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &ofilename)
int invokeManyRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &outputDirName_const="")
Get the right ofilenames and invoke several times rootcling One invokation per header.
unsigned int checkHeadersNames(std::vector< std::string > &headersNames)
Loop on arguments: stop at the first which starts with -.
void headers2outputsNames(const std::vector< std::string > &headersNames, std::vector< std::string > &ofilesnames)
Get a proper name for the output file.
char * string2charptr(const std::string &str)
The caller is responsible for deleting the string!
unsigned int extractArgs(int argc, char **argv, std::vector< std::string > &args)
Extract the arguments from the command line.
void AddToArgVector(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
int FinalizeStreamerInfoWriting(cling::Interpreter &interp, bool writeEmptyRootPCM=false)
Make up for skipping RegisterModule, now that dictionary parsing is done and these headers cannot be ...
std::list< std::string > CollapseIdenticalNamespaces(const std::list< std::string > &fwdDeclarationsList)
If two identical namespaces are there, just declare one only Example: namespace A { namespace B { fwd...
static llvm::cl::opt< bool > gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
int RootClingMain(int argc, char **argv, bool isGenreflex=false)
static llvm::StringRef GetModuleNameFromRdictName(llvm::StringRef rdictName)
static llvm::cl::opt< bool > gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), llvm::cl::cat(gRootclingOptions), llvm::cl::init("-"))
int STLContainerStreamer(const clang::FieldDecl &m, int rwmode, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
Create Streamer code for an STL container.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static llvm::cl::opt< bool > gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
static llvm::cl::list< std::string > gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), llvm::cl::cat(gRootclingOptions))
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
static void MaybeSuppressWin32CrashDialogs()
void RecordDeclCallback(const clang::RecordDecl *recordDecl)
void CheckClassNameForRootMap(const std::string &classname, map< string, string > &autoloads)
bool Which(cling::Interpreter &interp, const char *fname, string &pname)
Find file name in path specified via -I statements to Cling.
void AdjustRootMapNames(std::string &rootmapFileName, std::string &rootmapLibName)
void AddNamespaceSTDdeclaration(std::ostream &dictStream)
static llvm::cl::list< std::string > gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptModuleByproducts("mByproduct", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("The list of the expected implicit modules build as part of building the current module."), llvm::cl::cat(gRootclingOptions))
map< string, string > gAutoloads
static llvm::cl::opt< bool > gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), llvm::cl::cat(gRootclingOptions))
static bool CheckModuleValid(TModuleGenerator &modGen, const std::string &resourceDir, cling::Interpreter &interpreter, llvm::StringRef LinkdefPath, const std::string &moduleName)
Check moduleName validity from modulemap. Check if this module is defined or not.
static void CheckForMinusW(std::string arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance, llvm::StringRef iSysRoot, clang::Module *module=nullptr)
Write the AST of the given CompilerInstance to the given File while respecting the given isysroot.
static llvm::cl::opt< bool > gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), llvm::cl::cat(gRootclingOptions))
void ExtractFilePath(const std::string &path, std::string &dirname)
Extract the path from a fullpath finding the last \ or / according to the content in gPathSeparator.
int STLStringStreamer(const clang::FieldDecl &m, int rwmode, std::ostream &dictStream)
Create Streamer code for a standard string object.
void CreateDictHeader(std::ostream &dictStream, const std::string &main_dictname)
const char * GetExePath()
Returns the executable path name, used e.g. by SetRootSys().
const std::string gPathSeparator(ROOT::TMetaUtils::GetPathSeparator())
static llvm::cl::list< std::string > gOptBareClingSink(llvm::cl::OneOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes options and sends them to cling."), llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gBareClingSubcommand))
bool InheritsFromTObject(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static bool InjectModuleUtilHeader(const char *argv0, TModuleGenerator &modGen, cling::Interpreter &interp, bool umbrella)
Write the extra header injected into the module: umbrella header if (umbrella) else content header.
static llvm::cl::list< std::string > gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), llvm::cl::cat(gRootclingOptions))
int ExtractClassesListAndDeclLines(RScanner &scan, std::list< std::string > &classesList, std::list< std::string > &classesListForRootmap, std::list< std::string > &fwdDeclarationsList, const cling::Interpreter &interpreter)
void ParseRootMapFileNewFormat(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map, using the new format.
static llvm::cl::OptionCategory gRootclingOptions("rootcling common options")
static llvm::cl::list< std::string > gOptSysIncludePaths("isystem", llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a system include path."), llvm::cl::cat(gRootclingOptions))
void ExtractHeadersForDecls(const RScanner::ClassColl_t &annotatedRcds, const RScanner::TypedefColl_t tDefDecls, const RScanner::FunctionColl_t funcDecls, const RScanner::VariableColl_t varDecls, const RScanner::EnumColl_t enumDecls, HeadersDeclsMap_t &headersClassesMap, HeadersDeclsMap_t &headersDeclsMap, const cling::Interpreter &interp)
bool ParsePragmaLine(const std::string &line, const char *expectedTokens[], size_t *end=nullptr)
Check whether the #pragma line contains expectedTokens (0-terminated array).
static llvm::cl::opt< bool > gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static bool GenerateAllDict(TModuleGenerator &modGen, clang::CompilerInstance *compilerInstance, const std::string ¤tDirectory)
Generates a PCH from the given ModuleGenerator and CompilerInstance.
void LoadLibraryMap(const std::string &fileListName, map< string, string > &autoloads)
Fill the map of libraries to be loaded in presence of a class Transparently support the old and new r...
std::ostream * CreateStreamPtrForSplitDict(const std::string &dictpathname, tempFileNamesCatalog &tmpCatalog)
Transform name of dictionary.
void WriteNamespaceInit(const clang::NamespaceDecl *cl, cling::Interpreter &interp, std::ostream &dictStream)
Write the code to initialize the namespace name and the initialization object.
static llvm::cl::list< std::string > gOptCompDefaultIncludePaths("compilerI", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a compiler default include path, to suppress unneeded `-isystem` arguments."), llvm::cl::cat(gRootclingOptions))
void AnnotateAllDeclsForPCH(cling::Interpreter &interp, RScanner &scan)
We need annotations even in the PCH: // !, // || etc.
size_t GetFullArrayLength(const clang::ConstantArrayType *arrayType)
static llvm::cl::opt< bool > gOptSplit("split", llvm::cl::desc("Split the dictionary into two parts: one containing the IO (ClassDef)\
information and another the interactivity support."), llvm::cl::cat(gRootclingOptions))
bool ProcessAndAppendIfNotThere(const std::string &el, std::list< std::string > &el_list, std::unordered_set< std::string > &el_set)
Separate multiline strings.
static llvm::cl::opt< bool > gOptNoGlobalUsingStd("noGlobalUsingStd", llvm::cl::desc("Do not declare {using namespace std} in dictionary global scope."), llvm::cl::cat(gRootclingOptions))
const ROOT::Internal::RootCling::DriverConfig * gDriverConfig
static llvm::cl::list< std::string > gOptModuleDependencies("m", llvm::cl::desc("The list of dependent modules of the dictionary."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::SubCommand gBareClingSubcommand("bare-cling", "Call directly cling and exit.")
static llvm::cl::opt< bool > gOptInterpreterOnly("interpreteronly", llvm::cl::desc("Generate minimal dictionary for interactivity (without IO information)."), llvm::cl::cat(gRootclingOptions))
void WriteArrayDimensions(const clang::QualType &type, std::ostream &dictStream)
Write "[0]" for all but the 1st dimension.
void GetMostExternalEnclosingClassName(const clang::DeclContext &theContext, std::string &ctxtName, const cling::Interpreter &interpreter, bool treatParent=true)
Extract the proper autoload key for nested classes The routine does not erase the name,...
std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, cling::Interpreter &interp)
int ExtractAutoloadKeys(std::list< std::string > &names, const COLL &decls, const cling::Interpreter &interp)
static llvm::cl::opt< std::string > gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), llvm::cl::cat(gRootclingOptions))
int GenerateFullDict(std::ostream &dictStream, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool writeEmptyRootPCM)
void WriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
void GetMostExternalEnclosingClassNameFromDecl(const clang::Decl &theDecl, std::string &ctxtName, const cling::Interpreter &interpreter)
static llvm::cl::opt< bool > gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::ZeroOrMore, llvm::cl::desc("<list of dictionary header files> <LinkDef file>"), llvm::cl::cat(gRootclingOptions))
void SetRootSys()
Set the ROOTSYS env var based on the executable location.
bool CheckInputOperator(const char *what, const char *proto, const string &fullname, const clang::RecordDecl *cl, cling::Interpreter &interp)
Check if the specified operator (what) has been properly declared if the user has requested a custom ...
void GenerateNecessaryIncludes(std::ostream &dictStream, const std::string &includeForSource, const std::string &extraIncludes)
void StrcpyArg(string &dest, const char *original)
Copy the command line argument, stripping MODULE/inc if necessary.
static llvm::cl::list< std::string > gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), llvm::cl::cat(gRootclingOptions))
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
static llvm::cl::opt< bool > gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), llvm::cl::cat(gRootclingOptions))
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
static std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
static llvm::cl::opt< bool > gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), llvm::cl::cat(gRootclingOptions))
const char * CopyArg(const char *original)
If the argument starts with MODULE/inc, strip it to make it the name we can use in #includes.
string GetNonConstMemberName(const clang::FieldDecl &m, const string &prefix="")
Return the name of the data member so that it can be used by non-const operation (so it includes a co...
static llvm::cl::list< std::string > gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), llvm::cl::cat(gRootclingOptions))
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
void ExtractSelectedNamespaces(RScanner &scan, std::list< std::string > &nsList)
Loop on selected classes and put them in a list.
static bool IncludeHeaders(const std::vector< std::string > &headers, cling::Interpreter &interpreter)
Includes all given headers in the interpreter.
clang::QualType GetPointeeTypeIfPossible(const clang::QualType &qt)
Get the pointee type if possible.
void AnnotateDecl(clang::CXXRecordDecl &CXXRD, const RScanner::DeclsSelRulesMap_t &declSelRulesMap, cling::Interpreter &interpreter, bool isGenreflex)
static llvm::cl::opt< VerboseLevel > gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), llvm::cl::values(clEnumVal(v, "Show errors."), clEnumVal(v0, "Show only fatal errors."), clEnumVal(v1, "Show errors (the same as -v)."), clEnumVal(v2, "Show warnings (default)."), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), llvm::cl::cat(gRootclingOptions))
void GenerateLinkdef(llvm::cl::list< std::string > &InputFiles, std::string &code_for_parser)
static llvm::cl::opt< std::string > gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include <header> but expands the header content."), llvm::cl::cat(gRootclingOptions))
bool isPointerToPointer(const clang::FieldDecl &m)
int CreateNewRootMapFile(const std::string &rootmapFileName, const std::string &rootmapLibName, const std::list< std::string > &classesDefsList, const std::list< std::string > &classesNames, const std::list< std::string > &nsNames, const std::list< std::string > &tdNames, const std::list< std::string > &enNames, const std::list< std::string > &varNames, const HeadersDeclsMap_t &headersClassesMap, const std::unordered_set< std::string > headersToIgnore)
Generate a rootmap file in the new format, like { decls } namespace A { namespace B { template <typen...
static llvm::cl::opt< std::string > gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::desc("<output dictionary file>"), llvm::cl::cat(gRootclingOptions))
bool IsSelectionXml(const char *filename)
bool IsGoodLibraryName(const std::string &name)
static llvm::cl::opt< bool > gOptReflex("reflex", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), llvm::cl::cat(gRootclingOptions))
bool IsSelectionFile(const char *filename)
const std::string GenerateStringFromHeadersForClasses(const HeadersDeclsMap_t &headersClassesMap, const std::string &detectedUmbrella, bool payLoadOnly=false)
Generate a string for the dictionary from the headers-classes map.
bool IsSupportedClassName(const char *name)
static bool ModuleContainsHeaders(TModuleGenerator &modGen, clang::Module *module, std::vector< std::string > &missingHeaders)
Returns true iff a given module (and its submodules) contains all headers needed by the given ModuleG...
static llvm::cl::opt< bool > gOptIgnoreExistingDict("r", llvm::cl::desc("Deprecated. Similar to -f but it ignores the dictionary generation. \
When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptForce("f", llvm::cl::desc("Overwrite <file>s."), llvm::cl::cat(gRootclingOptions))
static void AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules)
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
static llvm::cl::list< std::string > gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), llvm::cl::cat(gRootclingOptions))
int CheckClassesForInterpreterOnlyDicts(cling::Interpreter &interp, RScanner &scan)
bool InheritsFromTSelector(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static void EmitTypedefs(const std::vector< const clang::TypedefNameDecl * > &tdvec)
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
bool Namespace__HasMethod(const clang::NamespaceDecl *cl, const char *name, const cling::Interpreter &interp)
static llvm::cl::list< std::string > gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), llvm::cl::cat(gRootclingOptions))
bool IsCorrectClingArgument(const std::string &argument)
Check if the argument is a sane cling argument.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)
void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream &dictStream, bool autoLoad=false)
Write the code to set the class name and the initialization object.
static llvm::cl::list< std::string > gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the <path> in the dictionary."), llvm::cl::cat(gRootclingOptions))
std::list< std::string > RecordDecl2Headers(const clang::CXXRecordDecl &rcd, const cling::Interpreter &interp, std::set< const clang::CXXRecordDecl * > &visitedDecls)
Extract the list of headers necessary for the Decl.
void EmitStreamerInfo(const char *normName)
static llvm::cl::opt< bool > gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), llvm::cl::cat(gRootclingOptions))
bool HasPath(const std::string &name)
Check if file has a path.
static llvm::cl::opt< std::string > gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), llvm::cl::cat(gRootclingOptions))
int CheckForUnsupportedClasses(const RScanner::ClassColl_t &annotatedRcds)
Check if the list of selected classes contains any class which is not supported.
llvm::StringRef GrabIndex(const clang::FieldDecl &member, int printError)
GrabIndex returns a static string (so use it or copy it immediately, do not call GrabIndex twice in t...
static void EmitEnums(const std::vector< const clang::EnumDecl * > &enumvec)
bool CheckClassDef(const clang::RecordDecl &cl, const cling::Interpreter &interp)
Return false if the class does not have ClassDef even-though it should.
bool NeedsSelection(const char *name)
int extractMultipleOptions(std::vector< ROOT::option::Option > &options, int oIndex, std::vector< std::string > &values)
Extract from options multiple values with the same option.
R__DLLEXPORT int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
cling::Interpreter *(* fTCling__GetInterpreter)()
bool(* fCloseStreamerInfoROOTFile)(bool writeEmptyRootPCM)
void(* fAddEnumToROOTFile)(const char *tdname)
void(* fInitializeStreamerInfoROOTFile)(const char *filename)
const char *(* fTROOT__GetIncludeDir)()
void(* fAddTypedefToROOTFile)(const char *tdname)
const char *(* fTROOT__GetEtcDir)()
void(* fAddStreamerInfoToROOTFile)(const char *normName)
const char ***(* fTROOT__GetExtraInterpreterArgs)()
static ArgStatus None(const Option &, bool)
For options that don't take an argument: Returns ARG_NONE.
Describes an option, its help text (usage) and how it should be parsed.
static option::ArgStatus Required(const option::Option &option, bool msg)
Determines the minimum lengths of the buffer and options arrays used for Parser.
unsigned options_max
Number of elements needed for an options[] array to be used for parsing the same argument vectors tha...
unsigned buffer_max
Number of elements needed for a buffer[] array to be used for parsing the same argument vectors that ...
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.
#define dest(otri, vertexptr)