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>
62#include <libprocstat.h>
71#include "cling/Interpreter/Interpreter.h"
72#include "cling/Interpreter/InterpreterCallbacks.h"
73#include "cling/Interpreter/LookupHelper.h"
74#include "cling/Interpreter/Value.h"
75#include "clang/AST/CXXInheritance.h"
76#include "clang/Basic/Diagnostic.h"
77#include "clang/Frontend/CompilerInstance.h"
78#include "clang/Frontend/FrontendActions.h"
79#include "clang/Frontend/FrontendDiagnostic.h"
80#include "clang/Lex/HeaderSearch.h"
81#include "clang/Lex/Preprocessor.h"
82#include "clang/Lex/ModuleMap.h"
83#include "clang/Lex/Pragma.h"
84#include "clang/Sema/Sema.h"
85#include "clang/Serialization/ASTWriter.h"
86#include "cling/Utils/AST.h"
88#include "llvm/ADT/StringRef.h"
90#include "llvm/Support/CommandLine.h"
91#include "llvm/Support/Path.h"
92#include "llvm/Support/PrettyStackTrace.h"
93#include "llvm/Support/Signals.h"
117#include <mach-o/dyld.h>
122#define strcasecmp _stricmp
123#define strncasecmp _strnicmp
131#define rootclingStringify(s) rootclingStringifyx(s)
132#define rootclingStringifyx(s) #s
139using std::string, std::map, std::ifstream, std::ofstream, std::endl, std::ios, std::vector;
150static llvm::cl::opt<bool>
152 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
153When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
173static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
177 for (
const auto td : tdvec)
180static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
184 for (
const auto en : enumvec) {
186 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
187 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
188 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
198 static std::string exepath;
201 exepath = _dyld_get_image_name(0);
203#if defined(__linux) || defined(__linux__)
204 char linkname[PATH_MAX];
210 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
211 int ret = readlink(linkname, buf, 1024);
212 if (ret > 0 && ret < 1024) {
218 procstat* ps = procstat_open_sysctl();
219 kinfo_proc* kp = kinfo_getproc(getpid());
222 char path_str[PATH_MAX] =
"";
223 procstat_getpathname(ps, kp, path_str,
sizeof(path_str));
231 char *buf =
new char[MAX_MODULE_NAME32 + 1];
232 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
234 while ((
p = strchr(
p,
'\\')))
240 return exepath.c_str();
246 const cling::Interpreter &interp)
254 const std::list<VariableSelectionRule> &fieldSelRules)
262 if (fieldSelRules.empty())
return;
264 clang::ASTContext &C = decl.getASTContext();
266 const std::string declName(decl.getNameAsString());
268 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
269 it != fieldSelRules.end(); ++it) {
270 if (! it->GetAttributeValue(propNames::name, varName))
continue;
271 if (declName == varName) {
274 BaseSelectionRule::AttributesMap_t::iterator iter;
275 std::string userDefinedProperty;
276 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
277 const std::string &
name = iter->first;
278 const std::string &
value = iter->second;
280 if (
name == propNames::name)
continue;
285 if (
name == propNames::iotype &&
286 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
287 const char *msg =
"Data member \"%s\" is an array or a pointer. "
288 "It is not possible to assign to it the iotype \"%s\". "
289 "This transformation is possible only with data members "
290 "which are not pointers or arrays.\n";
292 msg, varName.c_str(),
value.c_str());
300 if (
name == propNames::comment) {
301 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
value,
nullptr, 0));
305 if ((
name == propNames::transient &&
value ==
"true") ||
306 (
name == propNames::persistent &&
value ==
"false")) {
307 userDefinedProperty = propNames::comment + propNames::separator +
"!";
311 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
"!",
nullptr, 0));
316 userDefinedProperty =
name + propNames::separator +
value;
319 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
329 cling::Interpreter &interpreter,
337 using namespace clang;
338 SourceLocation commentSLoc;
339 llvm::StringRef comment;
341 ASTContext &C = CXXRD.getASTContext();
344 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
345 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
346 if (declSelRulePair == declSelRulesMap.end()){
347 const std::string thisClassName(CXXRD.getName());
348 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
353 if (thisClassBaseSelectionRule) {
356 BaseSelectionRule::AttributesMap_t::iterator iter;
357 std::string userDefinedProperty;
359 const std::string &
name =
attr.first;
364 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
371 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
372 E = CXXRD.decls_end();
I != E; ++
I) {
376 if (!(*I)->isImplicit()
377 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
381 if (isClassDefMacro) {
382 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
388 if (comment.size()) {
390 if (isClassDefMacro) {
391 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
392 }
else if (!isGenreflex) {
398 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
403 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
407 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
421 llvm::APInt
len = arrayType->getSize();
422 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
423 len *= subArrayType->getSize();
424 arrayType = subArrayType;
426 return len.getLimitedValue();
432 const cling::Interpreter &interp)
434 static const clang::CXXRecordDecl *TObject_decl
437 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
444 const cling::Interpreter &interp)
446 static const clang::CXXRecordDecl *TObject_decl
459 return (0 == strcasecmp(
filename + (
len - xmllen),
".xml"));
485 if (exepath && *exepath) {
487 char *ep =
new char[PATH_MAX];
488 if (!realpath(exepath, ep)) {
489 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
490 strlcpy(ep, exepath, PATH_MAX);
493 int nche = strlen(exepath) + 1;
494 char *ep =
new char[nche];
495 strlcpy(ep, exepath, nche);
499 if ((s = strrchr(ep,
'/'))) {
501 int removesubdirs = 2;
502 if (!strncmp(s + 1,
"rootcling_stage1.exe", 20)) {
506 }
else if (!strncmp(s + 1,
"rootcling_stage1", 16)) {
511 for (
int i = 1; s && i < removesubdirs; ++i) {
513 s = strrchr(ep,
'/');
527 int ncha = strlen(ep) + 10;
528 char *env =
new char[ncha];
529 snprintf(env, ncha,
"ROOTSYS=%s", ep);
550 const char *expectedTokens[],
551 size_t *end =
nullptr)
554 if (
line[0] !=
'#')
return false;
556 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
557 while (isspace(
line[pos])) ++pos;
558 size_t lenToken = strlen(*iToken);
559 if (
line.compare(pos, lenToken, *iToken)) {
578 if (recordDecl->hasOwningModule()) {
579 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
582 std::string qual_name;
588 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
597 if (classname.find(
':') == std::string::npos)
return;
600 int slen = classname.size();
601 for (
int k = 0; k < slen; ++k) {
602 if (classname[k] ==
':') {
603 if (k + 1 >= slen || classname[k + 1] !=
':') {
608 string base = classname.substr(0, k);
613 autoloads[base] =
"";
617 }
else if (classname[k] ==
'<') {
629 std::string classname;
631 while (file >>
line) {
633 if (
line.find(
"Library.") != 0)
continue;
635 int pos =
line.find(
":", 8);
636 classname =
line.substr(8, pos - 8);
641 getline(file,
line,
'\n');
642 while (
line[0] ==
' ')
line.replace(0, 1,
"");
646 if (classname ==
"ROOT::TImpProxy") {
650 autoloads[classname] =
line;
665 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
667 while (getline(file,
line,
'\n')) {
668 if (
line ==
"{ decls }") {
669 while (getline(file,
line,
'\n')) {
670 if (
line[0] ==
'[')
break;
673 const char firstChar =
line[0];
674 if (firstChar ==
'[') {
676 libs =
line.substr(1,
line.find(
']') - 1);
677 while (libs[0] ==
' ') libs.replace(0, 1,
"");
678 }
else if (0 != keyLenMap.count(firstChar)) {
679 unsigned int keyLen = keyLenMap.at(firstChar);
680 keyname =
line.substr(keyLen,
line.length() - keyLen);
682 autoloads[keyname] = libs;
692void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
694 std::ifstream filelist(fileListName.c_str());
701 if (llvm::sys::fs::is_directory(
filename))
continue;
707 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
709 file.seekg(0, std::ios::beg);
730 const string &fullname,
731 const clang::RecordDecl *cl,
732 cling::Interpreter &interp)
735 const clang::FunctionDecl *method
740 clang::TranslationUnitDecl *TU =
741 cl->getASTContext().getTranslationUnitDecl();
745 bool has_input_error =
false;
746 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
748 if (strstr(
filename.c_str(),
"TBuffer.h") !=
nullptr ||
749 strstr(
filename.c_str(),
"Rtypes.h") !=
nullptr) {
751 has_input_error =
true;
754 has_input_error =
true;
756 if (has_input_error) {
758 const char *maybeconst =
"";
759 const char *mayberef =
"&";
760 if (
what[strlen(
what) - 1] ==
'<') {
761 maybeconst =
"const ";
765 "in this version of ROOT, the option '!' used in a linkdef file\n"
766 " implies the actual existence of customized operators.\n"
767 " The following declaration is now required:\n"
768 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
770 return has_input_error;
782 int ncha = fullname.length() + 13;
783 char *
proto =
new char[ncha];
795 return has_input_error;
801bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
807 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
811 bool isAbstract = clxx->isAbstract();
814 std::string qualName;
816 const char *qualName_c = qualName.c_str();
818 "because it inherits from TObject but does not "
819 "have its own ClassDef.\n",
832 if (
m.getType().isConstQualified()) {
833 string ret =
"const_cast< ";
836 if (type_name.substr(0,6)==
"const ") {
837 ret += type_name.c_str()+6;
843 ret +=
m.getName().str();
847 return prefix +
m.getName().str();
857 const cling::Interpreter &interp,
859 std::ostream &dictStream)
862 std::string mTypename;
875 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
877 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
878 if (!tmplt_specialization)
return 0;
884 string fulName1, fulName2;
885 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
886 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
887 clang::QualType ti = arg0.getAsType();
891 fulName1 = ti.getAsString();
894 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
895 clang::QualType tmplti = arg1.getAsType();
898 fulName2 = tmplti.getAsString();
905 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
911 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
915 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
917 }
else if (
m.getType()->isPointerType()) {
922 dictStream <<
" {" << std::endl;
924 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
929 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
932 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
935 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
936 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
937 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
940 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
941 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
942 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
946 dictStream <<
" R__stl.clear();" << std::endl;
949 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
950 <<
" if (R__tcl1==0) {" << std::endl
951 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
952 << fulName1.c_str() <<
"!\");" << std::endl
953 <<
" return;" << std::endl
954 <<
" }" << std::endl;
957 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
958 <<
" if (R__tcl2==0) {" << std::endl
959 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
960 << fulName2.c_str() <<
"!\");" << std::endl
961 <<
" return;" << std::endl
962 <<
" }" << std::endl;
965 dictStream <<
" int R__i, R__n;" << std::endl
966 <<
" R__b >> R__n;" << std::endl;
969 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
971 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
975 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
995 std::string keyName(ti.getAsString());
996 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
997 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
998 <<
" R__stl.insert(R__t3);" << std::endl;
1006 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1011 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1014 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1019 dictStream <<
" }" << std::endl
1020 <<
" }" << std::endl;
1021 if (isArr) dictStream <<
" }" << std::endl;
1027 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
1029 dictStream <<
" {" << std::endl;
1032 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1035 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1038 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1041 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1045 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1046 <<
" R__b << R__n;" << std::endl
1047 <<
" if(R__n) {" << std::endl;
1050 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1051 <<
" if (R__tcl1==0) {" << std::endl
1052 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1053 << fulName1.c_str() <<
"!\");" << std::endl
1054 <<
" return;" << std::endl
1055 <<
" }" << std::endl;
1058 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1059 <<
" if (R__tcl2==0) {" << std::endl
1060 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1061 <<
" return;" << std::endl
1062 <<
" }" << std::endl;
1065 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1066 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1068 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1069 clang::QualType tmplti = arg1.getAsType();
1076 dictStream <<
" }" << std::endl
1077 <<
" }" << std::endl
1078 <<
" }" << std::endl;
1079 if (isArr) dictStream <<
" }" << std::endl;
1091 std::string mTypenameStr;
1095 if (!strcmp(mTypeName,
"string")) {
1097 std::string fieldname =
m.getName().str();
1100 if (
m.getType()->isConstantArrayType()) {
1101 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1102 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1104 std::stringstream fullIdx;
1105 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1108 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1109 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1110 fullIdx <<
"[R__i" << dim <<
"]";
1111 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1114 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1115 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1118 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1119 if (
m.getType()->isPointerType())
1120 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1121 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1123 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1127 if (
m.getType()->isPointerType())
1128 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1129 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1130 else if (
m.getType()->isConstantArrayType()) {
1131 std::stringstream fullIdx;
1132 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1135 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1136 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1137 fullIdx <<
"[R__i" << dim <<
"]";
1138 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1141 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1143 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1154 if (
m.getType()->isPointerType()) {
1155 if (
m.getType()->getPointeeType()->isPointerType()) {
1167 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1169 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1171 dictStream <<
"[0]";
1172 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1187 int enclSpaceNesting = 0;
1194 dictStream <<
"#include \"TInterpreter.h\"\n";
1196 dictStream <<
"//_______________________________________"
1197 <<
"_______________________________________" << std::endl;
1198 if (add_template_keyword) dictStream <<
"template <> ";
1199 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1202 <<
"//_______________________________________"
1203 <<
"_______________________________________" << std::endl;
1204 if (add_template_keyword) dictStream <<
"template <> ";
1205 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1206 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1208 dictStream <<
"//_______________________________________"
1209 <<
"_______________________________________" << std::endl;
1210 if (add_template_keyword) dictStream <<
"template <> ";
1211 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1212 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1213 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1215 <<
"//_______________________________________"
1216 <<
"_______________________________________" << std::endl;
1217 if (add_template_keyword) dictStream <<
"template <> ";
1218 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1219 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1220 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1222 <<
"//_______________________________________"
1223 <<
"_______________________________________" << std::endl;
1224 if (add_template_keyword) dictStream <<
"template <> ";
1225 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1229 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1230 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1231 <<
"*)nullptr)->GetClass();" << std::endl
1232 <<
" return fgIsA;\n"
1233 <<
"}" << std::endl << std::endl
1235 <<
"//_______________________________________"
1236 <<
"_______________________________________" << std::endl;
1237 if (add_template_keyword) dictStream <<
"template <> ";
1238 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1240 dictStream <<
" Dictionary();\n";
1242 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1243 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1245 dictStream <<
" return fgIsA;" << std::endl
1246 <<
"}" << std::endl << std::endl;
1248 while (enclSpaceNesting) {
1249 dictStream <<
"} // namespace " << nsname << std::endl;
1258 cling::Interpreter &interp,
1259 std::ostream &dictStream)
1261 if (cl->isAnonymousNamespace()) {
1273 if (classname !=
"ROOT") {
1277 dictStream <<
" namespace ROOTDict {" << std::endl;
1280 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1284 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1285 dictStream << std::endl
1287 <<
" // Function generating the singleton type initializer" << std::endl
1290 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1291 <<
" {" << std::endl
1293 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1294 <<
" {" << std::endl
1297 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1299 <<
" instance(\"" << classname.c_str() <<
"\", ";
1302 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1304 dictStream <<
"0 /*version*/, ";
1308 for (
unsigned int i = 0; i <
filename.length(); i++) {
1312 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1316 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1318 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1321 dictStream << 0 <<
");" << std::endl
1323 <<
" return &instance;" << std::endl
1324 <<
" }" << std::endl
1325 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1326 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1327 <<
" // Static variable to force the class initialization" << std::endl
1329 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1330 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1333 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1334 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1335 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1336 <<
" }" << std::endl << std::endl;
1339 dictStream <<
" }" << std::endl;
1341 dictStream <<
"}" << std::endl;
1343 dictStream << std::endl;
1352llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1355 llvm::StringRef where;
1358 if (
index.size() == 0 && printError) {
1359 const char *errorstring;
1362 errorstring =
"is not an integer";
1365 errorstring =
"has not been defined before the array";
1368 errorstring =
"is a private member of a parent class";
1371 errorstring =
"is not known";
1374 errorstring =
"UNKNOWN ERROR!!!!";
1377 if (where.size() == 0) {
1379 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1382 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1391 const cling::Interpreter &interp,
1393 std::ostream &dictStream)
1395 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1396 if (clxx ==
nullptr)
return;
1403 int enclSpaceNesting = 0;
1409 dictStream <<
"//_______________________________________"
1410 <<
"_______________________________________" << std::endl;
1411 if (add_template_keyword) dictStream <<
"template <> ";
1412 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1413 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1421 int basestreamer = 0;
1422 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1426 string base_fullname;
1429 if (strstr(base_fullname.c_str(),
"::")) {
1431 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1432 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1433 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1435 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1440 if (!basestreamer) {
1441 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1442 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1444 dictStream <<
"}" << std::endl << std::endl;
1445 while (enclSpaceNesting) {
1446 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1453 string classname = fullname;
1454 if (strstr(fullname.c_str(),
"::")) {
1456 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1457 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1458 classname =
"thisClass";
1460 for (
int i = 0; i < 2; i++) {
1465 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1466 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1467 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1469 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1470 dictStream <<
" } else {" << std::endl;
1471 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1476 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1480 string base_fullname;
1483 if (strstr(base_fullname.c_str(),
"::")) {
1485 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1486 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1487 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1490 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1496 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1501 clang::QualType
type = field_iter->getType();
1502 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1512 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1516 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1519 if (strncmp(comment,
"!", 1)) {
1522 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1523 if (
type.getTypePtr()->isConstantArrayType() &&
1524 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1525 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1529 dictStream <<
" int R__i;" << std::endl;
1532 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1534 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());
1535 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1537 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1539 }
else if (
type.getTypePtr()->isPointerType()) {
1540 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1541 if (indexvar.size() == 0) {
1543 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1544 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1546 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1550 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1555 <<
"," << indexvar.str() <<
");" << std::endl;
1556 }
else if (isDouble32) {
1558 <<
"," << indexvar.str() <<
");" << std::endl;
1561 <<
"," << indexvar.str() <<
");" << std::endl;
1565 dictStream <<
" R__b.WriteFastArrayFloat16("
1566 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1567 }
else if (isDouble32) {
1568 dictStream <<
" R__b.WriteFastArrayDouble32("
1569 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1571 dictStream <<
" R__b.WriteFastArray("
1572 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1576 }
else if (
type.getTypePtr()->isArrayType()) {
1578 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1579 if (underling_type->isEnumeralType())
1580 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1584 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1585 }
else if (isDouble32) {
1587 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1590 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1594 if (underling_type->isEnumeralType()) {
1595 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1598 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1599 }
else if (isDouble32) {
1600 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1603 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1608 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1611 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1612 if (underling_type->isEnumeralType())
1613 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1614 << s <<
");" << std::endl;
1615 else if (isFloat16) {
1617 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1618 }
else if (isDouble32) {
1620 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1623 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1626 if (underling_type->isEnumeralType())
1627 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1628 else if (isFloat16) {
1629 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1630 }
else if (isDouble32) {
1631 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1633 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1637 }
else if (underling_type->isEnumeralType()) {
1639 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1640 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1642 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1647 <<
"=Float16_t(R_Dummy);}" << std::endl;
1650 }
else if (isDouble32) {
1653 <<
"=Double32_t(R_Dummy);}" << std::endl;
1675 if (
type.getTypePtr()->isConstantArrayType() &&
1676 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1677 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1681 dictStream <<
" int R__i;" << std::endl;
1684 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1689 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1694 dictStream <<
"[R__i];" << std::endl;
1695 }
else if (
type.getTypePtr()->isPointerType()) {
1703 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1704 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1706 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1710 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1724 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1730 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1734 dictStream <<
" int R__i;" << std::endl;
1737 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1738 std::string mTypeNameStr;
1740 const char *mTypeName = mTypeNameStr.c_str();
1741 const char *constwd =
"const ";
1742 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1743 mTypeName += strlen(constwd);
1744 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1746 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1750 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1756 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1757 << field_iter->getName().str() <<
"));" << std::endl;
1768 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1769 <<
" }" << std::endl
1770 <<
"}" << std::endl << std::endl;
1772 while (enclSpaceNesting) {
1773 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1781 const cling::Interpreter &interp,
1783 std::ostream &dictStream)
1787 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1788 if (clxx ==
nullptr)
return;
1793 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1805 int enclSpaceNesting = 0;
1811 dictStream <<
"//_______________________________________"
1812 <<
"_______________________________________" << std::endl;
1813 if (add_template_keyword) dictStream <<
"template <> ";
1814 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1816 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1817 <<
" if (R__b.IsReading()) {" << std::endl
1818 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1819 <<
" } else {" << std::endl
1820 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1821 <<
" }" << std::endl
1822 <<
"}" << std::endl << std::endl;
1824 while (enclSpaceNesting) {
1825 dictStream <<
"} // namespace " << nsname << std::endl;
1833 const cling::Interpreter &interp,
1835 std::ostream &dictStream,
1836 bool isAutoStreamer)
1838 if (isAutoStreamer) {
1848 std::string &code_for_parser)
1850 code_for_parser +=
"#ifdef __CINT__\n\n";
1851 code_for_parser +=
"#pragma link off all globals;\n";
1852 code_for_parser +=
"#pragma link off all classes;\n";
1853 code_for_parser +=
"#pragma link off all functions;\n\n";
1855 for (std::string& arg : InputFiles) {
1857 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1858 for (
int j = 0; j < 3; j++) {
1859 if (arg[
l] ==
'-') {
1864 if (arg[
l] ==
'!') {
1869 if (arg[
l] ==
'+') {
1875 if (nostr || noinp) {
1877 if (nostr) strlcat(trail,
"-", 3);
1878 if (noinp) strlcat(trail,
"!", 3);
1881 strlcpy(trail,
"+", 3);
1885 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1886 llvm::sys::path::replace_extension(filestem,
"");
1888 code_for_parser +=
"#pragma link C++ class ";
1889 code_for_parser += filestem.str().str();
1890 if (nostr || noinp || bcnt)
1891 code_for_parser += trail;
1892 code_for_parser +=
";\n";
1895 code_for_parser +=
"\n#endif\n";
1903bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1908 static const char *fopenopts =
"rb";
1910 static const char *fopenopts =
"r";
1914 fp = fopen(pname.c_str(), fopenopts);
1920 llvm::SmallVector<std::string, 10> includePaths;
1922 interp.GetIncludePaths(includePaths,
false,
false);
1924 const size_t nPaths = includePaths.size();
1925 for (
size_t i = 0; i < nPaths; i += 1 ) {
1929 fp = fopen(pname.c_str(), fopenopts);
1951 const char *inc = strstr(original,
"\\inc\\");
1953 inc = strstr(original,
"/inc/");
1954 if (inc && strlen(inc) > 5)
1974 cling::Interpreter &interp,
1977 std::ostringstream out;
1982 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1983 const std::string &hdrName
2001static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
2002 llvm::StringRef iSysRoot,
2003 clang::Module *module =
nullptr)
2006 llvm::SmallVector<char, 128> buffer;
2007 llvm::BitstreamWriter stream(buffer);
2008 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
2009 std::unique_ptr<llvm::raw_ostream> out =
2010 compilerInstance->createOutputFile(fileName,
true,
2019 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2021 writer.WriteAST(compilerInstance->getSema(), fileName.str(), module, iSysRoot);
2024 out->write(&buffer.front(), buffer.size());
2036 const std::string ¤tDirectory)
2038 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2040 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2048static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2051 if (headers.empty())
2055 std::stringstream includes;
2056 for (
const std::string &header : headers) {
2057 includes <<
"#include \"" << header <<
"\"\n";
2059 std::string includeListStr = includes.str();
2060 auto result = interpreter.declare(includeListStr);
2061 return result == cling::Interpreter::CompilationResult::kSuccess;
2069 char platformDefines[64] = {0};
2070#ifdef __INTEL_COMPILER
2071 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2072 clingArgs.push_back(platformDefines);
2075 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2076 clingArgs.push_back(platformDefines);
2079 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2080 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2081 clingArgs.push_back(platformDefines);
2083#ifdef __GNUC_MINOR__
2084 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2085 clingArgs.push_back(platformDefines);
2088 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2089 clingArgs.push_back(platformDefines);
2092 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2093 clingArgs.push_back(platformDefines);
2096 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2097 clingArgs.push_back(platformDefines);
2099#ifdef _STLPORT_VERSION
2101 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2102 clingArgs.push_back(platformDefines);
2105 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2106 clingArgs.push_back(platformDefines);
2109 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2110 clingArgs.push_back(platformDefines);
2113 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2114 clingArgs.push_back(platformDefines);
2117 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2118 clingArgs.push_back(platformDefines);
2121 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2122 clingArgs.push_back(platformDefines);
2125 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2126 clingArgs.push_back(platformDefines);
2130 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
2131 clingArgs.push_back(platformDefines);
2134 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2135 clingArgs.push_back(platformDefines);
2136 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2137 clingArgs.push_back(platformDefines);
2146 return llvm::sys::path::filename(path).str();
2156 if (std::string::npos != pos) {
2157 dirname.assign(path.begin(), path.begin() + pos + 1);
2168 std::string dictLocation;
2170 return !dictLocation.empty();
2176 std::string &rootmapLibName)
2180 if (rootmapFileName.empty()) {
2182 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2183 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2184 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2186 rootmapLibName.c_str(),
2187 rootmapFileName.c_str());
2196 std::string &ctxtName,
2197 const cling::Interpreter &interpreter,
2198 bool treatParent =
true)
2200 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2202 if (!outerCtxt)
return;
2204 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2214 std::string &ctxtName,
2215 const cling::Interpreter &interpreter)
2217 const clang::DeclContext *theContext = theDecl.getDeclContext();
2225 const cling::Interpreter &interp)
2227 if (!decls.empty()) {
2228 std::string autoLoadKey;
2229 for (
auto &
d : decls) {
2233 if (autoLoadKey.empty()) {
2234 names.push_back(
d->getQualifiedNameAsString());
2252 const std::string &rootmapLibName,
2253 const std::list<std::string> &classesDefsList,
2254 const std::list<std::string> &classesNames,
2255 const std::list<std::string> &nsNames,
2256 const std::list<std::string> &tdNames,
2257 const std::list<std::string> &enNames,
2258 const std::list<std::string> &varNames,
2260 const std::unordered_set<std::string> headersToIgnore)
2263 std::ofstream rootmapFile(rootmapFileName.c_str());
2271 std::unordered_set<std::string> classesKeys;
2275 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2276 !enNames.empty() || !varNames.empty()) {
2279 if (!classesDefsList.empty()) {
2280 rootmapFile <<
"{ decls }\n";
2281 for (
auto & classDef : classesDefsList) {
2282 rootmapFile << classDef << std::endl;
2284 rootmapFile <<
"\n";
2286 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2289 if (!classesNames.empty()) {
2290 rootmapFile <<
"# List of selected classes\n";
2291 for (
auto & className : classesNames) {
2292 rootmapFile <<
"class " << className << std::endl;
2293 classesKeys.insert(className);
2296 std::unordered_set<std::string> treatedHeaders;
2297 for (
auto & className : classesNames) {
2299 if (className.find(
"<") != std::string::npos)
continue;
2300 if (headersClassesMap.count(className)) {
2301 auto &headers = headersClassesMap.at(className);
2302 if (!headers.empty()){
2303 auto &header = headers.front();
2304 if (treatedHeaders.insert(header).second &&
2305 headersToIgnore.find(header) == headersToIgnore.end() &&
2307 rootmapFile <<
"header " << header << std::endl;
2315 if (!nsNames.empty()) {
2316 rootmapFile <<
"# List of selected namespaces\n";
2317 for (
auto & nsName : nsNames) {
2318 rootmapFile <<
"namespace " << nsName << std::endl;
2323 if (!tdNames.empty()) {
2324 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2325 for (
const auto & autoloadKey : tdNames)
2326 if (classesKeys.insert(autoloadKey).second)
2327 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2332 if (!enNames.empty()){
2333 rootmapFile <<
"# List of selected enums and outer classes\n";
2334 for (
const auto & autoloadKey : enNames)
2335 if (classesKeys.insert(autoloadKey).second)
2336 rootmapFile <<
"enum " << autoloadKey << std::endl;
2340 if (!varNames.empty()){
2341 rootmapFile <<
"# List of selected vars\n";
2342 for (
const auto & autoloadKey : varNames)
2343 if (classesKeys.insert(autoloadKey).second)
2344 rootmapFile <<
"var " << autoloadKey << std::endl;
2358 auto nsPattern =
'{';
auto nsPatternLength = 1;
2359 auto foundNsPos =
line.find_last_of(nsPattern);
2360 if (foundNsPos == std::string::npos)
return {
"",
""};
2361 foundNsPos+=nsPatternLength;
2362 auto extNs =
line.substr(0,foundNsPos);
2364 auto nsEndPattern =
'}';
2365 auto foundEndNsPos =
line.find(nsEndPattern);
2366 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2368 return {extNs, contained};
2384 std::map<std::string, std::string> nsEntitiesMap;
2385 std::list<std::string> optFwdDeclList;
2386 for (
auto const & fwdDecl : fwdDeclarationsList){
2389 if (extNsAndEntities.first.empty()) {
2391 optFwdDeclList.push_front(fwdDecl);
2393 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2394 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2398 std::string optFwdDecl;
2399 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2400 optFwdDecl = extNsAndEntities.first;
2401 optFwdDecl += extNsAndEntities.second;
2402 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2405 optFwdDeclList.push_front(optFwdDecl);
2408 return optFwdDeclList;
2416 std::list<std::string> &el_list,
2417 std::unordered_set<std::string> &el_set)
2419 std::stringstream elStream(el);
2422 while (getline(elStream, tmp,
'\n')) {
2424 if (el_set.insert(tmp).second && !tmp.empty()) {
2425 el_list.push_back(tmp);
2436 std::list<std::string> &classesList,
2437 std::list<std::string> &classesListForRootmap,
2438 std::list<std::string> &fwdDeclarationsList,
2439 const cling::Interpreter &interpreter)
2447 std::unordered_set<std::string> classesSet;
2448 std::unordered_set<std::string> outerMostClassesSet;
2450 std::string attrName, attrValue;
2451 bool isClassSelected;
2452 std::unordered_set<std::string> availableFwdDecls;
2453 std::string fwdDeclaration;
2455 fwdDeclaration =
"";
2461 fwdDeclaration =
"";
2468 isClassSelected =
true;
2469 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2470 std::string normalizedName;
2471 normalizedName = selClass.GetNormalizedName();
2472 if (!normalizedName.empty() &&
2473 !classesSet.insert(normalizedName).second &&
2474 outerMostClassesSet.count(normalizedName) == 0) {
2475 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2476 <<
" was already selected. This means that two different instances of"
2477 <<
" clang::RecordDecl had the same name, which is not possible."
2478 <<
" This can be a hint of a serious problem in the class selection."
2479 <<
" In addition, the generated dictionary would not even compile.\n";
2482 classesList.push_back(normalizedName);
2485 const char *reqName(selClass.GetRequestedName());
2488 fwdDeclaration =
"";
2493 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2494 fwdDeclaration =
"";
2497 std::string fwdDeclarationTemplateSpec;
2499 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2507 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2509 attrName ==
"rootmap" &&
2510 attrValue ==
"false") {
2511 attrName = attrValue =
"";
2512 isClassSelected =
false;
2516 if (isClassSelected) {
2532 std::string outerMostClassName;
2534 if (!outerMostClassName.empty() &&
2535 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2536 classesSet.insert(outerMostClassName).second &&
2537 outerMostClassesSet.insert(outerMostClassName).second) {
2538 classesListForRootmap.push_back(outerMostClassName);
2540 classesListForRootmap.push_back(normalizedName);
2541 if (reqName && reqName[0] && reqName != normalizedName) {
2542 classesListForRootmap.push_back(reqName);
2547 std::string demangledName = selClass.GetDemangledTypeInfo();
2548 if (!demangledName.empty()) {
2553 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2555 classesListForRootmap.push_back(demangledName);
2561 classesListForRootmap.sort();
2574 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2589 if (clang::CXXRecordDecl *CXXRD =
2590 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2602 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2605 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2608 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2624 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2625 "#include \"TFile.h\"\n"
2626 "#include \"TObjArray.h\"\n"
2627 "#include \"TVirtualArray.h\"\n"
2628 "#include \"TStreamerElement.h\"\n"
2629 "#include \"TProtoClass.h\"\n"
2630 "#include \"TBaseClass.h\"\n"
2631 "#include \"TListOfDataMembers.h\"\n"
2632 "#include \"TListOfEnums.h\"\n"
2633 "#include \"TListOfEnumsWithLock.h\"\n"
2634 "#include \"TDataMember.h\"\n"
2635 "#include \"TEnum.h\"\n"
2636 "#include \"TEnumConstant.h\"\n"
2637 "#include \"TDictAttributeMap.h\"\n"
2638 "#include \"TMessageHandler.h\"\n"
2639 "#include \"TArray.h\"\n"
2640 "#include \"TRefArray.h\"\n"
2641 "#include \"root_std_complex.h\"\n")
2642 != cling::Interpreter::kSuccess)
2653 cling::Interpreter &interp,
2659 bool writeEmptyRootPCM)
2663 bool needsCollectionProxy =
false;
2685 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2686 if (nsName.find(
"(anonymous)") == std::string::npos)
2691 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2695 if (selClass.RequestOnlyTClass()) {
2703 if (clang::CXXRecordDecl *CXXRD =
2704 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2708 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2716 }
else if (CRD->getName() ==
"RVec") {
2717 static const clang::DeclContext *vecOpsDC =
nullptr;
2719 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2720 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2721 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2729 needsCollectionProxy);
2744 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2748 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2760 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2764 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2769 needsCollectionProxy);
2804 if (finRetCode != 0)
return finRetCode;
2814 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2815 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2818 <<
"#define R__NO_DEPRECATION" << std::endl
2823 <<
"\n/*******************************************************************/\n"
2824 <<
"#include <stddef.h>\n"
2825 <<
"#include <stdio.h>\n"
2826 <<
"#include <stdlib.h>\n"
2827 <<
"#include <string.h>\n"
2828 <<
"#include <assert.h>\n"
2829 <<
"#define G__DICTIONARY\n"
2830 <<
"#include \"ROOT/RConfig.hxx\"\n"
2831 <<
"#include \"TClass.h\"\n"
2832 <<
"#include \"TDictAttributeMap.h\"\n"
2833 <<
"#include \"TInterpreter.h\"\n"
2834 <<
"#include \"TROOT.h\"\n"
2835 <<
"#include \"TBuffer.h\"\n"
2836 <<
"#include \"TMemberInspector.h\"\n"
2837 <<
"#include \"TInterpreter.h\"\n"
2838 <<
"#include \"TVirtualMutex.h\"\n"
2839 <<
"#include \"TError.h\"\n\n"
2840 <<
"#ifndef G__ROOT\n"
2841 <<
"#define G__ROOT\n"
2843 <<
"#include \"RtypesImp.h\"\n"
2844 <<
"#include \"TIsAProxy.h\"\n"
2845 <<
"#include \"TFileMergeInfo.h\"\n"
2846 <<
"#include <algorithm>\n"
2847 <<
"#include \"TCollectionProxyInfo.h\"\n"
2848 <<
"/*******************************************************************/\n\n"
2849 <<
"#include \"TDataMember.h\"\n\n";
2856 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2857 <<
"namespace std {} using namespace std;\n\n";
2863 const std::string &includeForSource,
2864 const std::string &extraIncludes)
2866 dictStream <<
"// Header files passed as explicit arguments\n"
2867 << includeForSource << std::endl
2868 <<
"// Header files passed via #pragma extra_include\n"
2869 << extraIncludes << std::endl;
2875#if defined(R__IOSSIM) || defined(R__IOS)
2900 return filename +
"_tmp_" + std::to_string(getpid());
2907 if (nameStr.empty())
return;
2909 std::string tmpNameStr(getTmpFileName(nameStr));
2912 const char *
name(nameStr.c_str());
2913 const char *tmpName(tmpNameStr.c_str());
2915 m_names.push_back(nameStr);
2916 m_tempNames.push_back(tmpNameStr);
2920 if (0 == std::rename(
name , tmpName)) {
2925 nameStr = tmpNameStr;
2936 for (
unsigned int i = 0; i < m_size; ++i) {
2937 const char *tmpName = m_tempNames[i].c_str();
2939 std::ifstream ifile(tmpName);
2944 if (ifile.is_open())
2946 if (0 != std::remove(tmpName)) {
2959 for (
unsigned int i = 0; i < m_size; ++i) {
2960 const char *tmpName = m_tempNames[i].c_str();
2961 const char *
name = m_names[i].c_str();
2963 std::ifstream ifile(tmpName);
2968 if (ifile.is_open())
2974 if (0 != std::rename(tmpName ,
name)) {
2975 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2976 llvm::sys::fs::remove(tmpName);
2980 if (0 != std::rename(tmpName ,
name)) {
2992 size_t i = std::distance(m_tempNames.begin(),
2993 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2994 if (i == m_tempNames.size())
return m_emptyString;
3001 std::cout <<
"Restoring files in temporary file catalog:\n";
3002 for (
unsigned int i = 0; i < m_size; ++i) {
3003 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3020 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
3021 const size_t dotPos = splitDictName.find_last_of(
".");
3022 splitDictName.insert(dotPos,
"_classdef");
3024 return new std::ofstream(splitDictName.c_str());
3033 std::list<std::string> &diagnosticPragmas)
3035 static const std::string pattern(
"-Wno-");
3037 if (arg.find(pattern) != 0)
3042 diagnosticPragmas.push_back(arg);
3048 cling::Interpreter &interp)
3051 std::string fwdDecl;
3052 std::string initStr(
"{");
3054 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3055 auto &clTemplDecl = *strigNargsToKeepPair.first;
3056 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3059 + std::to_string(strigNargsToKeepPair.second)
3062 if (!fwdDeclnArgsToSkipColl.empty())
3073 if (qt.isNull())
return qt;
3074 clang::QualType thisQt(qt);
3075 while (thisQt->isPointerType() ||
3076 thisQt->isReferenceType()) {
3077 thisQt = thisQt->getPointeeType();
3087 const cling::Interpreter &interp,
3088 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3090 std::list<std::string> headers;
3093 cling::Interpreter::PushTransactionRAII RAII(&interp);
3096 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3100 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3103 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3104 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3106 if (tArgQualType.isNull())
continue;
3107 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3108 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3115 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3117 if (baseQualType.isNull())
continue;
3118 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3119 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3124 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3125 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3127 if (fieldQualType.isNull()) continue ;
3128 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3129 if (fieldCxxRcd->hasDefinition())
3130 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3136 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3138 for (
auto & fPar : methodIt->parameters()) {
3140 if (fParQualType.isNull())
continue;
3141 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3142 if (fParCxxRcd->hasDefinition())
3143 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3148 if (retQualType.isNull())
continue;
3149 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3150 if (retCxxRcd->hasDefinition())
3159 headers.emplace_back(header);
3172 if (
auto dclCtxt= rcd.getDeclContext()){
3173 if (! dclCtxt->isStdNamespace()){
3182 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3183 if (!clAsTmplSpecDecl)
return false;
3188 auto& astCtxt = rcd.getASTContext();
3189 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3190 for (
auto&& arg : templInstArgs.asArray()){
3192 auto argKind = arg.getKind();
3193 if (argKind != clang::TemplateArgument::Type){
3194 if (argKind == clang::TemplateArgument::Integral)
continue;
3198 auto argQualType = arg.getAsType();
3199 auto isPOD = argQualType.isPODType(astCtxt);
3201 if (isPOD)
continue;
3203 auto argType = argQualType.getTypePtr();
3204 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3207 if (isArgGoodForAutoParseMap)
continue;
3226 const cling::Interpreter &interp)
3228 std::set<const clang::CXXRecordDecl *> visitedDecls;
3229 std::unordered_set<std::string> buffer;
3230 std::string autoParseKey;
3233 for (
auto & annotatedRcd : annotatedRcds) {
3234 if (
const clang::CXXRecordDecl *cxxRcd =
3235 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3237 visitedDecls.clear();
3241 headers.remove_if([&buffer](
const std::string & s) {
3242 return !buffer.insert(s).second;
3245 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3247 headersDeclsMap[autoParseKey] = headers;
3248 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3250 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3255 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3256 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3257 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3263 for (
auto & tDef : tDefDecls) {
3264 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3266 visitedDecls.clear();
3271 headers.remove_if([&buffer](
const std::string & s) {
3272 return !buffer.insert(s).second;
3275 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3276 headersDeclsMap[autoParseKey] = headers;
3281 for (
auto & func : funcDecls) {
3287 for (
auto & var : varDecls) {
3293 for (
auto & en : enumDecls) {
3303 const cling::Interpreter &interp)
3305 std::string newFwdDeclString;
3309 std::string fwdDeclString;
3311 std::unordered_set<std::string> fwdDecls;
3332 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3337 selectedDecls.begin(),
3341 selectedDecls.push_back(TD);
3346 std::string fwdDeclLogs;
3354 std::cout <<
"Logs from forward decl printer: \n"
3371 if (fwdDeclString.empty()) fwdDeclString =
"";
3372 return fwdDeclString;
3379 const std::string &detectedUmbrella,
3380 bool payLoadOnly =
false)
3382 std::string headerName;
3385 std::cout <<
"Class-headers Mapping:\n";
3386 std::string headersClassesMapString =
"";
3387 for (
auto const & classHeaders : headersClassesMap) {
3389 std::cout <<
" o " << classHeaders.first <<
" --> ";
3390 headersClassesMapString +=
"\"";
3391 headersClassesMapString += classHeaders.first +
"\"";
3392 for (
auto const & header : classHeaders.second) {
3393 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3394 headersClassesMapString +=
", " + headerName;
3396 std::cout <<
", " << headerName;
3401 std::cout << std::endl;
3402 headersClassesMapString +=
", \"@\",\n";
3404 headersClassesMapString +=
"nullptr";
3405 return headersClassesMapString;
3428 static const std::vector<std::string> namePrfxes {
3431 auto pos = find_if(namePrfxes.begin(),
3433 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3434 return namePrfxes.end() == pos;
3441 static const std::vector<std::string> uclNamePrfxes {
3445 static const std::set<std::string> unsupportedClassesNormNames{
3448 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3449 auto pos = find_if(uclNamePrfxes.begin(),
3450 uclNamePrfxes.end(),
3451 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3452 return uclNamePrfxes.end() == pos;
3462 for (
auto&& aRcd : annotatedRcds){
3463 auto clName = aRcd.GetNormalizedName();
3465 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3466 <<
"currently the support for its I/O is not yet available. Note that "
3467 << clName <<
", even if not selected, will be available for "
3468 <<
"interpreted code.\n";
3472 std::cerr <<
"Error: It is not necessary to explicitly select class "
3473 << clName <<
". I/O is supported for it transparently.\n";
3485 bool isLocked =
false;
3488 InterpreterCallbacks(interp),
3489 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3494 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3495 clang::OptionalFileEntryRef , llvm::StringRef ,
3496 llvm::StringRef ,
const clang::Module * ,
3497 clang::SrcMgr::CharacteristicKind )
override
3499 if (isLocked)
return;
3500 if (IsAngled)
return;
3501 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3502 auto curLexer = PP.getCurrentFileLexer();
3503 if (!curLexer)
return;
3504 auto fileEntry = curLexer->getFileEntry();
3505 if (!fileEntry)
return;
3506 auto thisFileName = fileEntry->getName();
3507 auto fileNameAsString = FileName.str();
3509 if (isThisLinkdef) {
3511 if (isTheIncludedLinkdef) {
3512 fFilesIncludedByLinkdef.clear();
3515 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3529 clang::SourceLocation ImportLoc,
3530 bool ForPragma)
override {
3532 using namespace clang;
3533 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3534 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3535 HeaderSearch& HS = PP.getHeaderSearchInfo();
3537 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3539 assert(M &&
"Must have module Core");
3540 PP.makeModuleVisible(CoreModule, ImportLoc);
3546 llvm::cl::desc(
"Allow implicit build of system modules."),
3548static llvm::cl::list<std::string>
3551 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3554static llvm::cl::opt<std::string>
3556 llvm::cl::desc(
"<output dictionary file>"),
3576 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3588 using namespace clang::diag;
3594 std::string moduleName;
3595 const clang::Module *module =
nullptr;
3598 const auto &ID =
Info.getID();
3599 if (ID == remark_module_build || ID == remark_module_build_done) {
3600 moduleName =
Info.getArgStdStr(0);
3601 module = fMap.findModule(moduleName);
3607 "Couldn't find module %s in the available modulemaps. This"
3608 "prevents us from correctly diagnosing wrongly built modules.\n",
3609 moduleName.c_str());
3622 bool isByproductModule =
false;
3626 isByproductModule =
true;
3631 isByproductModule =
true;
3634 if (!isByproductModule)
3635 fChild->HandleDiagnostic(DiagLevel,
Info);
3637 if (ID == remark_module_build && !isByproductModule) {
3639 "Building module '%s' implicitly. If '%s' requires a \n"
3640 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3641 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3643 moduleName.c_str(), moduleName.c_str());
3651 DiagnosticConsumer::clear();
3654 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3656 fChild->BeginSourceFile(LangOpts, PP);
3657 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3662 fChild->EndSourceFile();
3663 DiagnosticConsumer::EndSourceFile();
3669 DiagnosticConsumer::finish();
3676#if defined(_WIN32) && defined(_MSC_VER)
3680 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3681 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3682 ::_set_error_mode(_OUT_TO_STDERR);
3683 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3684 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3685 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3686 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3687 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3688 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3693static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3695static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3706static llvm::cl::opt<VerboseLevel>
3708 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3709 clEnumVal(
v0,
"Show only fatal errors."),
3710 clEnumVal(
v1,
"Show errors (the same as -v)."),
3711 clEnumVal(
v2,
"Show warnings (default)."),
3712 clEnumVal(
v3,
"Show notes."),
3713 clEnumVal(
v4,
"Show information.")),
3717static llvm::cl::opt<bool>
3718gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3721static llvm::cl::opt<bool>
3722gOptReflex(
"reflex", llvm::cl::desc(
"Behave internally like genreflex."),
3724static llvm::cl::opt<bool>
3725gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3728static llvm::cl::opt<std::string>
3730 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3733static llvm::cl::opt<bool>
3735 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3738static llvm::cl::opt<bool>
3739gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3741static llvm::cl::opt<bool>
3742gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3744static llvm::cl::list<std::string>
3746 llvm::cl::desc(
"Generate rootmap file."),
3748static llvm::cl::opt<std::string>
3750 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3752static llvm::cl::opt<bool>
3754 llvm::cl::desc(
"Generate a C++ module."),
3756static llvm::cl::list<std::string>
3758 llvm::cl::desc(
"Specify a C++ modulemap file."),
3761static llvm::cl::opt<bool>
3763 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3765static llvm::cl::opt<bool>
3767 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3769static llvm::cl::opt<bool>
3771 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3773static llvm::cl::opt<bool>
3775 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3777static llvm::cl::opt<bool>
3779 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3780information and another the interactivity support."),
3782static llvm::cl::opt<bool>
3785 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3787static llvm::cl::opt<std::string>
3789 llvm::cl::desc(
"The path to the library of the built dictionary."),
3791static llvm::cl::list<std::string>
3793 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3795static llvm::cl::list<std::string>
3797 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3801static llvm::cl::opt<bool>
3803 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3811static llvm::cl::opt<bool>
3814 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3816static llvm::cl::opt<bool>
3818 llvm::cl::desc(
"Check the selection syntax only."),
3820static llvm::cl::opt<bool>
3822 llvm::cl::desc(
"Fail if there are warnings."),
3824static llvm::cl::opt<bool>
3826 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3828static llvm::cl::opt<std::string>
3830 llvm::cl::desc(
"Specify an isysroot."),
3832 llvm::cl::init(
"-"));
3833static llvm::cl::list<std::string>
3835 llvm::cl::desc(
"Specify an include path."),
3837static llvm::cl::list<std::string>
3839 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3841static llvm::cl::list<std::string>
3843 llvm::cl::desc(
"Specify a system include path."),
3845static llvm::cl::list<std::string>
3847 llvm::cl::desc(
"Specify defined macros."),
3849static llvm::cl::list<std::string>
3851 llvm::cl::desc(
"Specify undefined macros."),
3853static llvm::cl::list<std::string>
3855 llvm::cl::desc(
"Specify compiler diagnostics options."),
3858static llvm::cl::list<std::string>
3860 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file | selection xml file>"),
3862static llvm::cl::list<std::string>
3864 llvm::cl::desc(
"Consumes all unrecognized options."),
3867static llvm::cl::SubCommand
3870static llvm::cl::list<std::string>
3872 llvm::cl::desc(
"Consumes options and sends them to cling."),
3882 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3885 std::vector<clang::Module::Header> moduleHeaders;
3887 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3889 bool foundAllHeaders =
true;
3891 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3892 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3893 if (header == moduleHeader.NameAsWritten)
3901 for (
const std::string &header : modGen.
GetHeaders()) {
3902 if (isHeaderInModule(header))
3905 clang::ModuleMap::KnownHeader SuggestedModule;
3906 clang::ConstSearchDirIterator *CurDir =
nullptr;
3907 if (
auto FE = headerSearch.LookupFile(
3908 header, clang::SourceLocation(),
3911 clang::ArrayRef<std::pair<clang::OptionalFileEntryRef, clang::DirectoryEntryRef>>(),
3914 0, &SuggestedModule,
3921 if (
auto OtherModule = SuggestedModule.getModule()) {
3922 std::string OtherModuleName;
3923 auto TLM = OtherModule->getTopLevelModuleName();
3925 OtherModuleName = TLM.str();
3927 OtherModuleName = OtherModule->Name;
3934 missingHeaders.push_back({header, OtherModuleName});
3937 missingHeaders.push_back({header, {}});
3939 foundAllHeaders =
false;
3941 return foundAllHeaders;
3947 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3949 clang::CompilerInstance *CI = interpreter.getCI();
3950 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3951 headerSearch.loadTopLevelSystemModules();
3954 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3959 moduleName.c_str());
3966 std::vector<std::array<std::string, 2>> missingHdrMod;
3969 std::stringstream msgStream;
3970 msgStream <<
"after creating module \"" << module->Name <<
"\" ";
3971 if (!module->PresumedModuleMapFile.empty())
3972 msgStream <<
"using modulemap \"" << module->PresumedModuleMapFile <<
"\" ";
3973 msgStream <<
"the following headers are not part of that module:\n";
3974 for (
auto &
H : missingHdrMod) {
3975 msgStream <<
" " <<
H[0];
3977 msgStream <<
" (already part of module \"" <<
H[1] <<
"\")";
3980 std::string warningMessage = msgStream.str();
3982 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3993 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3994 warningMessage.c_str(),
4001 std::vector<std::string> missingHeaders;
4002 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
4003 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
4006 module->Name.c_str());
4016 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
4017 moduleName.consume_front(
"lib");
4018 moduleName.consume_back(
".pcm");
4019 moduleName.consume_back(
"_rdict");
4027 bool isGenreflex =
false)
4038 const char *executableFileName = argv[0];
4040 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
4041 llvm::PrettyStackTraceProgram
X(argc, argv);
4044#if defined(R__WIN32) && !defined(R__WINGCC)
4049 for (
int iic = 1 ; iic < argc; ++iic) {
4050 std::string iiarg(argv[iic]);
4052 size_t len = iiarg.length();
4054 char *argviic =
new char[
len + 1];
4055 strlcpy(argviic, iiarg.c_str(),
len + 1);
4056 argv[iic] = argviic;
4065 auto &opts = llvm::cl::getRegisteredOptions();
4066 llvm::cl::Option* optHelp = opts[
"help"];
4067 llvm::cl::alias optHelpAlias1(
"h",
4068 llvm::cl::desc(
"Alias for -help"),
4069 llvm::cl::aliasopt(*optHelp));
4070 llvm::cl::alias optHelpAlias2(
"?",
4071 llvm::cl::desc(
"Alias for -help"),
4072 llvm::cl::aliasopt(*optHelp));
4074 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
4078 std::vector<const char *> clingArgsC;
4079 clingArgsC.push_back(executableFileName);
4081 clingArgsC.push_back(
"-I");
4088 clingArgsC.push_back(Opt.c_str());
4090 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
4092 llvmResourceDir.c_str());
4095 return interp->getDiagnostics().hasFatalErrorOccurred();
4098 std::string dictname;
4112 llvm::cl::PrintHelpMessage();
4127 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
4128 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4155 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4156 llvm::cl::PrintHelpMessage();
4160 std::vector<std::string> clingArgs;
4161 clingArgs.push_back(executableFileName);
4162 clingArgs.push_back(
"-iquote.");
4168 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4174 if (GetErrorIgnoreLevel() >
kWarning)
4176 GetWarningsAreErrors() =
true;
4190 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4195 clingArgs.push_back(std::string(
"-D") + PPDefine);
4198 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4201 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4208 clingArgs.push_back(
"-isystem");
4209 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4213 for (
const std::string &WDiag :
gOptWDiags) {
4214 const std::string FullWDiag = std::string(
"-W") + WDiag;
4218 clingArgs.push_back(FullWDiag);
4222 clingArgs.push_back(std::string(
"-I") + includeDir);
4224 std::vector<std::string> pcmArgs;
4225 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4226 auto thisArg = clingArgs[parg];
4228 if (thisArg ==
"-c" ||
4234 while (
c ==
' ')
c = thisArg[++
offset];
4238 [&](
const std::string& path){
4239 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4240 if (excludePathsEnd != excludePathPos)
continue;
4242 pcmArgs.push_back(thisArg);
4249 clingArgs.push_back(
"-D__ROOTCLING__");
4252 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4253#elif defined(R__WIN32)
4254 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4257 clingArgs.push_back(
"-D_XKEYCHECK_H");
4259 clingArgs.push_back(
"-DNOMINMAX");
4261 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4264 clingArgs.push_back(
"-fsyntax-only");
4266 clingArgs.push_back(
"-fPIC");
4268 clingArgs.push_back(
"-Xclang");
4269 clingArgs.push_back(
"-fmodules-embed-all-files");
4270 clingArgs.push_back(
"-Xclang");
4271 clingArgs.push_back(
"-main-file-name");
4272 clingArgs.push_back(
"-Xclang");
4273 clingArgs.push_back((dictname +
".h").c_str());
4281 std::string outputFile;
4283 llvm::StringRef moduleName;
4288 auto clingArgsInterpreter = clingArgs;
4297 clingArgsInterpreter.push_back(
"-fmodules");
4298 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4301 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4303 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4307 if (llvm::sys::fs::exists(ModuleMapCWD))
4308 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4316 clingArgsInterpreter.push_back(
"-Xclang");
4317 clingArgsInterpreter.push_back(
"-fmodule-feature");
4318 clingArgsInterpreter.push_back(
"-Xclang");
4321 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4331 if (moduleName ==
"Core") {
4333 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4334 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4335 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4336 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4338 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4339 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4343 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4345 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4347 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4348 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4349 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4350 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4351 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4352 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4353 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4354 }
else if (moduleName ==
"MathCore") {
4355 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4360 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4364 clingArgsInterpreter.push_back(
"-v");
4367 std::vector<const char *> clingArgsC;
4368 for (
auto const &clingArg : clingArgsInterpreter) {
4370 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4371 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4374 clingArgsC.push_back(clingArg.c_str());
4378 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4379 cling::Interpreter* interpPtr =
nullptr;
4381 std::list<std::string> filesIncludedByLinkdef;
4385 clingArgsC.push_back(
"-ffast-math");
4388 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4389 llvmResourceDir.c_str()));
4390 interpPtr = owningInterpPtr.get();
4393 clingArgsC.push_back(
"-resource-dir");
4394 clingArgsC.push_back(llvmResourceDir.c_str());
4395 clingArgsC.push_back(
nullptr);
4397 extraArgs = &clingArgsC[1];
4399 if (!interpPtr->getCI())
4402 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4403 interpPtr->setCallbacks(std::move(callBacks));
4406 cling::Interpreter &interp = *interpPtr;
4407 clang::CompilerInstance *CI = interp.getCI();
4409 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4410 CI->getSourceManager().setAllFilesAreTransient(
true);
4412 clang::Preprocessor &PP = CI->getPreprocessor();
4413 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4414 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4415 auto &diags = interp.getDiagnostics();
4422 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4427 diags.setClient(recordingClient,
true);
4433 interp.DumpIncludePath();
4438 interp.printIncludedFiles(llvm::outs());
4439 llvm::outs() <<
"\n\n";
4440 llvm::outs().flush();
4443 const clang::LangOptions& LangOpts
4444 = interp.getCI()->getASTContext().getLangOpts();
4445#define LANGOPT(Name, Bits, Default, Description) \
4446 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4447#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4448#include "clang/Basic/LangOptions.def"
4452 interp.getOptions().ErrorOut =
true;
4453 interp.enableRawInput(
true);
4457 if (DepMod.endswith(
"_rdict.pcm")) {
4464 cling::Interpreter::PushTransactionRAII RAII(&interp);
4465 if (!interp.loadModule(DepMod.str(),
false)) {
4474 if (interp.declare(
"#include <assert.h>\n"
4475 "#include \"Rtypes.h\"\n"
4476 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4484 if (interp.declare(
"#include <string>\n"
4485 "#include <RtypesCore.h>\n"
4486 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4497 clingArgs.push_back(
"-D__CINT__");
4498 clingArgs.push_back(
"-D__MAKECINT__");
4504 std::string interpPragmaSource;
4505 std::string includeForSource;
4506 std::string interpreterDeclarations;
4507 std::string linkdef;
4513 if (isSelectionFile) {
4515 linkdef = optHeaderFileName;
4518 executableFileName, optHeaderFileName.c_str());
4524 std::string fullheader(optHeaderFileName);
4527 if (fullheader[fullheader.length() - 1] ==
'+') {
4528 fullheader.erase(fullheader.length() - 1);
4533 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4534 if (!isSelectionFile) {
4542 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4543 pcmArgs.push_back(header);
4545 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4550 bool hasSelectionFile = !linkdef.empty();
4551 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4562 if (!newName.empty())
4575 string incCurDir =
"-I";
4576 incCurDir += currentDirectory;
4577 pcmArgs.push_back(incCurDir);
4582 std::stringstream res;
4583 const char* delim=
"\n";
4584 std::copy(diagnosticPragmas.begin(),
4585 diagnosticPragmas.end(),
4586 std::ostream_iterator<std::string>(res, delim));
4587 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4593 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4595 IgnoringPragmaHandler(
const char* pragma):
4596 clang::PragmaNamespace(pragma) {}
4597 void HandlePragma(clang::Preprocessor &PP,
4598 clang::PragmaIntroducer Introducer,
4599 clang::Token &tok)
override {
4600 PP.DiscardUntilEndOfDirective();
4606 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4607 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4608 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4609 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4611 if (!interpreterDeclarations.empty() &&
4612 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4624 pcmArgs.push_back(linkdef);
4632 interp.AddIncludePath(inclPath);
4634 std::stringstream definesUndefinesStr;
4637 if (!definesUndefinesStr.str().empty()) {
4638 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4639 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4650 if (linkdef.empty()) {
4656 std::ofstream fileout;
4658 std::ostream *splitDictStream =
nullptr;
4659 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4681 splitDeleter.reset(splitDictStream);
4683 splitDictStream = &dictStream;
4686 size_t dh = main_dictname.rfind(
'.');
4687 if (dh != std::string::npos) {
4688 main_dictname.erase(dh);
4691 std::string main_dictname_copy(main_dictname);
4713 string linkdefFilename;
4714 if (linkdef.empty()) {
4715 linkdefFilename =
"in memory";
4717 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4725 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4731 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4733 std::string extraIncludes;
4738 const unsigned int selRulesInitialSize = selectionRules.
Size();
4742 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4746 int rootclingRetCode(0);
4750 std::ifstream file(linkdefFilename.c_str());
4751 if (file.is_open()) {
4764 clingArgs.push_back(
"-Ietc/cling/cint");
4766 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4767 llvmResourceDir.c_str())) {
4769 rootclingRetCode += 1;
4779 }
else if (isSelXML) {
4783 std::ifstream file(linkdefFilename.c_str());
4784 if (file.is_open()) {
4788 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4824 dictStream <<
"#include \"TBuffer.h\"\n"
4825 <<
"#include \"TVirtualObject.h\"\n"
4826 <<
"#include <vector>\n"
4827 <<
"#include \"TSchemaHelper.h\"\n\n";
4829 std::list<std::string> includes;
4831 for (
auto & incFile : includes) {
4832 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4834 dictStream << std::endl;
4839 int scannerVerbLevel = 0;
4842 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4844 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4867 scan.
Scan(CI->getASTContext());
4869 bool has_input_error =
false;
4876 !dictSelRulesPresent &&
4883 if (rootclingRetCode)
return rootclingRetCode;
4890 if (annRcd.RequestNoInputOperator()) {
4902 if (has_input_error) {
4912 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4913 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4941 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4942 constructorTypes.emplace_back(
"__void__", interp);
4943 constructorTypes.emplace_back(
"", interp);
4974 if (rootclingRetCode != 0) {
4975 return rootclingRetCode;
4994 std::string detectedUmbrella;
4995 for (
auto & arg : pcmArgs) {
4997 detectedUmbrella = arg;
5003 headersDeclsMap.clear();
5007 std::string headersClassesMapString =
"\"\"";
5008 std::string fwdDeclsString =
"\"\"";
5024 if (modGen.
IsPCH()) {
5027 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
5037 ofstream outputfile(liblist_filename.c_str(), ios::out);
5040 executableFileName, liblist_filename.c_str());
5042 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
5043 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
5045 outputfile <<
"# Now the list of classes\n";
5050 outputfile << annRcd.GetNormalizedName() << endl;
5057 if (0 != rootclingRetCode)
return rootclingRetCode;
5063 [](
const std::string &
a,
const std::string &
b) -> std::string {
5064 if (a.empty()) return b;
5065 else return a +
" " + b;
5070 std::list<std::string> classesNames;
5071 std::list<std::string> classesNamesForRootmap;
5072 std::list<std::string> classesDefsList;
5076 classesNamesForRootmap,
5080 std::list<std::string> enumNames;
5085 std::list<std::string> varNames;
5090 if (0 != rootclingRetCode)
return rootclingRetCode;
5093 if (rootMapNeeded) {
5095 std::list<std::string> nsNames;
5104 rootmapLibName.c_str());
5107 std::unordered_set<std::string> headersToIgnore;
5110 headersToIgnore.insert(optHeaderFileName.c_str());
5112 std::list<std::string> typedefsRootmapLines;
5120 classesNamesForRootmap,
5122 typedefsRootmapLines,
5128 if (0 != rootclingRetCode)
return 1;
5138 cling::Interpreter::PushTransactionRAII RAII(&interp);
5139 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5150 if(rootclingRetCode == 0) {
5151 rootclingRetCode += tmpCatalog.
commit();
5156 return rootclingRetCode;
5167 unsigned int numberOfHeaders = 0;
5168 for (std::vector<std::string>::iterator it = headersNames.begin();
5169 it != headersNames.end(); ++it) {
5170 const std::string headername(*it);
5175 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5176 headername.c_str());
5179 return numberOfHeaders;
5185 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5188 unsigned int argvCounter = 0;
5189 for (
int i = 1; i < argc; ++i) {
5192 args.push_back(argv[i]);
5194 }
else if (argvCounter) {
5195 argv[i - argvCounter] = argv[i];
5202 std::cout <<
"Args: \n";
5203 for (std::vector<std::string>::iterator it = args.begin();
5204 it < args.end(); ++it) {
5205 std::cout << i <<
") " << *it << std::endl;
5219 if (std::string::npos !=
result) {
5231 const unsigned int size(str.size());
5232 char *
a =
new char[
size + 1];
5234 memcpy(
a, str.c_str(),
size);
5250 std::vector<std::string> &ofilesnames)
5252 ofilesnames.reserve(headersNames.size());
5254 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5255 it != headersNames.end(); ++it) {
5256 std::string ofilename(*it);
5258 ofilesnames.push_back(ofilename);
5265 const std::vector<std::string> &argsToBeAdded,
5266 const std::string &optName =
"")
5268 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5269 it != argsToBeAdded.end(); ++it) {
5277 const std::vector<std::string> &argsToBeAdded,
5278 const std::string &optName =
"")
5280 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5281 it != argsToBeAdded.end(); ++it) {
5282 if (optName.length()) {
5292 const std::string &selectionFileName,
5293 const std::string &targetLibName,
5295 const std::vector<std::string> &pcmsNames,
5296 const std::vector<std::string> &includes,
5297 const std::vector<std::string> &preprocDefines,
5298 const std::vector<std::string> &preprocUndefines,
5299 const std::vector<std::string> &warnings,
5300 const std::string &rootmapFileName,
5301 const std::string &rootmapLibName,
5302 bool interpreteronly,
5305 bool writeEmptyRootPCM,
5307 bool noIncludePaths,
5308 bool noGlobalUsingStd,
5309 const std::vector<std::string> &headersNames,
5310 bool failOnWarnings,
5311 bool printRootclingInvocation,
5312 const std::string &ofilename)
5316 std::vector<char *> argvVector;
5327 std::string dictLocation;
5333 std::string newRootmapLibName(rootmapLibName);
5334 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5335 if (headersNames.size() != 1) {
5337 "*** genreflex: No rootmap lib and several header specified!\n");
5340 newRootmapLibName =
"lib";
5341 newRootmapLibName += cleanHeaderName;
5347 std::string newRootmapFileName(rootmapFileName);
5348 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5349 newRootmapFileName = dictLocation + newRootmapFileName;
5354 if (!newRootmapFileName.empty()) {
5360 if (!newRootmapLibName.empty()) {
5370 if (interpreteronly)
5378 if (!targetLibName.empty()) {
5388 if (noGlobalUsingStd)
5398 if (writeEmptyRootPCM)
5421 if (!selectionFileName.empty()) {
5425 const int argc = argvVector.size();
5430 for (
int i = 0; i < argc; i++) {
5431 cmd += argvVector[i];
5436 std::cout << cmd << std::endl;
5437 if (printRootclingInvocation)
return 0;
5440 char **argv = & (argvVector[0]);
5445 for (
int i = 0; i < argc; i++)
5446 delete [] argvVector[i];
5448 return rootclingReturnCode;
5457 const std::string &selectionFileName,
5458 const std::string &targetLibName,
5460 const std::vector<std::string> &pcmsNames,
5461 const std::vector<std::string> &includes,
5462 const std::vector<std::string> &preprocDefines,
5463 const std::vector<std::string> &preprocUndefines,
5464 const std::vector<std::string> &warnings,
5465 const std::string &rootmapFileName,
5466 const std::string &rootmapLibName,
5467 bool interpreteronly,
5470 bool writeEmptyRootPCM,
5472 bool noIncludePaths,
5473 bool noGlobalUsingStd,
5474 const std::vector<std::string> &headersNames,
5475 bool failOnWarnings,
5476 bool printRootclingInvocation,
5477 const std::string &outputDirName_const =
"")
5479 std::string outputDirName(outputDirName_const);
5481 std::vector<std::string> ofilesNames;
5488 std::vector<std::string> namesSingleton(1);
5489 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5490 namesSingleton[0] = headersNames[i];
5491 std::string ofilenameFullPath(ofilesNames[i]);
5492 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5493 ofilenameFullPath = outputDirName + ofilenameFullPath;
5514 printRootclingInvocation,
5516 if (returnCode != 0)