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));
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,
"!"));
316 userDefinedProperty =
name + propNames::separator +
value;
319 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty));
330 cling::Interpreter &interpreter,
338 using namespace clang;
339 SourceLocation commentSLoc;
340 llvm::StringRef comment;
342 ASTContext &C = CXXRD.getASTContext();
345 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
346 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
347 if (declSelRulePair == declSelRulesMap.end()){
348 const std::string thisClassName(CXXRD.getName());
349 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
354 if (thisClassBaseSelectionRule) {
357 BaseSelectionRule::AttributesMap_t::iterator iter;
358 std::string userDefinedProperty;
360 const std::string &
name =
attr.first;
365 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty));
372 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
373 E = CXXRD.decls_end();
I != E; ++
I) {
377 if (!(*I)->isImplicit()
378 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
382 if (isClassDefMacro) {
383 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
389 if (comment.size()) {
391 if (isClassDefMacro) {
392 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str()));
393 }
else if (!isGenreflex) {
399 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str()));
404 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
408 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
422 llvm::APInt
len = arrayType->getSize();
423 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
424 len *= subArrayType->getSize();
425 arrayType = subArrayType;
427 return len.getLimitedValue();
433 const cling::Interpreter &interp)
435 static const clang::CXXRecordDecl *TObject_decl
438 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
445 const cling::Interpreter &interp)
447 static const clang::CXXRecordDecl *TObject_decl
460 return (0 == strcasecmp(
filename + (
len - xmllen),
".xml"));
486 if (exepath && *exepath) {
488 char *ep =
new char[PATH_MAX];
489 if (!realpath(exepath, ep)) {
490 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
491 strlcpy(ep, exepath, PATH_MAX);
494 int nche = strlen(exepath) + 1;
495 char *ep =
new char[nche];
496 strlcpy(ep, exepath, nche);
500 if ((s = strrchr(ep,
'/'))) {
502 int removesubdirs = 2;
503 if (!strncmp(s + 1,
"rootcling_stage1.exe", 20)) {
507 }
else if (!strncmp(s + 1,
"rootcling_stage1", 16)) {
512 for (
int i = 1; s && i < removesubdirs; ++i) {
514 s = strrchr(ep,
'/');
528 int ncha = strlen(ep) + 10;
529 char *env =
new char[ncha];
530 snprintf(env, ncha,
"ROOTSYS=%s", ep);
551 const char *expectedTokens[],
552 size_t *end =
nullptr)
555 if (
line[0] !=
'#')
return false;
557 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
558 while (isspace(
line[pos])) ++pos;
559 size_t lenToken = strlen(*iToken);
560 if (
line.compare(pos, lenToken, *iToken)) {
579 if (recordDecl->hasOwningModule()) {
580 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
583 std::string qual_name;
589 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
598 if (classname.find(
':') == std::string::npos)
return;
601 int slen = classname.size();
602 for (
int k = 0; k < slen; ++k) {
603 if (classname[k] ==
':') {
604 if (k + 1 >= slen || classname[k + 1] !=
':') {
609 string base = classname.substr(0, k);
614 autoloads[base] =
"";
618 }
else if (classname[k] ==
'<') {
630 std::string classname;
632 while (file >>
line) {
634 if (
line.find(
"Library.") != 0)
continue;
636 int pos =
line.find(
":", 8);
637 classname =
line.substr(8, pos - 8);
642 getline(file,
line,
'\n');
643 while (
line[0] ==
' ')
line.replace(0, 1,
"");
647 if (classname ==
"ROOT::TImpProxy") {
651 autoloads[classname] =
line;
666 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
668 while (getline(file,
line,
'\n')) {
669 if (
line ==
"{ decls }") {
670 while (getline(file,
line,
'\n')) {
671 if (
line[0] ==
'[')
break;
674 const char firstChar =
line[0];
675 if (firstChar ==
'[') {
677 libs =
line.substr(1,
line.find(
']') - 1);
678 while (libs[0] ==
' ') libs.replace(0, 1,
"");
679 }
else if (0 != keyLenMap.count(firstChar)) {
680 unsigned int keyLen = keyLenMap.at(firstChar);
681 keyname =
line.substr(keyLen,
line.length() - keyLen);
683 autoloads[keyname] = libs;
693void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
695 std::ifstream filelist(fileListName.c_str());
702 if (llvm::sys::fs::is_directory(
filename))
continue;
708 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
710 file.seekg(0, std::ios::beg);
731 const string &fullname,
732 const clang::RecordDecl *cl,
733 cling::Interpreter &interp)
736 const clang::FunctionDecl *method
741 clang::TranslationUnitDecl *TU =
742 cl->getASTContext().getTranslationUnitDecl();
746 bool has_input_error =
false;
747 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
749 if (strstr(
filename.c_str(),
"TBuffer.h") !=
nullptr ||
750 strstr(
filename.c_str(),
"Rtypes.h") !=
nullptr) {
752 has_input_error =
true;
755 has_input_error =
true;
757 if (has_input_error) {
759 const char *maybeconst =
"";
760 const char *mayberef =
"&";
761 if (
what[strlen(
what) - 1] ==
'<') {
762 maybeconst =
"const ";
766 "in this version of ROOT, the option '!' used in a linkdef file\n"
767 " implies the actual existence of customized operators.\n"
768 " The following declaration is now required:\n"
769 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
771 return has_input_error;
783 int ncha = fullname.length() + 13;
784 char *
proto =
new char[ncha];
796 return has_input_error;
802bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
808 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
812 bool isAbstract = clxx->isAbstract();
815 std::string qualName;
817 const char *qualName_c = qualName.c_str();
819 "because it inherits from TObject but does not "
820 "have its own ClassDef.\n",
833 if (
m.getType().isConstQualified()) {
834 string ret =
"const_cast< ";
837 if (type_name.substr(0,6)==
"const ") {
838 ret += type_name.c_str()+6;
844 ret +=
m.getName().str();
848 return prefix +
m.getName().str();
858 const cling::Interpreter &interp,
860 std::ostream &dictStream)
863 std::string mTypename;
876 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
878 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
879 if (!tmplt_specialization)
return 0;
885 string fulName1, fulName2;
886 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
887 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
888 clang::QualType ti = arg0.getAsType();
892 fulName1 = ti.getAsString();
895 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
896 clang::QualType tmplti = arg1.getAsType();
899 fulName2 = tmplti.getAsString();
906 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
912 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
916 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
918 }
else if (
m.getType()->isPointerType()) {
923 dictStream <<
" {" << std::endl;
925 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
930 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
933 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
936 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
937 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
938 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
941 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
942 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
943 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
947 dictStream <<
" R__stl.clear();" << std::endl;
950 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
951 <<
" if (R__tcl1==0) {" << std::endl
952 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
953 << fulName1.c_str() <<
"!\");" << std::endl
954 <<
" return;" << std::endl
955 <<
" }" << std::endl;
958 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
959 <<
" if (R__tcl2==0) {" << std::endl
960 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
961 << fulName2.c_str() <<
"!\");" << std::endl
962 <<
" return;" << std::endl
963 <<
" }" << std::endl;
966 dictStream <<
" int R__i, R__n;" << std::endl
967 <<
" R__b >> R__n;" << std::endl;
970 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
972 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
976 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
996 std::string keyName(ti.getAsString());
997 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
998 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
999 <<
" R__stl.insert(R__t3);" << std::endl;
1007 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1012 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1015 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1020 dictStream <<
" }" << std::endl
1021 <<
" }" << std::endl;
1022 if (isArr) dictStream <<
" }" << std::endl;
1028 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
1030 dictStream <<
" {" << std::endl;
1033 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1036 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1039 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1042 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1046 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1047 <<
" R__b << R__n;" << std::endl
1048 <<
" if(R__n) {" << std::endl;
1051 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1052 <<
" if (R__tcl1==0) {" << std::endl
1053 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1054 << fulName1.c_str() <<
"!\");" << std::endl
1055 <<
" return;" << std::endl
1056 <<
" }" << std::endl;
1059 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1060 <<
" if (R__tcl2==0) {" << std::endl
1061 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1062 <<
" return;" << std::endl
1063 <<
" }" << std::endl;
1066 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1067 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1069 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1070 clang::QualType tmplti = arg1.getAsType();
1077 dictStream <<
" }" << std::endl
1078 <<
" }" << std::endl
1079 <<
" }" << std::endl;
1080 if (isArr) dictStream <<
" }" << std::endl;
1092 std::string mTypenameStr;
1096 if (!strcmp(mTypeName,
"string")) {
1098 std::string fieldname =
m.getName().str();
1101 if (
m.getType()->isConstantArrayType()) {
1102 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1103 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1105 std::stringstream fullIdx;
1106 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1109 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1110 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1111 fullIdx <<
"[R__i" << dim <<
"]";
1112 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1115 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1116 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1119 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1120 if (
m.getType()->isPointerType())
1121 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1122 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1124 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1128 if (
m.getType()->isPointerType())
1129 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1130 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1131 else if (
m.getType()->isConstantArrayType()) {
1132 std::stringstream fullIdx;
1133 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1136 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1137 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1138 fullIdx <<
"[R__i" << dim <<
"]";
1139 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1142 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1144 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1155 if (
m.getType()->isPointerType()) {
1156 if (
m.getType()->getPointeeType()->isPointerType()) {
1168 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1170 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1172 dictStream <<
"[0]";
1173 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1188 int enclSpaceNesting = 0;
1195 dictStream <<
"#include \"TInterpreter.h\"\n";
1197 dictStream <<
"//_______________________________________"
1198 <<
"_______________________________________" << std::endl;
1199 if (add_template_keyword) dictStream <<
"template <> ";
1200 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1203 <<
"//_______________________________________"
1204 <<
"_______________________________________" << std::endl;
1205 if (add_template_keyword) dictStream <<
"template <> ";
1206 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1207 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1209 dictStream <<
"//_______________________________________"
1210 <<
"_______________________________________" << std::endl;
1211 if (add_template_keyword) dictStream <<
"template <> ";
1212 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1213 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1214 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1216 <<
"//_______________________________________"
1217 <<
"_______________________________________" << std::endl;
1218 if (add_template_keyword) dictStream <<
"template <> ";
1219 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1220 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1221 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1223 <<
"//_______________________________________"
1224 <<
"_______________________________________" << std::endl;
1225 if (add_template_keyword) dictStream <<
"template <> ";
1226 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1230 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1231 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1232 <<
"*)nullptr)->GetClass();" << std::endl
1233 <<
" return fgIsA;\n"
1234 <<
"}" << std::endl << std::endl
1236 <<
"//_______________________________________"
1237 <<
"_______________________________________" << std::endl;
1238 if (add_template_keyword) dictStream <<
"template <> ";
1239 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1241 dictStream <<
" Dictionary();\n";
1243 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1244 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1246 dictStream <<
" return fgIsA;" << std::endl
1247 <<
"}" << std::endl << std::endl;
1249 while (enclSpaceNesting) {
1250 dictStream <<
"} // namespace " << nsname << std::endl;
1259 cling::Interpreter &interp,
1260 std::ostream &dictStream)
1262 if (cl->isAnonymousNamespace()) {
1274 if (classname !=
"ROOT") {
1278 dictStream <<
" namespace ROOTDict {" << std::endl;
1281 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1285 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1286 dictStream << std::endl
1288 <<
" // Function generating the singleton type initializer" << std::endl
1291 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1292 <<
" {" << std::endl
1294 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1295 <<
" {" << std::endl
1298 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1300 <<
" instance(\"" << classname.c_str() <<
"\", ";
1303 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1305 dictStream <<
"0 /*version*/, ";
1309 for (
unsigned int i = 0; i <
filename.length(); i++) {
1313 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1317 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1319 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1322 dictStream << 0 <<
");" << std::endl
1324 <<
" return &instance;" << std::endl
1325 <<
" }" << std::endl
1326 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1327 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1328 <<
" // Static variable to force the class initialization" << std::endl
1330 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1331 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1334 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1335 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1336 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1337 <<
" }" << std::endl << std::endl;
1340 dictStream <<
" }" << std::endl;
1342 dictStream <<
"}" << std::endl;
1344 dictStream << std::endl;
1353llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1356 llvm::StringRef where;
1359 if (
index.size() == 0 && printError) {
1360 const char *errorstring;
1363 errorstring =
"is not an integer";
1366 errorstring =
"has not been defined before the array";
1369 errorstring =
"is a private member of a parent class";
1372 errorstring =
"is not known";
1375 errorstring =
"UNKNOWN ERROR!!!!";
1378 if (where.size() == 0) {
1380 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1383 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1392 const cling::Interpreter &interp,
1394 std::ostream &dictStream)
1396 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1397 if (clxx ==
nullptr)
return;
1404 int enclSpaceNesting = 0;
1410 dictStream <<
"//_______________________________________"
1411 <<
"_______________________________________" << std::endl;
1412 if (add_template_keyword) dictStream <<
"template <> ";
1413 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1414 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1422 int basestreamer = 0;
1423 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1427 string base_fullname;
1430 if (strstr(base_fullname.c_str(),
"::")) {
1432 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1433 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1434 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1436 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1441 if (!basestreamer) {
1442 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1443 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1445 dictStream <<
"}" << std::endl << std::endl;
1446 while (enclSpaceNesting) {
1447 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1454 string classname = fullname;
1455 if (strstr(fullname.c_str(),
"::")) {
1457 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1458 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1459 classname =
"thisClass";
1461 for (
int i = 0; i < 2; i++) {
1466 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1467 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1468 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1470 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1471 dictStream <<
" } else {" << std::endl;
1472 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1477 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1481 string base_fullname;
1484 if (strstr(base_fullname.c_str(),
"::")) {
1486 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1487 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1488 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1491 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1497 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1502 clang::QualType
type = field_iter->getType();
1503 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1513 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1517 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1520 if (strncmp(comment,
"!", 1)) {
1523 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1524 if (
type.getTypePtr()->isConstantArrayType() &&
1525 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1526 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1530 dictStream <<
" int R__i;" << std::endl;
1533 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1535 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());
1536 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1538 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1540 }
else if (
type.getTypePtr()->isPointerType()) {
1541 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1542 if (indexvar.size() == 0) {
1544 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1545 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1547 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1551 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1556 <<
"," << indexvar.str() <<
");" << std::endl;
1557 }
else if (isDouble32) {
1559 <<
"," << indexvar.str() <<
");" << std::endl;
1562 <<
"," << indexvar.str() <<
");" << std::endl;
1566 dictStream <<
" R__b.WriteFastArrayFloat16("
1567 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1568 }
else if (isDouble32) {
1569 dictStream <<
" R__b.WriteFastArrayDouble32("
1570 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1572 dictStream <<
" R__b.WriteFastArray("
1573 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1577 }
else if (
type.getTypePtr()->isArrayType()) {
1579 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1580 if (underling_type->isEnumeralType())
1581 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1585 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1586 }
else if (isDouble32) {
1588 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1591 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1595 if (underling_type->isEnumeralType()) {
1596 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1599 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1600 }
else if (isDouble32) {
1601 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1604 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1609 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1612 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1613 if (underling_type->isEnumeralType())
1614 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1615 << s <<
");" << std::endl;
1616 else if (isFloat16) {
1618 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1619 }
else if (isDouble32) {
1621 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1624 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1627 if (underling_type->isEnumeralType())
1628 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1629 else if (isFloat16) {
1630 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1631 }
else if (isDouble32) {
1632 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1634 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1638 }
else if (underling_type->isEnumeralType()) {
1640 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1641 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1643 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1648 <<
"=Float16_t(R_Dummy);}" << std::endl;
1651 }
else if (isDouble32) {
1654 <<
"=Double32_t(R_Dummy);}" << std::endl;
1676 if (
type.getTypePtr()->isConstantArrayType() &&
1677 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1678 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1682 dictStream <<
" int R__i;" << std::endl;
1685 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1690 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1695 dictStream <<
"[R__i];" << std::endl;
1696 }
else if (
type.getTypePtr()->isPointerType()) {
1704 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1705 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1707 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1711 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1725 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1731 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1735 dictStream <<
" int R__i;" << std::endl;
1738 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1739 std::string mTypeNameStr;
1741 const char *mTypeName = mTypeNameStr.c_str();
1742 const char *constwd =
"const ";
1743 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1744 mTypeName += strlen(constwd);
1745 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1747 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1751 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1757 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1758 << field_iter->getName().str() <<
"));" << std::endl;
1769 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1770 <<
" }" << std::endl
1771 <<
"}" << std::endl << std::endl;
1773 while (enclSpaceNesting) {
1774 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1782 const cling::Interpreter &interp,
1784 std::ostream &dictStream)
1788 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1789 if (clxx ==
nullptr)
return;
1794 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1806 int enclSpaceNesting = 0;
1812 dictStream <<
"//_______________________________________"
1813 <<
"_______________________________________" << std::endl;
1814 if (add_template_keyword) dictStream <<
"template <> ";
1815 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1817 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1818 <<
" if (R__b.IsReading()) {" << std::endl
1819 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1820 <<
" } else {" << std::endl
1821 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1822 <<
" }" << std::endl
1823 <<
"}" << std::endl << std::endl;
1825 while (enclSpaceNesting) {
1826 dictStream <<
"} // namespace " << nsname << std::endl;
1834 const cling::Interpreter &interp,
1836 std::ostream &dictStream,
1837 bool isAutoStreamer)
1839 if (isAutoStreamer) {
1849 std::string &code_for_parser)
1851 code_for_parser +=
"#ifdef __CINT__\n\n";
1852 code_for_parser +=
"#pragma link off all globals;\n";
1853 code_for_parser +=
"#pragma link off all classes;\n";
1854 code_for_parser +=
"#pragma link off all functions;\n\n";
1856 for (std::string& arg : InputFiles) {
1858 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1859 for (
int j = 0; j < 3; j++) {
1860 if (arg[
l] ==
'-') {
1865 if (arg[
l] ==
'!') {
1870 if (arg[
l] ==
'+') {
1876 if (nostr || noinp) {
1878 if (nostr) strlcat(trail,
"-", 3);
1879 if (noinp) strlcat(trail,
"!", 3);
1882 strlcpy(trail,
"+", 3);
1886 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1887 llvm::sys::path::replace_extension(filestem,
"");
1889 code_for_parser +=
"#pragma link C++ class ";
1890 code_for_parser += filestem.str().str();
1891 if (nostr || noinp || bcnt)
1892 code_for_parser += trail;
1893 code_for_parser +=
";\n";
1896 code_for_parser +=
"\n#endif\n";
1904bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1909 static const char *fopenopts =
"rb";
1911 static const char *fopenopts =
"r";
1915 fp = fopen(pname.c_str(), fopenopts);
1921 llvm::SmallVector<std::string, 10> includePaths;
1923 interp.GetIncludePaths(includePaths,
false,
false);
1925 const size_t nPaths = includePaths.size();
1926 for (
size_t i = 0; i < nPaths; i += 1 ) {
1930 fp = fopen(pname.c_str(), fopenopts);
1952 const char *inc = strstr(original,
"\\inc\\");
1954 inc = strstr(original,
"/inc/");
1955 if (inc && strlen(inc) > 5)
1975 cling::Interpreter &interp,
1978 std::ostringstream out;
1983 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1984 const std::string &hdrName
2002static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
2003 llvm::StringRef iSysRoot,
2004 clang::Module *module =
nullptr)
2007 llvm::SmallVector<char, 128> buffer;
2008 llvm::BitstreamWriter stream(buffer);
2009 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
2010 std::unique_ptr<llvm::raw_ostream> out =
2011 compilerInstance->createOutputFile(fileName,
true,
2020 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2022 writer.WriteAST(compilerInstance->getSema(), fileName.str(), module, iSysRoot);
2025 out->write(&buffer.front(), buffer.size());
2037 const std::string ¤tDirectory)
2039 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2041 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2049static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2052 if (headers.empty())
2056 std::stringstream includes;
2057 for (
const std::string &header : headers) {
2058 includes <<
"#include \"" << header <<
"\"\n";
2060 std::string includeListStr = includes.str();
2061 auto result = interpreter.declare(includeListStr);
2062 return result == cling::Interpreter::CompilationResult::kSuccess;
2070 char platformDefines[64] = {0};
2071#ifdef __INTEL_COMPILER
2072 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2073 clingArgs.push_back(platformDefines);
2076 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2077 clingArgs.push_back(platformDefines);
2080 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2081 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2082 clingArgs.push_back(platformDefines);
2084#ifdef __GNUC_MINOR__
2085 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2086 clingArgs.push_back(platformDefines);
2089 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2090 clingArgs.push_back(platformDefines);
2093 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2094 clingArgs.push_back(platformDefines);
2097 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2098 clingArgs.push_back(platformDefines);
2100#ifdef _STLPORT_VERSION
2102 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2103 clingArgs.push_back(platformDefines);
2106 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2107 clingArgs.push_back(platformDefines);
2110 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2111 clingArgs.push_back(platformDefines);
2114 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2115 clingArgs.push_back(platformDefines);
2118 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2119 clingArgs.push_back(platformDefines);
2122 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2123 clingArgs.push_back(platformDefines);
2126 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2127 clingArgs.push_back(platformDefines);
2131 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
2132 clingArgs.push_back(platformDefines);
2135 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2136 clingArgs.push_back(platformDefines);
2137 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2138 clingArgs.push_back(platformDefines);
2147 return llvm::sys::path::filename(path).str();
2157 if (std::string::npos != pos) {
2158 dirname.assign(path.begin(), path.begin() + pos + 1);
2169 std::string dictLocation;
2171 return !dictLocation.empty();
2177 std::string &rootmapLibName)
2181 if (rootmapFileName.empty()) {
2183 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2184 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2185 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2187 rootmapLibName.c_str(),
2188 rootmapFileName.c_str());
2197 std::string &ctxtName,
2198 const cling::Interpreter &interpreter,
2199 bool treatParent =
true)
2201 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2203 if (!outerCtxt)
return;
2205 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2215 std::string &ctxtName,
2216 const cling::Interpreter &interpreter)
2218 const clang::DeclContext *theContext = theDecl.getDeclContext();
2226 const cling::Interpreter &interp)
2228 if (!decls.empty()) {
2229 std::string autoLoadKey;
2230 for (
auto &
d : decls) {
2234 if (autoLoadKey.empty()) {
2235 names.push_back(
d->getQualifiedNameAsString());
2253 const std::string &rootmapLibName,
2254 const std::list<std::string> &classesDefsList,
2255 const std::list<std::string> &classesNames,
2256 const std::list<std::string> &nsNames,
2257 const std::list<std::string> &tdNames,
2258 const std::list<std::string> &enNames,
2259 const std::list<std::string> &varNames,
2261 const std::unordered_set<std::string> headersToIgnore)
2264 std::ofstream rootmapFile(rootmapFileName.c_str());
2272 std::unordered_set<std::string> classesKeys;
2276 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2277 !enNames.empty() || !varNames.empty()) {
2280 if (!classesDefsList.empty()) {
2281 rootmapFile <<
"{ decls }\n";
2282 for (
auto & classDef : classesDefsList) {
2283 rootmapFile << classDef << std::endl;
2285 rootmapFile <<
"\n";
2287 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2290 if (!classesNames.empty()) {
2291 rootmapFile <<
"# List of selected classes\n";
2292 for (
auto & className : classesNames) {
2293 rootmapFile <<
"class " << className << std::endl;
2294 classesKeys.insert(className);
2297 std::unordered_set<std::string> treatedHeaders;
2298 for (
auto & className : classesNames) {
2300 if (className.find(
"<") != std::string::npos)
continue;
2301 if (headersClassesMap.count(className)) {
2302 auto &headers = headersClassesMap.at(className);
2303 if (!headers.empty()){
2304 auto &header = headers.front();
2305 if (treatedHeaders.insert(header).second &&
2306 headersToIgnore.find(header) == headersToIgnore.end() &&
2308 rootmapFile <<
"header " << header << std::endl;
2316 if (!nsNames.empty()) {
2317 rootmapFile <<
"# List of selected namespaces\n";
2318 for (
auto & nsName : nsNames) {
2319 rootmapFile <<
"namespace " << nsName << std::endl;
2324 if (!tdNames.empty()) {
2325 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2326 for (
const auto & autoloadKey : tdNames)
2327 if (classesKeys.insert(autoloadKey).second)
2328 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2333 if (!enNames.empty()){
2334 rootmapFile <<
"# List of selected enums and outer classes\n";
2335 for (
const auto & autoloadKey : enNames)
2336 if (classesKeys.insert(autoloadKey).second)
2337 rootmapFile <<
"enum " << autoloadKey << std::endl;
2341 if (!varNames.empty()){
2342 rootmapFile <<
"# List of selected vars\n";
2343 for (
const auto & autoloadKey : varNames)
2344 if (classesKeys.insert(autoloadKey).second)
2345 rootmapFile <<
"var " << autoloadKey << std::endl;
2359 auto nsPattern =
'{';
auto nsPatternLength = 1;
2360 auto foundNsPos =
line.find_last_of(nsPattern);
2361 if (foundNsPos == std::string::npos)
return {
"",
""};
2362 foundNsPos+=nsPatternLength;
2363 auto extNs =
line.substr(0,foundNsPos);
2365 auto nsEndPattern =
'}';
2366 auto foundEndNsPos =
line.find(nsEndPattern);
2367 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2369 return {extNs, contained};
2385 std::map<std::string, std::string> nsEntitiesMap;
2386 std::list<std::string> optFwdDeclList;
2387 for (
auto const & fwdDecl : fwdDeclarationsList){
2390 if (extNsAndEntities.first.empty()) {
2392 optFwdDeclList.push_front(fwdDecl);
2394 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2395 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2399 std::string optFwdDecl;
2400 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2401 optFwdDecl = extNsAndEntities.first;
2402 optFwdDecl += extNsAndEntities.second;
2403 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2406 optFwdDeclList.push_front(optFwdDecl);
2409 return optFwdDeclList;
2417 std::list<std::string> &el_list,
2418 std::unordered_set<std::string> &el_set)
2420 std::stringstream elStream(el);
2423 while (getline(elStream, tmp,
'\n')) {
2425 if (el_set.insert(tmp).second && !tmp.empty()) {
2426 el_list.push_back(tmp);
2437 std::list<std::string> &classesList,
2438 std::list<std::string> &classesListForRootmap,
2439 std::list<std::string> &fwdDeclarationsList,
2440 const cling::Interpreter &interpreter)
2448 std::unordered_set<std::string> classesSet;
2449 std::unordered_set<std::string> outerMostClassesSet;
2451 std::string attrName, attrValue;
2452 bool isClassSelected;
2453 std::unordered_set<std::string> availableFwdDecls;
2454 std::string fwdDeclaration;
2456 fwdDeclaration =
"";
2462 fwdDeclaration =
"";
2469 isClassSelected =
true;
2470 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2471 std::string normalizedName;
2472 normalizedName = selClass.GetNormalizedName();
2473 if (!normalizedName.empty() &&
2474 !classesSet.insert(normalizedName).second &&
2475 outerMostClassesSet.count(normalizedName) == 0) {
2476 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2477 <<
" was already selected. This means that two different instances of"
2478 <<
" clang::RecordDecl had the same name, which is not possible."
2479 <<
" This can be a hint of a serious problem in the class selection."
2480 <<
" In addition, the generated dictionary would not even compile.\n";
2483 classesList.push_back(normalizedName);
2486 const char *reqName(selClass.GetRequestedName());
2489 fwdDeclaration =
"";
2494 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2495 fwdDeclaration =
"";
2498 std::string fwdDeclarationTemplateSpec;
2500 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2508 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2510 attrName ==
"rootmap" &&
2511 attrValue ==
"false") {
2512 attrName = attrValue =
"";
2513 isClassSelected =
false;
2517 if (isClassSelected) {
2533 std::string outerMostClassName;
2535 if (!outerMostClassName.empty() &&
2536 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2537 classesSet.insert(outerMostClassName).second &&
2538 outerMostClassesSet.insert(outerMostClassName).second) {
2539 classesListForRootmap.push_back(outerMostClassName);
2541 classesListForRootmap.push_back(normalizedName);
2542 if (reqName && reqName[0] && reqName != normalizedName) {
2543 classesListForRootmap.push_back(reqName);
2548 std::string demangledName = selClass.GetDemangledTypeInfo();
2549 if (!demangledName.empty()) {
2554 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2556 classesListForRootmap.push_back(demangledName);
2562 classesListForRootmap.sort();
2575 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2590 if (clang::CXXRecordDecl *CXXRD =
2591 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2603 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2606 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2609 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2625 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2626 "#include \"TFile.h\"\n"
2627 "#include \"TObjArray.h\"\n"
2628 "#include \"TVirtualArray.h\"\n"
2629 "#include \"TStreamerElement.h\"\n"
2630 "#include \"TProtoClass.h\"\n"
2631 "#include \"TBaseClass.h\"\n"
2632 "#include \"TListOfDataMembers.h\"\n"
2633 "#include \"TListOfEnums.h\"\n"
2634 "#include \"TListOfEnumsWithLock.h\"\n"
2635 "#include \"TDataMember.h\"\n"
2636 "#include \"TEnum.h\"\n"
2637 "#include \"TEnumConstant.h\"\n"
2638 "#include \"TDictAttributeMap.h\"\n"
2639 "#include \"TMessageHandler.h\"\n"
2640 "#include \"TArray.h\"\n"
2641 "#include \"TRefArray.h\"\n"
2642 "#include \"root_std_complex.h\"\n")
2643 != cling::Interpreter::kSuccess)
2654 cling::Interpreter &interp,
2660 bool writeEmptyRootPCM)
2664 bool needsCollectionProxy =
false;
2686 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2687 if (nsName.find(
"(anonymous)") == std::string::npos)
2692 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2696 if (selClass.RequestOnlyTClass()) {
2704 if (clang::CXXRecordDecl *CXXRD =
2705 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2709 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2717 }
else if (CRD->getName() ==
"RVec") {
2718 static const clang::DeclContext *vecOpsDC =
nullptr;
2720 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2721 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2722 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2730 needsCollectionProxy);
2745 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2749 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2761 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2765 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2770 needsCollectionProxy);
2805 if (finRetCode != 0)
return finRetCode;
2815 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2816 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2819 <<
"#define R__NO_DEPRECATION" << std::endl
2824 <<
"\n/*******************************************************************/\n"
2825 <<
"#include <stddef.h>\n"
2826 <<
"#include <stdio.h>\n"
2827 <<
"#include <stdlib.h>\n"
2828 <<
"#include <string.h>\n"
2829 <<
"#include <assert.h>\n"
2830 <<
"#define G__DICTIONARY\n"
2831 <<
"#include \"ROOT/RConfig.hxx\"\n"
2832 <<
"#include \"TClass.h\"\n"
2833 <<
"#include \"TDictAttributeMap.h\"\n"
2834 <<
"#include \"TInterpreter.h\"\n"
2835 <<
"#include \"TROOT.h\"\n"
2836 <<
"#include \"TBuffer.h\"\n"
2837 <<
"#include \"TMemberInspector.h\"\n"
2838 <<
"#include \"TInterpreter.h\"\n"
2839 <<
"#include \"TVirtualMutex.h\"\n"
2840 <<
"#include \"TError.h\"\n\n"
2841 <<
"#ifndef G__ROOT\n"
2842 <<
"#define G__ROOT\n"
2844 <<
"#include \"RtypesImp.h\"\n"
2845 <<
"#include \"TIsAProxy.h\"\n"
2846 <<
"#include \"TFileMergeInfo.h\"\n"
2847 <<
"#include <algorithm>\n"
2848 <<
"#include \"TCollectionProxyInfo.h\"\n"
2849 <<
"/*******************************************************************/\n\n"
2850 <<
"#include \"TDataMember.h\"\n\n";
2857 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2858 <<
"namespace std {} using namespace std;\n\n";
2864 const std::string &includeForSource,
2865 const std::string &extraIncludes)
2867 dictStream <<
"// Header files passed as explicit arguments\n"
2868 << includeForSource << std::endl
2869 <<
"// Header files passed via #pragma extra_include\n"
2870 << extraIncludes << std::endl;
2876#if defined(R__IOSSIM) || defined(R__IOS)
2901 return filename +
"_tmp_" + std::to_string(getpid());
2908 if (nameStr.empty())
return;
2910 std::string tmpNameStr(getTmpFileName(nameStr));
2913 const char *
name(nameStr.c_str());
2914 const char *tmpName(tmpNameStr.c_str());
2916 m_names.push_back(nameStr);
2917 m_tempNames.push_back(tmpNameStr);
2921 if (0 == std::rename(
name , tmpName)) {
2926 nameStr = tmpNameStr;
2937 for (
unsigned int i = 0; i < m_size; ++i) {
2938 const char *tmpName = m_tempNames[i].c_str();
2940 std::ifstream ifile(tmpName);
2945 if (ifile.is_open())
2947 if (0 != std::remove(tmpName)) {
2960 for (
unsigned int i = 0; i < m_size; ++i) {
2961 const char *tmpName = m_tempNames[i].c_str();
2962 const char *
name = m_names[i].c_str();
2964 std::ifstream ifile(tmpName);
2969 if (ifile.is_open())
2975 if (0 != std::rename(tmpName ,
name)) {
2976 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2977 llvm::sys::fs::remove(tmpName);
2981 if (0 != std::rename(tmpName ,
name)) {
2993 size_t i = std::distance(m_tempNames.begin(),
2994 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2995 if (i == m_tempNames.size())
return m_emptyString;
3002 std::cout <<
"Restoring files in temporary file catalog:\n";
3003 for (
unsigned int i = 0; i < m_size; ++i) {
3004 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3021 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
3022 const size_t dotPos = splitDictName.find_last_of(
".");
3023 splitDictName.insert(dotPos,
"_classdef");
3025 return new std::ofstream(splitDictName.c_str());
3034 std::list<std::string> &diagnosticPragmas)
3036 static const std::string pattern(
"-Wno-");
3038 if (arg.find(pattern) != 0)
3043 diagnosticPragmas.push_back(arg);
3049 cling::Interpreter &interp)
3052 std::string fwdDecl;
3053 std::string initStr(
"{");
3055 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3056 auto &clTemplDecl = *strigNargsToKeepPair.first;
3057 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3060 + std::to_string(strigNargsToKeepPair.second)
3063 if (!fwdDeclnArgsToSkipColl.empty())
3074 if (qt.isNull())
return qt;
3075 clang::QualType thisQt(qt);
3076 while (thisQt->isPointerType() ||
3077 thisQt->isReferenceType()) {
3078 thisQt = thisQt->getPointeeType();
3088 const cling::Interpreter &interp,
3089 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3091 std::list<std::string> headers;
3094 cling::Interpreter::PushTransactionRAII RAII(&interp);
3097 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3101 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3104 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3105 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3107 if (tArgQualType.isNull())
continue;
3108 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3109 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3116 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3118 if (baseQualType.isNull())
continue;
3119 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3120 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3125 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3126 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3128 if (fieldQualType.isNull()) continue ;
3129 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3130 if (fieldCxxRcd->hasDefinition())
3131 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3137 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3139 for (
auto & fPar : methodIt->parameters()) {
3141 if (fParQualType.isNull())
continue;
3142 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3143 if (fParCxxRcd->hasDefinition())
3144 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3149 if (retQualType.isNull())
continue;
3150 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3151 if (retCxxRcd->hasDefinition())
3160 headers.emplace_back(header);
3173 if (
auto dclCtxt= rcd.getDeclContext()){
3174 if (! dclCtxt->isStdNamespace()){
3183 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3184 if (!clAsTmplSpecDecl)
return false;
3189 auto& astCtxt = rcd.getASTContext();
3190 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3191 for (
auto&& arg : templInstArgs.asArray()){
3193 auto argKind = arg.getKind();
3194 if (argKind != clang::TemplateArgument::Type){
3195 if (argKind == clang::TemplateArgument::Integral)
continue;
3199 auto argQualType = arg.getAsType();
3200 auto isPOD = argQualType.isPODType(astCtxt);
3202 if (isPOD)
continue;
3204 auto argType = argQualType.getTypePtr();
3205 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3208 if (isArgGoodForAutoParseMap)
continue;
3227 const cling::Interpreter &interp)
3229 std::set<const clang::CXXRecordDecl *> visitedDecls;
3230 std::unordered_set<std::string> buffer;
3231 std::string autoParseKey;
3234 for (
auto & annotatedRcd : annotatedRcds) {
3235 if (
const clang::CXXRecordDecl *cxxRcd =
3236 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3238 visitedDecls.clear();
3242 headers.remove_if([&buffer](
const std::string & s) {
3243 return !buffer.insert(s).second;
3246 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3248 headersDeclsMap[autoParseKey] = headers;
3249 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3251 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3256 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3257 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3258 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3264 for (
auto & tDef : tDefDecls) {
3265 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3267 visitedDecls.clear();
3272 headers.remove_if([&buffer](
const std::string & s) {
3273 return !buffer.insert(s).second;
3276 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3277 headersDeclsMap[autoParseKey] = headers;
3282 for (
auto & func : funcDecls) {
3288 for (
auto & var : varDecls) {
3294 for (
auto & en : enumDecls) {
3304 const cling::Interpreter &interp)
3306 std::string newFwdDeclString;
3310 std::string fwdDeclString;
3312 std::unordered_set<std::string> fwdDecls;
3333 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3338 selectedDecls.begin(),
3342 selectedDecls.push_back(TD);
3347 std::string fwdDeclLogs;
3355 std::cout <<
"Logs from forward decl printer: \n"
3372 if (fwdDeclString.empty()) fwdDeclString =
"";
3373 return fwdDeclString;
3380 const std::string &detectedUmbrella,
3381 bool payLoadOnly =
false)
3383 std::string headerName;
3386 std::cout <<
"Class-headers Mapping:\n";
3387 std::string headersClassesMapString =
"";
3388 for (
auto const & classHeaders : headersClassesMap) {
3390 std::cout <<
" o " << classHeaders.first <<
" --> ";
3391 headersClassesMapString +=
"\"";
3392 headersClassesMapString += classHeaders.first +
"\"";
3393 for (
auto const & header : classHeaders.second) {
3394 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3395 headersClassesMapString +=
", " + headerName;
3397 std::cout <<
", " << headerName;
3402 std::cout << std::endl;
3403 headersClassesMapString +=
", \"@\",\n";
3405 headersClassesMapString +=
"nullptr";
3406 return headersClassesMapString;
3429 static const std::vector<std::string> namePrfxes {
3432 auto pos = find_if(namePrfxes.begin(),
3434 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3435 return namePrfxes.end() == pos;
3442 static const std::vector<std::string> uclNamePrfxes {
3446 static const std::set<std::string> unsupportedClassesNormNames{
3449 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3450 auto pos = find_if(uclNamePrfxes.begin(),
3451 uclNamePrfxes.end(),
3452 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3453 return uclNamePrfxes.end() == pos;
3463 for (
auto&& aRcd : annotatedRcds){
3464 auto clName = aRcd.GetNormalizedName();
3466 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3467 <<
"currently the support for its I/O is not yet available. Note that "
3468 << clName <<
", even if not selected, will be available for "
3469 <<
"interpreted code.\n";
3473 std::cerr <<
"Error: It is not necessary to explicitly select class "
3474 << clName <<
". I/O is supported for it transparently.\n";
3486 bool isLocked =
false;
3489 InterpreterCallbacks(interp),
3490 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3495 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3496 clang::OptionalFileEntryRef , llvm::StringRef ,
3497 llvm::StringRef ,
const clang::Module * ,
3498 clang::SrcMgr::CharacteristicKind )
override
3500 if (isLocked)
return;
3501 if (IsAngled)
return;
3502 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3503 auto curLexer = PP.getCurrentFileLexer();
3504 if (!curLexer)
return;
3505 auto fileEntry = curLexer->getFileEntry();
3506 if (!fileEntry)
return;
3507 auto thisFileName = fileEntry->getName();
3508 auto fileNameAsString = FileName.str();
3510 if (isThisLinkdef) {
3512 if (isTheIncludedLinkdef) {
3513 fFilesIncludedByLinkdef.clear();
3516 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3530 clang::SourceLocation ImportLoc,
3531 bool ForPragma)
override {
3533 using namespace clang;
3534 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3535 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3536 HeaderSearch& HS = PP.getHeaderSearchInfo();
3538 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3540 assert(M &&
"Must have module Core");
3541 PP.makeModuleVisible(CoreModule, ImportLoc);
3547 llvm::cl::desc(
"Allow implicit build of system modules."),
3549static llvm::cl::list<std::string>
3552 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3555static llvm::cl::opt<std::string>
3557 llvm::cl::desc(
"<output dictionary file>"),
3577 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3589 using namespace clang::diag;
3595 std::string moduleName;
3596 const clang::Module *module =
nullptr;
3599 const auto &ID =
Info.getID();
3600 if (ID == remark_module_build || ID == remark_module_build_done) {
3601 moduleName =
Info.getArgStdStr(0);
3602 module = fMap.findModule(moduleName);
3608 "Couldn't find module %s in the available modulemaps. This"
3609 "prevents us from correctly diagnosing wrongly built modules.\n",
3610 moduleName.c_str());
3623 bool isByproductModule =
false;
3627 isByproductModule =
true;
3632 isByproductModule =
true;
3635 if (!isByproductModule)
3636 fChild->HandleDiagnostic(DiagLevel,
Info);
3638 if (ID == remark_module_build && !isByproductModule) {
3640 "Building module '%s' implicitly. If '%s' requires a \n"
3641 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3642 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3644 moduleName.c_str(), moduleName.c_str());
3652 DiagnosticConsumer::clear();
3655 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3657 fChild->BeginSourceFile(LangOpts, PP);
3658 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3663 fChild->EndSourceFile();
3664 DiagnosticConsumer::EndSourceFile();
3670 DiagnosticConsumer::finish();
3677#if defined(_WIN32) && defined(_MSC_VER)
3681 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3682 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3683 ::_set_error_mode(_OUT_TO_STDERR);
3684 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3685 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3686 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3687 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3688 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3689 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3694static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3696static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3707static llvm::cl::opt<VerboseLevel>
3709 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3710 clEnumVal(
v0,
"Show only fatal errors."),
3711 clEnumVal(
v1,
"Show errors (the same as -v)."),
3712 clEnumVal(
v2,
"Show warnings (default)."),
3713 clEnumVal(
v3,
"Show notes."),
3714 clEnumVal(
v4,
"Show information.")),
3718static llvm::cl::opt<bool>
3719gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3722static llvm::cl::opt<bool>
3723gOptReflex(
"reflex", llvm::cl::desc(
"Behave internally like genreflex."),
3725static llvm::cl::opt<bool>
3726gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3729static llvm::cl::opt<std::string>
3731 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3734static llvm::cl::opt<bool>
3736 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3739static llvm::cl::opt<bool>
3740gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3742static llvm::cl::opt<bool>
3743gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3745static llvm::cl::list<std::string>
3747 llvm::cl::desc(
"Generate rootmap file."),
3749static llvm::cl::opt<std::string>
3751 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3753static llvm::cl::opt<bool>
3755 llvm::cl::desc(
"Generate a C++ module."),
3757static llvm::cl::list<std::string>
3759 llvm::cl::desc(
"Specify a C++ modulemap file."),
3762static llvm::cl::opt<bool>
3764 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3766static llvm::cl::opt<bool>
3768 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3770static llvm::cl::opt<bool>
3772 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3774static llvm::cl::opt<bool>
3776 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3778static llvm::cl::opt<bool>
3780 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3781information and another the interactivity support."),
3783static llvm::cl::opt<bool>
3786 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3788static llvm::cl::opt<std::string>
3790 llvm::cl::desc(
"The path to the library of the built dictionary."),
3792static llvm::cl::list<std::string>
3794 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3796static llvm::cl::list<std::string>
3798 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3802static llvm::cl::opt<bool>
3804 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3812static llvm::cl::opt<bool>
3815 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3817static llvm::cl::opt<bool>
3819 llvm::cl::desc(
"Check the selection syntax only."),
3821static llvm::cl::opt<bool>
3823 llvm::cl::desc(
"Fail if there are warnings."),
3825static llvm::cl::opt<bool>
3827 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3829static llvm::cl::opt<std::string>
3831 llvm::cl::desc(
"Specify an isysroot."),
3833 llvm::cl::init(
"-"));
3834static llvm::cl::list<std::string>
3836 llvm::cl::desc(
"Specify an include path."),
3838static llvm::cl::list<std::string>
3840 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3842static llvm::cl::list<std::string>
3844 llvm::cl::desc(
"Specify a system include path."),
3846static llvm::cl::list<std::string>
3848 llvm::cl::desc(
"Specify defined macros."),
3850static llvm::cl::list<std::string>
3852 llvm::cl::desc(
"Specify undefined macros."),
3854static llvm::cl::list<std::string>
3856 llvm::cl::desc(
"Specify compiler diagnostics options."),
3859static llvm::cl::list<std::string>
3861 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file | selection xml file>"),
3863static llvm::cl::list<std::string>
3865 llvm::cl::desc(
"Consumes all unrecognized options."),
3868static llvm::cl::SubCommand
3871static llvm::cl::list<std::string>
3873 llvm::cl::desc(
"Consumes options and sends them to cling."),
3883 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3886 std::vector<clang::Module::Header> moduleHeaders;
3888 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3890 bool foundAllHeaders =
true;
3892 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3893 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3894 if (header == moduleHeader.NameAsWritten)
3902 for (
const std::string &header : modGen.
GetHeaders()) {
3903 if (isHeaderInModule(header))
3906 clang::ModuleMap::KnownHeader SuggestedModule;
3907 clang::ConstSearchDirIterator *CurDir =
nullptr;
3908 if (
auto FE = headerSearch.LookupFile(
3909 header, clang::SourceLocation(),
3912 clang::ArrayRef<std::pair<const clang::FileEntry *, const clang::DirectoryEntry *>>(),
3915 0, &SuggestedModule,
3922 if (
auto OtherModule = SuggestedModule.getModule()) {
3923 std::string OtherModuleName;
3924 auto TLM = OtherModule->getTopLevelModuleName();
3926 OtherModuleName = TLM.str();
3928 OtherModuleName = OtherModule->Name;
3935 missingHeaders.push_back({header, OtherModuleName});
3938 missingHeaders.push_back({header, {}});
3940 foundAllHeaders =
false;
3942 return foundAllHeaders;
3948 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3950 clang::CompilerInstance *CI = interpreter.getCI();
3951 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3952 headerSearch.loadTopLevelSystemModules();
3955 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3960 moduleName.c_str());
3967 std::vector<std::array<std::string, 2>> missingHdrMod;
3970 std::stringstream msgStream;
3971 msgStream <<
"after creating module \"" << module->Name <<
"\" ";
3972 if (!module->PresumedModuleMapFile.empty())
3973 msgStream <<
"using modulemap \"" << module->PresumedModuleMapFile <<
"\" ";
3974 msgStream <<
"the following headers are not part of that module:\n";
3975 for (
auto &
H : missingHdrMod) {
3976 msgStream <<
" " <<
H[0];
3978 msgStream <<
" (already part of module \"" <<
H[1] <<
"\")";
3981 std::string warningMessage = msgStream.str();
3983 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3994 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3995 warningMessage.c_str(),
4002 std::vector<std::string> missingHeaders;
4003 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
4004 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
4007 module->Name.c_str());
4017 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
4018 moduleName.consume_front(
"lib");
4019 moduleName.consume_back(
".pcm");
4020 moduleName.consume_back(
"_rdict");
4028 bool isGenreflex =
false)
4039 const char *executableFileName = argv[0];
4041 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
4042 llvm::PrettyStackTraceProgram
X(argc, argv);
4045#if defined(R__WIN32) && !defined(R__WINGCC)
4050 for (
int iic = 1 ; iic < argc; ++iic) {
4051 std::string iiarg(argv[iic]);
4053 size_t len = iiarg.length();
4055 char *argviic =
new char[
len + 1];
4056 strlcpy(argviic, iiarg.c_str(),
len + 1);
4057 argv[iic] = argviic;
4066 auto &opts = llvm::cl::getRegisteredOptions();
4067 llvm::cl::Option* optHelp = opts[
"help"];
4068 llvm::cl::alias optHelpAlias1(
"h",
4069 llvm::cl::desc(
"Alias for -help"),
4070 llvm::cl::aliasopt(*optHelp));
4071 llvm::cl::alias optHelpAlias2(
"?",
4072 llvm::cl::desc(
"Alias for -help"),
4073 llvm::cl::aliasopt(*optHelp));
4075 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
4079 std::vector<const char *> clingArgsC;
4080 clingArgsC.push_back(executableFileName);
4082 clingArgsC.push_back(
"-I");
4089 clingArgsC.push_back(Opt.c_str());
4091 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
4093 llvmResourceDir.c_str());
4096 return interp->getDiagnostics().hasFatalErrorOccurred();
4099 std::string dictname;
4113 llvm::cl::PrintHelpMessage();
4128 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
4129 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4156 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4157 llvm::cl::PrintHelpMessage();
4161 std::vector<std::string> clingArgs;
4162 clingArgs.push_back(executableFileName);
4163 clingArgs.push_back(
"-iquote.");
4169 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4175 if (GetErrorIgnoreLevel() >
kWarning)
4177 GetWarningsAreErrors() =
true;
4191 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4196 clingArgs.push_back(std::string(
"-D") + PPDefine);
4199 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4202 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4209 clingArgs.push_back(
"-isystem");
4210 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4214 for (
const std::string &WDiag :
gOptWDiags) {
4215 const std::string FullWDiag = std::string(
"-W") + WDiag;
4219 clingArgs.push_back(FullWDiag);
4223 clingArgs.push_back(std::string(
"-I") + includeDir);
4225 std::vector<std::string> pcmArgs;
4226 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4227 auto thisArg = clingArgs[parg];
4229 if (thisArg ==
"-c" ||
4235 while (
c ==
' ')
c = thisArg[++
offset];
4239 [&](
const std::string& path){
4240 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4241 if (excludePathsEnd != excludePathPos)
continue;
4243 pcmArgs.push_back(thisArg);
4250 clingArgs.push_back(
"-D__ROOTCLING__");
4253 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4254#elif defined(R__WIN32)
4255 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4258 clingArgs.push_back(
"-D_XKEYCHECK_H");
4260 clingArgs.push_back(
"-DNOMINMAX");
4262 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4265 clingArgs.push_back(
"-fsyntax-only");
4267 clingArgs.push_back(
"-fPIC");
4269 clingArgs.push_back(
"-Xclang");
4270 clingArgs.push_back(
"-fmodules-embed-all-files");
4271 clingArgs.push_back(
"-Xclang");
4272 clingArgs.push_back(
"-main-file-name");
4273 clingArgs.push_back(
"-Xclang");
4274 clingArgs.push_back((dictname +
".h").c_str());
4282 std::string outputFile;
4284 llvm::StringRef moduleName;
4289 auto clingArgsInterpreter = clingArgs;
4298 clingArgsInterpreter.push_back(
"-fmodules");
4299 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4302 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4304 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4308 if (llvm::sys::fs::exists(ModuleMapCWD))
4309 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4317 clingArgsInterpreter.push_back(
"-Xclang");
4318 clingArgsInterpreter.push_back(
"-fmodule-feature");
4319 clingArgsInterpreter.push_back(
"-Xclang");
4322 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4332 if (moduleName ==
"Core") {
4334 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4335 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4336 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4337 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4339 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4340 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4344 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4346 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4348 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4349 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4350 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4351 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4352 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4353 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4354 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4355 }
else if (moduleName ==
"MathCore") {
4356 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4361 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4365 clingArgsInterpreter.push_back(
"-v");
4368 std::vector<const char *> clingArgsC;
4369 for (
auto const &clingArg : clingArgsInterpreter) {
4371 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4372 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4375 clingArgsC.push_back(clingArg.c_str());
4379 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4380 cling::Interpreter* interpPtr =
nullptr;
4382 std::list<std::string> filesIncludedByLinkdef;
4386 clingArgsC.push_back(
"-ffast-math");
4389 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4390 llvmResourceDir.c_str()));
4391 interpPtr = owningInterpPtr.get();
4394 clingArgsC.push_back(
"-resource-dir");
4395 clingArgsC.push_back(llvmResourceDir.c_str());
4396 clingArgsC.push_back(
nullptr);
4398 extraArgs = &clingArgsC[1];
4401 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4402 interpPtr->setCallbacks(std::move(callBacks));
4405 cling::Interpreter &interp = *interpPtr;
4406 clang::CompilerInstance *CI = interp.getCI();
4408 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4409 CI->getSourceManager().setAllFilesAreTransient(
true);
4411 clang::Preprocessor &PP = CI->getPreprocessor();
4412 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4413 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4414 auto &diags = interp.getDiagnostics();
4421 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4426 diags.setClient(recordingClient,
true);
4432 interp.DumpIncludePath();
4437 interp.printIncludedFiles(llvm::outs());
4438 llvm::outs() <<
"\n\n";
4439 llvm::outs().flush();
4442 const clang::LangOptions& LangOpts
4443 = interp.getCI()->getASTContext().getLangOpts();
4444#define LANGOPT(Name, Bits, Default, Description) \
4445 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4446#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4447#include "clang/Basic/LangOptions.def"
4451 interp.getOptions().ErrorOut =
true;
4452 interp.enableRawInput(
true);
4456 if (DepMod.endswith(
"_rdict.pcm")) {
4463 cling::Interpreter::PushTransactionRAII RAII(&interp);
4464 if (!interp.loadModule(DepMod.str(),
false)) {
4473 if (interp.declare(
"#include <assert.h>\n"
4474 "#include \"Rtypes.h\"\n"
4475 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4483 if (interp.declare(
"#include <string>\n"
4484 "#include <RtypesCore.h>\n"
4485 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4496 clingArgs.push_back(
"-D__CINT__");
4497 clingArgs.push_back(
"-D__MAKECINT__");
4503 std::string interpPragmaSource;
4504 std::string includeForSource;
4505 std::string interpreterDeclarations;
4506 std::string linkdef;
4512 if (isSelectionFile) {
4514 linkdef = optHeaderFileName;
4517 executableFileName, optHeaderFileName.c_str());
4523 std::string fullheader(optHeaderFileName);
4526 if (fullheader[fullheader.length() - 1] ==
'+') {
4527 fullheader.erase(fullheader.length() - 1);
4532 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4533 if (!isSelectionFile) {
4541 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4542 pcmArgs.push_back(header);
4544 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4549 bool hasSelectionFile = !linkdef.empty();
4550 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4561 if (!newName.empty())
4574 string incCurDir =
"-I";
4575 incCurDir += currentDirectory;
4576 pcmArgs.push_back(incCurDir);
4581 std::stringstream res;
4582 const char* delim=
"\n";
4583 std::copy(diagnosticPragmas.begin(),
4584 diagnosticPragmas.end(),
4585 std::ostream_iterator<std::string>(res, delim));
4586 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4592 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4594 IgnoringPragmaHandler(
const char* pragma):
4595 clang::PragmaNamespace(pragma) {}
4596 void HandlePragma(clang::Preprocessor &PP,
4597 clang::PragmaIntroducer Introducer,
4598 clang::Token &tok)
override {
4599 PP.DiscardUntilEndOfDirective();
4605 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4606 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4607 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4608 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4610 if (!interpreterDeclarations.empty() &&
4611 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4623 pcmArgs.push_back(linkdef);
4631 interp.AddIncludePath(inclPath);
4633 std::stringstream definesUndefinesStr;
4636 if (!definesUndefinesStr.str().empty()) {
4637 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4638 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4649 if (linkdef.empty()) {
4655 std::ofstream fileout;
4657 std::ostream *splitDictStream =
nullptr;
4658 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4680 splitDeleter.reset(splitDictStream);
4682 splitDictStream = &dictStream;
4685 size_t dh = main_dictname.rfind(
'.');
4686 if (dh != std::string::npos) {
4687 main_dictname.erase(dh);
4690 std::string main_dictname_copy(main_dictname);
4712 string linkdefFilename;
4713 if (linkdef.empty()) {
4714 linkdefFilename =
"in memory";
4716 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4724 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4730 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4732 std::string extraIncludes;
4737 const unsigned int selRulesInitialSize = selectionRules.
Size();
4741 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4745 int rootclingRetCode(0);
4749 std::ifstream file(linkdefFilename.c_str());
4750 if (file.is_open()) {
4763 clingArgs.push_back(
"-Ietc/cling/cint");
4765 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4766 llvmResourceDir.c_str())) {
4768 rootclingRetCode += 1;
4778 }
else if (isSelXML) {
4782 std::ifstream file(linkdefFilename.c_str());
4783 if (file.is_open()) {
4787 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4823 dictStream <<
"#include \"TBuffer.h\"\n"
4824 <<
"#include \"TVirtualObject.h\"\n"
4825 <<
"#include <vector>\n"
4826 <<
"#include \"TSchemaHelper.h\"\n\n";
4828 std::list<std::string> includes;
4830 for (
auto & incFile : includes) {
4831 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4833 dictStream << std::endl;
4838 int scannerVerbLevel = 0;
4841 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4843 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4866 scan.
Scan(CI->getASTContext());
4868 bool has_input_error =
false;
4875 !dictSelRulesPresent &&
4882 if (rootclingRetCode)
return rootclingRetCode;
4889 if (annRcd.RequestNoInputOperator()) {
4901 if (has_input_error) {
4911 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4912 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4940 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4941 constructorTypes.emplace_back(
"__void__", interp);
4942 constructorTypes.emplace_back(
"", interp);
4973 if (rootclingRetCode != 0) {
4974 return rootclingRetCode;
4993 std::string detectedUmbrella;
4994 for (
auto & arg : pcmArgs) {
4996 detectedUmbrella = arg;
5002 headersDeclsMap.clear();
5006 std::string headersClassesMapString =
"\"\"";
5007 std::string fwdDeclsString =
"\"\"";
5023 if (modGen.
IsPCH()) {
5026 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
5036 ofstream outputfile(liblist_filename.c_str(), ios::out);
5039 executableFileName, liblist_filename.c_str());
5041 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
5042 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
5044 outputfile <<
"# Now the list of classes\n";
5049 outputfile << annRcd.GetNormalizedName() << endl;
5056 if (0 != rootclingRetCode)
return rootclingRetCode;
5062 [](
const std::string &
a,
const std::string &
b) -> std::string {
5063 if (a.empty()) return b;
5064 else return a +
" " + b;
5069 std::list<std::string> classesNames;
5070 std::list<std::string> classesNamesForRootmap;
5071 std::list<std::string> classesDefsList;
5075 classesNamesForRootmap,
5079 std::list<std::string> enumNames;
5084 std::list<std::string> varNames;
5089 if (0 != rootclingRetCode)
return rootclingRetCode;
5092 if (rootMapNeeded) {
5094 std::list<std::string> nsNames;
5103 rootmapLibName.c_str());
5106 std::unordered_set<std::string> headersToIgnore;
5109 headersToIgnore.insert(optHeaderFileName.c_str());
5111 std::list<std::string> typedefsRootmapLines;
5119 classesNamesForRootmap,
5121 typedefsRootmapLines,
5127 if (0 != rootclingRetCode)
return 1;
5137 cling::Interpreter::PushTransactionRAII RAII(&interp);
5138 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5149 if(rootclingRetCode == 0) {
5150 rootclingRetCode += tmpCatalog.
commit();
5155 return rootclingRetCode;
5166 unsigned int numberOfHeaders = 0;
5167 for (std::vector<std::string>::iterator it = headersNames.begin();
5168 it != headersNames.end(); ++it) {
5169 const std::string headername(*it);
5174 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5175 headername.c_str());
5178 return numberOfHeaders;
5184 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5187 unsigned int argvCounter = 0;
5188 for (
int i = 1; i < argc; ++i) {
5191 args.push_back(argv[i]);
5193 }
else if (argvCounter) {
5194 argv[i - argvCounter] = argv[i];
5201 std::cout <<
"Args: \n";
5202 for (std::vector<std::string>::iterator it = args.begin();
5203 it < args.end(); ++it) {
5204 std::cout << i <<
") " << *it << std::endl;
5218 if (std::string::npos !=
result) {
5230 const unsigned int size(str.size());
5231 char *
a =
new char[
size + 1];
5233 memcpy(
a, str.c_str(),
size);
5249 std::vector<std::string> &ofilesnames)
5251 ofilesnames.reserve(headersNames.size());
5253 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5254 it != headersNames.end(); ++it) {
5255 std::string ofilename(*it);
5257 ofilesnames.push_back(ofilename);
5264 const std::vector<std::string> &argsToBeAdded,
5265 const std::string &optName =
"")
5267 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5268 it != argsToBeAdded.end(); ++it) {
5276 const std::vector<std::string> &argsToBeAdded,
5277 const std::string &optName =
"")
5279 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5280 it != argsToBeAdded.end(); ++it) {
5281 if (optName.length()) {
5291 const std::string &selectionFileName,
5292 const std::string &targetLibName,
5294 const std::vector<std::string> &pcmsNames,
5295 const std::vector<std::string> &includes,
5296 const std::vector<std::string> &preprocDefines,
5297 const std::vector<std::string> &preprocUndefines,
5298 const std::vector<std::string> &warnings,
5299 const std::string &rootmapFileName,
5300 const std::string &rootmapLibName,
5301 bool interpreteronly,
5304 bool writeEmptyRootPCM,
5306 bool noIncludePaths,
5307 bool noGlobalUsingStd,
5308 const std::vector<std::string> &headersNames,
5309 bool failOnWarnings,
5310 bool printRootclingInvocation,
5311 const std::string &ofilename)
5315 std::vector<char *> argvVector;
5326 std::string dictLocation;
5332 std::string newRootmapLibName(rootmapLibName);
5333 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5334 if (headersNames.size() != 1) {
5336 "*** genreflex: No rootmap lib and several header specified!\n");
5339 newRootmapLibName =
"lib";
5340 newRootmapLibName += cleanHeaderName;
5346 std::string newRootmapFileName(rootmapFileName);
5347 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5348 newRootmapFileName = dictLocation + newRootmapFileName;
5353 if (!newRootmapFileName.empty()) {
5359 if (!newRootmapLibName.empty()) {
5369 if (interpreteronly)
5377 if (!targetLibName.empty()) {
5387 if (noGlobalUsingStd)
5397 if (writeEmptyRootPCM)
5420 if (!selectionFileName.empty()) {
5424 const int argc = argvVector.size();
5429 for (
int i = 0; i < argc; i++) {
5430 cmd += argvVector[i];
5435 std::cout << cmd << std::endl;
5436 if (printRootclingInvocation)
return 0;
5439 char **argv = & (argvVector[0]);
5444 for (
int i = 0; i < argc; i++)
5445 delete [] argvVector[i];
5447 return rootclingReturnCode;
5456 const std::string &selectionFileName,
5457 const std::string &targetLibName,
5459 const std::vector<std::string> &pcmsNames,
5460 const std::vector<std::string> &includes,
5461 const std::vector<std::string> &preprocDefines,
5462 const std::vector<std::string> &preprocUndefines,
5463 const std::vector<std::string> &warnings,
5464 const std::string &rootmapFileName,
5465 const std::string &rootmapLibName,
5466 bool interpreteronly,
5469 bool writeEmptyRootPCM,
5471 bool noIncludePaths,
5472 bool noGlobalUsingStd,
5473 const std::vector<std::string> &headersNames,
5474 bool failOnWarnings,
5475 bool printRootclingInvocation,
5476 const std::string &outputDirName_const =
"")
5478 std::string outputDirName(outputDirName_const);
5480 std::vector<std::string> ofilesNames;
5487 std::vector<std::string> namesSingleton(1);
5488 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5489 namesSingleton[0] = headersNames[i];
5490 std::string ofilenameFullPath(ofilesNames[i]);
5491 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5492 ofilenameFullPath = outputDirName + ofilenameFullPath;
5513 printRootclingInvocation,
5515 if (returnCode != 0)