12#include "rootclingCommandLineOptionsHelp.h"
14#include "RConfigure.h"
33#include <unordered_map>
34#include <unordered_set>
46#define PATH_MAX _MAX_PATH
54#include <mach-o/dyld.h>
62#include <libprocstat.h>
71#include "cling/Interpreter/Interpreter.h"
72#include "cling/Interpreter/InterpreterCallbacks.h"
73#include "cling/Interpreter/LookupHelper.h"
74#include "cling/Interpreter/Value.h"
75#include "clang/AST/CXXInheritance.h"
76#include "clang/Basic/Diagnostic.h"
77#include "clang/Frontend/CompilerInstance.h"
78#include "clang/Frontend/FrontendActions.h"
79#include "clang/Frontend/FrontendDiagnostic.h"
80#include "clang/Lex/HeaderSearch.h"
81#include "clang/Lex/Preprocessor.h"
82#include "clang/Lex/ModuleMap.h"
83#include "clang/Lex/Pragma.h"
84#include "clang/Sema/Sema.h"
85#include "clang/Serialization/ASTWriter.h"
86#include "cling/Utils/AST.h"
88#include "llvm/ADT/StringRef.h"
90#include "llvm/Support/CommandLine.h"
91#include "llvm/Support/Path.h"
92#include "llvm/Support/PrettyStackTrace.h"
93#include "llvm/Support/Signals.h"
117#include <mach-o/dyld.h>
122#define strcasecmp _stricmp
123#define strncasecmp _strnicmp
131#define rootclingStringify(s) rootclingStringifyx(s)
132#define rootclingStringifyx(s) #s
139using std::string, std::map, std::ifstream, std::ofstream, std::endl, std::ios, std::vector;
150static llvm::cl::opt<bool>
152 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
153When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
173static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
177 for (
const auto td : tdvec)
180static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
184 for (
const auto en : enumvec) {
186 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
187 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
188 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
198 static std::string exepath;
201 exepath = _dyld_get_image_name(0);
203#if defined(__linux) || defined(__linux__)
204 char linkname[PATH_MAX];
210 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
211 int ret = readlink(linkname, buf, 1024);
212 if (ret > 0 && ret < 1024) {
218 procstat* ps = procstat_open_sysctl();
219 kinfo_proc* kp = kinfo_getproc(getpid());
222 char path_str[PATH_MAX] =
"";
223 procstat_getpathname(ps, kp, path_str,
sizeof(path_str));
231 char *buf =
new char[MAX_MODULE_NAME32 + 1];
232 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
234 while ((
p = strchr(
p,
'\\')))
240 return exepath.c_str();
246 const cling::Interpreter &interp)
254 const std::list<VariableSelectionRule> &fieldSelRules)
262 if (fieldSelRules.empty())
return;
264 clang::ASTContext &C = decl.getASTContext();
266 const std::string declName(decl.getNameAsString());
268 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
269 it != fieldSelRules.end(); ++it) {
270 if (! it->GetAttributeValue(propNames::name, varName))
continue;
271 if (declName == varName) {
274 BaseSelectionRule::AttributesMap_t::iterator iter;
275 std::string userDefinedProperty;
276 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
277 const std::string &
name = iter->first;
278 const std::string &
value = iter->second;
280 if (
name == propNames::name)
continue;
285 if (
name == propNames::iotype &&
286 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
287 const char *msg =
"Data member \"%s\" is an array or a pointer. "
288 "It is not possible to assign to it the iotype \"%s\". "
289 "This transformation is possible only with data members "
290 "which are not pointers or arrays.\n";
292 msg, varName.c_str(),
value.c_str());
300 if (
name == propNames::comment) {
301 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
value,
nullptr, 0));
305 if ((
name == propNames::transient &&
value ==
"true") ||
306 (
name == propNames::persistent &&
value ==
"false")) {
307 userDefinedProperty = propNames::comment + propNames::separator +
"!";
311 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
"!",
nullptr, 0));
316 userDefinedProperty =
name + propNames::separator +
value;
319 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
329 cling::Interpreter &interpreter,
337 using namespace clang;
338 SourceLocation commentSLoc;
339 llvm::StringRef comment;
341 ASTContext &C = CXXRD.getASTContext();
344 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
345 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
346 if (declSelRulePair == declSelRulesMap.end()){
347 const std::string thisClassName(CXXRD.getName());
348 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
353 if (thisClassBaseSelectionRule) {
356 BaseSelectionRule::AttributesMap_t::iterator iter;
357 std::string userDefinedProperty;
359 const std::string &
name =
attr.first;
364 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
371 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
372 E = CXXRD.decls_end();
I != E; ++
I) {
376 if (!(*I)->isImplicit()
377 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
381 if (isClassDefMacro) {
382 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
388 if (comment.size()) {
390 if (isClassDefMacro) {
391 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
392 }
else if (!isGenreflex) {
398 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
403 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
407 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
421 llvm::APInt
len = arrayType->getSize();
422 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
423 len *= subArrayType->getSize();
424 arrayType = subArrayType;
426 return len.getLimitedValue();
432 const cling::Interpreter &interp)
434 static const clang::CXXRecordDecl *TObject_decl
437 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
444 const cling::Interpreter &interp)
446 static const clang::CXXRecordDecl *TObject_decl
459 return (0 == strcasecmp(
filename + (
len - xmllen),
".xml"));
485 if (exepath && *exepath) {
487 char *ep =
new char[PATH_MAX];
488 if (!realpath(exepath, ep)) {
489 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
490 strlcpy(ep, exepath, PATH_MAX);
493 int nche = strlen(exepath) + 1;
494 char *ep =
new char[nche];
495 strlcpy(ep, exepath, nche);
499 if ((s = strrchr(ep,
'/'))) {
501 int removesubdirs = 2;
502 if (!strncmp(s + 1,
"rootcling_stage1.exe", 20)) {
506 }
else if (!strncmp(s + 1,
"rootcling_stage1", 16)) {
511 for (
int i = 1; s && i < removesubdirs; ++i) {
513 s = strrchr(ep,
'/');
527 int ncha = strlen(ep) + 10;
528 char *env =
new char[ncha];
529 snprintf(env, ncha,
"ROOTSYS=%s", ep);
550 const char *expectedTokens[],
551 size_t *end =
nullptr)
554 if (
line[0] !=
'#')
return false;
556 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
557 while (isspace(
line[pos])) ++pos;
558 size_t lenToken = strlen(*iToken);
559 if (
line.compare(pos, lenToken, *iToken)) {
578 if (recordDecl->hasOwningModule()) {
579 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
582 std::string qual_name;
588 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
597 if (classname.find(
':') == std::string::npos)
return;
600 int slen = classname.size();
601 for (
int k = 0; k < slen; ++k) {
602 if (classname[k] ==
':') {
603 if (k + 1 >= slen || classname[k + 1] !=
':') {
608 string base = classname.substr(0, k);
613 autoloads[base] =
"";
617 }
else if (classname[k] ==
'<') {
629 std::string classname;
631 while (file >>
line) {
633 if (
line.find(
"Library.") != 0)
continue;
635 int pos =
line.find(
":", 8);
636 classname =
line.substr(8, pos - 8);
641 getline(file,
line,
'\n');
642 while (
line[0] ==
' ')
line.replace(0, 1,
"");
646 if (classname ==
"ROOT::TImpProxy") {
650 autoloads[classname] =
line;
665 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
667 while (getline(file,
line,
'\n')) {
668 if (
line ==
"{ decls }") {
669 while (getline(file,
line,
'\n')) {
670 if (
line[0] ==
'[')
break;
673 const char firstChar =
line[0];
674 if (firstChar ==
'[') {
676 libs =
line.substr(1,
line.find(
']') - 1);
677 while (libs[0] ==
' ') libs.replace(0, 1,
"");
678 }
else if (0 != keyLenMap.count(firstChar)) {
679 unsigned int keyLen = keyLenMap.at(firstChar);
680 keyname =
line.substr(keyLen,
line.length() - keyLen);
682 autoloads[keyname] = libs;
692void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
694 std::ifstream filelist(fileListName.c_str());
701 if (llvm::sys::fs::is_directory(
filename))
continue;
707 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
709 file.seekg(0, std::ios::beg);
730 const string &fullname,
731 const clang::RecordDecl *cl,
732 cling::Interpreter &interp)
735 const clang::FunctionDecl *method
740 clang::TranslationUnitDecl *TU =
741 cl->getASTContext().getTranslationUnitDecl();
745 bool has_input_error =
false;
746 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
748 if (strstr(
filename.c_str(),
"TBuffer.h") !=
nullptr ||
749 strstr(
filename.c_str(),
"Rtypes.h") !=
nullptr) {
751 has_input_error =
true;
754 has_input_error =
true;
756 if (has_input_error) {
758 const char *maybeconst =
"";
759 const char *mayberef =
"&";
760 if (
what[strlen(
what) - 1] ==
'<') {
761 maybeconst =
"const ";
765 "in this version of ROOT, the option '!' used in a linkdef file\n"
766 " implies the actual existence of customized operators.\n"
767 " The following declaration is now required:\n"
768 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
770 return has_input_error;
782 int ncha = fullname.length() + 13;
783 char *
proto =
new char[ncha];
795 return has_input_error;
801bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
807 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
811 bool isAbstract = clxx->isAbstract();
814 std::string qualName;
816 const char *qualName_c = qualName.c_str();
818 "because it inherits from TObject but does not "
819 "have its own ClassDef.\n",
832 if (
m.getType().isConstQualified()) {
833 string ret =
"const_cast< ";
836 if (type_name.substr(0,6)==
"const ") {
837 ret += type_name.c_str()+6;
843 ret +=
m.getName().str();
847 return prefix +
m.getName().str();
857 const cling::Interpreter &interp,
859 std::ostream &dictStream)
862 std::string mTypename;
875 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
877 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
878 if (!tmplt_specialization)
return 0;
884 string fulName1, fulName2;
885 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
886 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
887 clang::QualType ti = arg0.getAsType();
891 fulName1 = ti.getAsString();
894 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
895 clang::QualType tmplti = arg1.getAsType();
898 fulName2 = tmplti.getAsString();
905 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
911 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
915 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
917 }
else if (
m.getType()->isPointerType()) {
922 dictStream <<
" {" << std::endl;
924 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
929 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
932 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
935 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
936 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
937 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
940 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
941 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
942 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
946 dictStream <<
" R__stl.clear();" << std::endl;
949 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
950 <<
" if (R__tcl1==0) {" << std::endl
951 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
952 << fulName1.c_str() <<
"!\");" << std::endl
953 <<
" return;" << std::endl
954 <<
" }" << std::endl;
957 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
958 <<
" if (R__tcl2==0) {" << std::endl
959 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
960 << fulName2.c_str() <<
"!\");" << std::endl
961 <<
" return;" << std::endl
962 <<
" }" << std::endl;
965 dictStream <<
" int R__i, R__n;" << std::endl
966 <<
" R__b >> R__n;" << std::endl;
969 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
971 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
975 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
995 std::string keyName(ti.getAsString());
996 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
997 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
998 <<
" R__stl.insert(R__t3);" << std::endl;
1006 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1011 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1014 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1019 dictStream <<
" }" << std::endl
1020 <<
" }" << std::endl;
1021 if (isArr) dictStream <<
" }" << std::endl;
1027 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
1029 dictStream <<
" {" << std::endl;
1032 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1035 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1038 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1041 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1045 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1046 <<
" R__b << R__n;" << std::endl
1047 <<
" if(R__n) {" << std::endl;
1050 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1051 <<
" if (R__tcl1==0) {" << std::endl
1052 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1053 << fulName1.c_str() <<
"!\");" << std::endl
1054 <<
" return;" << std::endl
1055 <<
" }" << std::endl;
1058 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1059 <<
" if (R__tcl2==0) {" << std::endl
1060 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1061 <<
" return;" << std::endl
1062 <<
" }" << std::endl;
1065 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1066 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1068 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1069 clang::QualType tmplti = arg1.getAsType();
1076 dictStream <<
" }" << std::endl
1077 <<
" }" << std::endl
1078 <<
" }" << std::endl;
1079 if (isArr) dictStream <<
" }" << std::endl;
1091 std::string mTypenameStr;
1095 if (!strcmp(mTypeName,
"string")) {
1097 std::string fieldname =
m.getName().str();
1100 if (
m.getType()->isConstantArrayType()) {
1101 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1102 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1104 std::stringstream fullIdx;
1105 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1108 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1109 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1110 fullIdx <<
"[R__i" << dim <<
"]";
1111 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1114 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1115 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1118 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1119 if (
m.getType()->isPointerType())
1120 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1121 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1123 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1127 if (
m.getType()->isPointerType())
1128 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1129 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1130 else if (
m.getType()->isConstantArrayType()) {
1131 std::stringstream fullIdx;
1132 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1135 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1136 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1137 fullIdx <<
"[R__i" << dim <<
"]";
1138 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1141 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1143 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1154 if (
m.getType()->isPointerType()) {
1155 if (
m.getType()->getPointeeType()->isPointerType()) {
1167 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1169 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1171 dictStream <<
"[0]";
1172 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1187 int enclSpaceNesting = 0;
1194 dictStream <<
"#include \"TInterpreter.h\"\n";
1196 dictStream <<
"//_______________________________________"
1197 <<
"_______________________________________" << std::endl;
1198 if (add_template_keyword) dictStream <<
"template <> ";
1199 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1202 <<
"//_______________________________________"
1203 <<
"_______________________________________" << std::endl;
1204 if (add_template_keyword) dictStream <<
"template <> ";
1205 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1206 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1208 dictStream <<
"//_______________________________________"
1209 <<
"_______________________________________" << std::endl;
1210 if (add_template_keyword) dictStream <<
"template <> ";
1211 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1212 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1213 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1215 <<
"//_______________________________________"
1216 <<
"_______________________________________" << std::endl;
1217 if (add_template_keyword) dictStream <<
"template <> ";
1218 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1219 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1220 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1222 <<
"//_______________________________________"
1223 <<
"_______________________________________" << std::endl;
1224 if (add_template_keyword) dictStream <<
"template <> ";
1225 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1229 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1230 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1231 <<
"*)nullptr)->GetClass();" << std::endl
1232 <<
" return fgIsA;\n"
1233 <<
"}" << std::endl << std::endl
1235 <<
"//_______________________________________"
1236 <<
"_______________________________________" << std::endl;
1237 if (add_template_keyword) dictStream <<
"template <> ";
1238 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1240 dictStream <<
" Dictionary();\n";
1242 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1243 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1245 dictStream <<
" return fgIsA;" << std::endl
1246 <<
"}" << std::endl << std::endl;
1248 while (enclSpaceNesting) {
1249 dictStream <<
"} // namespace " << nsname << std::endl;
1258 cling::Interpreter &interp,
1259 std::ostream &dictStream)
1261 if (cl->isAnonymousNamespace()) {
1273 if (classname !=
"ROOT") {
1277 dictStream <<
" namespace ROOTDict {" << std::endl;
1280 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1284 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1285 dictStream << std::endl
1287 <<
" // Function generating the singleton type initializer" << std::endl
1290 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1291 <<
" {" << std::endl
1293 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1294 <<
" {" << std::endl
1297 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1299 <<
" instance(\"" << classname.c_str() <<
"\", ";
1302 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1304 dictStream <<
"0 /*version*/, ";
1308 for (
unsigned int i = 0; i <
filename.length(); i++) {
1312 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1316 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1318 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1321 dictStream << 0 <<
");" << std::endl
1323 <<
" return &instance;" << std::endl
1324 <<
" }" << std::endl
1325 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1326 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1327 <<
" // Static variable to force the class initialization" << std::endl
1329 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1330 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1333 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1334 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1335 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1336 <<
" }" << std::endl << std::endl;
1339 dictStream <<
" }" << std::endl;
1341 dictStream <<
"}" << std::endl;
1343 dictStream << std::endl;
1352llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1355 llvm::StringRef where;
1358 if (
index.size() == 0 && printError) {
1359 const char *errorstring;
1362 errorstring =
"is not an integer";
1365 errorstring =
"has not been defined before the array";
1368 errorstring =
"is a private member of a parent class";
1371 errorstring =
"is not known";
1374 errorstring =
"UNKNOWN ERROR!!!!";
1377 if (where.size() == 0) {
1379 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1382 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1391 const cling::Interpreter &interp,
1393 std::ostream &dictStream)
1395 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1396 if (clxx ==
nullptr)
return;
1403 int enclSpaceNesting = 0;
1409 dictStream <<
"//_______________________________________"
1410 <<
"_______________________________________" << std::endl;
1411 if (add_template_keyword) dictStream <<
"template <> ";
1412 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1413 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1421 int basestreamer = 0;
1422 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1426 string base_fullname;
1429 if (strstr(base_fullname.c_str(),
"::")) {
1431 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1432 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1433 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1435 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1440 if (!basestreamer) {
1441 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1442 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1444 dictStream <<
"}" << std::endl << std::endl;
1445 while (enclSpaceNesting) {
1446 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1453 string classname = fullname;
1454 if (strstr(fullname.c_str(),
"::")) {
1456 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1457 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1458 classname =
"thisClass";
1460 for (
int i = 0; i < 2; i++) {
1465 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1466 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1467 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1469 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1470 dictStream <<
" } else {" << std::endl;
1471 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1476 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1480 string base_fullname;
1483 if (strstr(base_fullname.c_str(),
"::")) {
1485 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1486 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1487 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1490 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1496 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1501 clang::QualType
type = field_iter->getType();
1502 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1512 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1516 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1519 if (strncmp(comment,
"!", 1)) {
1522 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1523 if (
type.getTypePtr()->isConstantArrayType() &&
1524 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1525 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1529 dictStream <<
" int R__i;" << std::endl;
1532 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1534 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: array of pointers to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1535 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1537 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1539 }
else if (
type.getTypePtr()->isPointerType()) {
1540 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1541 if (indexvar.size() == 0) {
1543 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1544 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1546 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1550 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1555 <<
"," << indexvar.str() <<
");" << std::endl;
1556 }
else if (isDouble32) {
1558 <<
"," << indexvar.str() <<
");" << std::endl;
1561 <<
"," << indexvar.str() <<
");" << std::endl;
1565 dictStream <<
" R__b.WriteFastArrayFloat16("
1566 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1567 }
else if (isDouble32) {
1568 dictStream <<
" R__b.WriteFastArrayDouble32("
1569 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1571 dictStream <<
" R__b.WriteFastArray("
1572 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1576 }
else if (
type.getTypePtr()->isArrayType()) {
1578 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1579 if (underling_type->isEnumeralType())
1580 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1584 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1585 }
else if (isDouble32) {
1587 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1590 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1594 if (underling_type->isEnumeralType()) {
1595 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1598 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1599 }
else if (isDouble32) {
1600 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1603 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1608 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1611 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1612 if (underling_type->isEnumeralType())
1613 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1614 << s <<
");" << std::endl;
1615 else if (isFloat16) {
1617 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1618 }
else if (isDouble32) {
1620 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1623 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1626 if (underling_type->isEnumeralType())
1627 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1628 else if (isFloat16) {
1629 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1630 }
else if (isDouble32) {
1631 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1633 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1637 }
else if (underling_type->isEnumeralType()) {
1639 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1640 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1642 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1647 <<
"=Float16_t(R_Dummy);}" << std::endl;
1650 }
else if (isDouble32) {
1653 <<
"=Double32_t(R_Dummy);}" << std::endl;
1675 if (
type.getTypePtr()->isConstantArrayType() &&
1676 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1677 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1681 dictStream <<
" int R__i;" << std::endl;
1684 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1689 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1694 dictStream <<
"[R__i];" << std::endl;
1695 }
else if (
type.getTypePtr()->isPointerType()) {
1703 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1704 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1706 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1710 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1724 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1730 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1734 dictStream <<
" int R__i;" << std::endl;
1737 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1738 std::string mTypeNameStr;
1740 const char *mTypeName = mTypeNameStr.c_str();
1741 const char *constwd =
"const ";
1742 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1743 mTypeName += strlen(constwd);
1744 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1746 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1750 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1756 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1757 << field_iter->getName().str() <<
"));" << std::endl;
1768 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1769 <<
" }" << std::endl
1770 <<
"}" << std::endl << std::endl;
1772 while (enclSpaceNesting) {
1773 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1781 const cling::Interpreter &interp,
1783 std::ostream &dictStream)
1787 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1788 if (clxx ==
nullptr)
return;
1793 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1805 int enclSpaceNesting = 0;
1811 dictStream <<
"//_______________________________________"
1812 <<
"_______________________________________" << std::endl;
1813 if (add_template_keyword) dictStream <<
"template <> ";
1814 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1816 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1817 <<
" if (R__b.IsReading()) {" << std::endl
1818 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1819 <<
" } else {" << std::endl
1820 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1821 <<
" }" << std::endl
1822 <<
"}" << std::endl << std::endl;
1824 while (enclSpaceNesting) {
1825 dictStream <<
"} // namespace " << nsname << std::endl;
1833 const cling::Interpreter &interp,
1835 std::ostream &dictStream,
1836 bool isAutoStreamer)
1838 if (isAutoStreamer) {
1848 std::string &code_for_parser)
1850 code_for_parser +=
"#ifdef __CINT__\n\n";
1851 code_for_parser +=
"#pragma link off all globals;\n";
1852 code_for_parser +=
"#pragma link off all classes;\n";
1853 code_for_parser +=
"#pragma link off all functions;\n\n";
1855 for (std::string& arg : InputFiles) {
1857 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1858 for (
int j = 0; j < 3; j++) {
1859 if (arg[
l] ==
'-') {
1864 if (arg[
l] ==
'!') {
1869 if (arg[
l] ==
'+') {
1875 if (nostr || noinp) {
1877 if (nostr) strlcat(trail,
"-", 3);
1878 if (noinp) strlcat(trail,
"!", 3);
1881 strlcpy(trail,
"+", 3);
1885 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1886 llvm::sys::path::replace_extension(filestem,
"");
1888 code_for_parser +=
"#pragma link C++ class ";
1889 code_for_parser += filestem.str().str();
1890 if (nostr || noinp || bcnt)
1891 code_for_parser += trail;
1892 code_for_parser +=
";\n";
1895 code_for_parser +=
"\n#endif\n";
1903bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1908 static const char *fopenopts =
"rb";
1910 static const char *fopenopts =
"r";
1914 fp = fopen(pname.c_str(), fopenopts);
1920 llvm::SmallVector<std::string, 10> includePaths;
1922 interp.GetIncludePaths(includePaths,
false,
false);
1924 const size_t nPaths = includePaths.size();
1925 for (
size_t i = 0; i < nPaths; i += 1 ) {
1929 fp = fopen(pname.c_str(), fopenopts);
1951 const char *inc = strstr(original,
"\\inc\\");
1953 inc = strstr(original,
"/inc/");
1954 if (inc && strlen(inc) > 5)
1974 cling::Interpreter &interp,
1977 std::ostringstream out;
1982 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1983 const std::string &hdrName
2001static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
2002 llvm::StringRef iSysRoot,
2003 clang::Module *module =
nullptr)
2006 llvm::SmallVector<char, 128> buffer;
2007 llvm::BitstreamWriter stream(buffer);
2008 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
2009 std::unique_ptr<llvm::raw_ostream> out =
2010 compilerInstance->createOutputFile(fileName,
true,
2019 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2021 writer.WriteAST(compilerInstance->getSema(), fileName.str(), module, iSysRoot);
2024 out->write(&buffer.front(), buffer.size());
2036 const std::string ¤tDirectory)
2038 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2040 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2048static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2051 if (headers.empty())
2055 std::stringstream includes;
2056 for (
const std::string &header : headers) {
2057 includes <<
"#include \"" << header <<
"\"\n";
2059 std::string includeListStr = includes.str();
2060 auto result = interpreter.declare(includeListStr);
2061 return result == cling::Interpreter::CompilationResult::kSuccess;
2069 char platformDefines[64] = {0};
2070#ifdef __INTEL_COMPILER
2071 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2072 clingArgs.push_back(platformDefines);
2075 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2076 clingArgs.push_back(platformDefines);
2079 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2080 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2081 clingArgs.push_back(platformDefines);
2083#ifdef __GNUC_MINOR__
2084 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2085 clingArgs.push_back(platformDefines);
2088 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2089 clingArgs.push_back(platformDefines);
2092 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2093 clingArgs.push_back(platformDefines);
2096 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2097 clingArgs.push_back(platformDefines);
2099#ifdef _STLPORT_VERSION
2101 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2102 clingArgs.push_back(platformDefines);
2105 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2106 clingArgs.push_back(platformDefines);
2109 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2110 clingArgs.push_back(platformDefines);
2113 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2114 clingArgs.push_back(platformDefines);
2117 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2118 clingArgs.push_back(platformDefines);
2121 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2122 clingArgs.push_back(platformDefines);
2125 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2126 clingArgs.push_back(platformDefines);
2130 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
2131 clingArgs.push_back(platformDefines);
2134 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2135 clingArgs.push_back(platformDefines);
2136 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2137 clingArgs.push_back(platformDefines);
2146 return llvm::sys::path::filename(path).str();
2156 if (std::string::npos != pos) {
2157 dirname.assign(path.begin(), path.begin() + pos + 1);
2168 std::string dictLocation;
2170 return !dictLocation.empty();
2176 std::string &rootmapLibName)
2180 if (rootmapFileName.empty()) {
2182 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2183 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2184 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2186 rootmapLibName.c_str(),
2187 rootmapFileName.c_str());
2196 std::string &ctxtName,
2197 const cling::Interpreter &interpreter,
2198 bool treatParent =
true)
2200 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2202 if (!outerCtxt)
return;
2204 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2214 std::string &ctxtName,
2215 const cling::Interpreter &interpreter)
2217 const clang::DeclContext *theContext = theDecl.getDeclContext();
2225 const cling::Interpreter &interp)
2227 if (!decls.empty()) {
2228 std::string autoLoadKey;
2229 for (
auto &
d : decls) {
2233 if (autoLoadKey.empty()) {
2234 names.push_back(
d->getQualifiedNameAsString());
2252 const std::string &rootmapLibName,
2253 const std::list<std::string> &classesDefsList,
2254 const std::list<std::string> &classesNames,
2255 const std::list<std::string> &nsNames,
2256 const std::list<std::string> &tdNames,
2257 const std::list<std::string> &enNames,
2258 const std::list<std::string> &varNames,
2260 const std::unordered_set<std::string> headersToIgnore)
2263 std::ofstream rootmapFile(rootmapFileName.c_str());
2271 std::unordered_set<std::string> classesKeys;
2275 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2276 !enNames.empty() || !varNames.empty()) {
2279 if (!classesDefsList.empty()) {
2280 rootmapFile <<
"{ decls }\n";
2281 for (
auto & classDef : classesDefsList) {
2282 rootmapFile << classDef << std::endl;
2284 rootmapFile <<
"\n";
2286 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2289 if (!classesNames.empty()) {
2290 rootmapFile <<
"# List of selected classes\n";
2291 for (
auto & className : classesNames) {
2292 rootmapFile <<
"class " << className << std::endl;
2293 classesKeys.insert(className);
2296 std::unordered_set<std::string> treatedHeaders;
2297 for (
auto & className : classesNames) {
2299 if (className.find(
"<") != std::string::npos)
continue;
2300 if (headersClassesMap.count(className)) {
2301 auto &headers = headersClassesMap.at(className);
2302 if (!headers.empty()){
2303 auto &header = headers.front();
2304 if (treatedHeaders.insert(header).second &&
2305 headersToIgnore.find(header) == headersToIgnore.end() &&
2307 rootmapFile <<
"header " << header << std::endl;
2315 if (!nsNames.empty()) {
2316 rootmapFile <<
"# List of selected namespaces\n";
2317 for (
auto & nsName : nsNames) {
2318 rootmapFile <<
"namespace " << nsName << std::endl;
2323 if (!tdNames.empty()) {
2324 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2325 for (
const auto & autoloadKey : tdNames)
2326 if (classesKeys.insert(autoloadKey).second)
2327 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2332 if (!enNames.empty()){
2333 rootmapFile <<
"# List of selected enums and outer classes\n";
2334 for (
const auto & autoloadKey : enNames)
2335 if (classesKeys.insert(autoloadKey).second)
2336 rootmapFile <<
"enum " << autoloadKey << std::endl;
2340 if (!varNames.empty()){
2341 rootmapFile <<
"# List of selected vars\n";
2342 for (
const auto & autoloadKey : varNames)
2343 if (classesKeys.insert(autoloadKey).second)
2344 rootmapFile <<
"var " << autoloadKey << std::endl;
2358 auto nsPattern =
'{';
auto nsPatternLength = 1;
2359 auto foundNsPos =
line.find_last_of(nsPattern);
2360 if (foundNsPos == std::string::npos)
return {
"",
""};
2361 foundNsPos+=nsPatternLength;
2362 auto extNs =
line.substr(0,foundNsPos);
2364 auto nsEndPattern =
'}';
2365 auto foundEndNsPos =
line.find(nsEndPattern);
2366 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2368 return {extNs, contained};
2384 std::map<std::string, std::string> nsEntitiesMap;
2385 std::list<std::string> optFwdDeclList;
2386 for (
auto const & fwdDecl : fwdDeclarationsList){
2389 if (extNsAndEntities.first.empty()) {
2391 optFwdDeclList.push_front(fwdDecl);
2393 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2394 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2398 std::string optFwdDecl;
2399 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2400 optFwdDecl = extNsAndEntities.first;
2401 optFwdDecl += extNsAndEntities.second;
2402 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2405 optFwdDeclList.push_front(optFwdDecl);
2408 return optFwdDeclList;
2416 std::list<std::string> &el_list,
2417 std::unordered_set<std::string> &el_set)
2419 std::stringstream elStream(el);
2422 while (getline(elStream, tmp,
'\n')) {
2424 if (el_set.insert(tmp).second && !tmp.empty()) {
2425 el_list.push_back(tmp);
2436 std::list<std::string> &classesList,
2437 std::list<std::string> &classesListForRootmap,
2438 std::list<std::string> &fwdDeclarationsList,
2439 const cling::Interpreter &interpreter)
2447 std::unordered_set<std::string> classesSet;
2448 std::unordered_set<std::string> outerMostClassesSet;
2450 std::string attrName, attrValue;
2451 bool isClassSelected;
2452 std::unordered_set<std::string> availableFwdDecls;
2453 std::string fwdDeclaration;
2455 fwdDeclaration =
"";
2461 fwdDeclaration =
"";
2468 isClassSelected =
true;
2469 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2470 std::string normalizedName;
2471 normalizedName = selClass.GetNormalizedName();
2472 if (!normalizedName.empty() &&
2473 !classesSet.insert(normalizedName).second &&
2474 outerMostClassesSet.count(normalizedName) == 0) {
2475 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2476 <<
" was already selected. This means that two different instances of"
2477 <<
" clang::RecordDecl had the same name, which is not possible."
2478 <<
" This can be a hint of a serious problem in the class selection."
2479 <<
" In addition, the generated dictionary would not even compile.\n";
2482 classesList.push_back(normalizedName);
2485 const char *reqName(selClass.GetRequestedName());
2488 fwdDeclaration =
"";
2493 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2494 fwdDeclaration =
"";
2497 std::string fwdDeclarationTemplateSpec;
2499 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2507 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2509 attrName ==
"rootmap" &&
2510 attrValue ==
"false") {
2511 attrName = attrValue =
"";
2512 isClassSelected =
false;
2516 if (isClassSelected) {
2532 std::string outerMostClassName;
2534 if (!outerMostClassName.empty() &&
2535 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2536 classesSet.insert(outerMostClassName).second &&
2537 outerMostClassesSet.insert(outerMostClassName).second) {
2538 classesListForRootmap.push_back(outerMostClassName);
2540 classesListForRootmap.push_back(normalizedName);
2541 if (reqName && reqName[0] && reqName != normalizedName) {
2542 classesListForRootmap.push_back(reqName);
2547 std::string demangledName = selClass.GetDemangledTypeInfo();
2548 if (!demangledName.empty()) {
2553 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2555 classesListForRootmap.push_back(demangledName);
2561 classesListForRootmap.sort();
2574 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2589 if (clang::CXXRecordDecl *CXXRD =
2590 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2602 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2605 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2608 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2624 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2625 "#include \"TFile.h\"\n"
2626 "#include \"TObjArray.h\"\n"
2627 "#include \"TVirtualArray.h\"\n"
2628 "#include \"TStreamerElement.h\"\n"
2629 "#include \"TProtoClass.h\"\n"
2630 "#include \"TBaseClass.h\"\n"
2631 "#include \"TListOfDataMembers.h\"\n"
2632 "#include \"TListOfEnums.h\"\n"
2633 "#include \"TListOfEnumsWithLock.h\"\n"
2634 "#include \"TDataMember.h\"\n"
2635 "#include \"TEnum.h\"\n"
2636 "#include \"TEnumConstant.h\"\n"
2637 "#include \"TDictAttributeMap.h\"\n"
2638 "#include \"TMessageHandler.h\"\n"
2639 "#include \"TArray.h\"\n"
2640 "#include \"TRefArray.h\"\n"
2641 "#include \"root_std_complex.h\"\n")
2642 != cling::Interpreter::kSuccess)
2653 cling::Interpreter &interp,
2659 bool writeEmptyRootPCM)
2663 bool needsCollectionProxy =
false;
2685 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2686 if (nsName.find(
"(anonymous)") == std::string::npos)
2691 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2695 if (selClass.RequestOnlyTClass()) {
2703 if (clang::CXXRecordDecl *CXXRD =
2704 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2708 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2716 }
else if (CRD->getName() ==
"RVec") {
2717 static const clang::DeclContext *vecOpsDC =
nullptr;
2719 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2720 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2721 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2729 needsCollectionProxy);
2744 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2748 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2760 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2764 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2769 needsCollectionProxy);
2804 if (finRetCode != 0)
return finRetCode;
2814 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2815 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2818 <<
"#define R__NO_DEPRECATION" << std::endl
2823 <<
"\n/*******************************************************************/\n"
2824 <<
"#include <stddef.h>\n"
2825 <<
"#include <stdio.h>\n"
2826 <<
"#include <stdlib.h>\n"
2827 <<
"#include <string.h>\n"
2828 <<
"#include <assert.h>\n"
2829 <<
"#define G__DICTIONARY\n"
2830 <<
"#include \"ROOT/RConfig.hxx\"\n"
2831 <<
"#include \"TClass.h\"\n"
2832 <<
"#include \"TDictAttributeMap.h\"\n"
2833 <<
"#include \"TInterpreter.h\"\n"
2834 <<
"#include \"TROOT.h\"\n"
2835 <<
"#include \"TBuffer.h\"\n"
2836 <<
"#include \"TMemberInspector.h\"\n"
2837 <<
"#include \"TInterpreter.h\"\n"
2838 <<
"#include \"TVirtualMutex.h\"\n"
2839 <<
"#include \"TError.h\"\n\n"
2840 <<
"#ifndef G__ROOT\n"
2841 <<
"#define G__ROOT\n"
2843 <<
"#include \"RtypesImp.h\"\n"
2844 <<
"#include \"TIsAProxy.h\"\n"
2845 <<
"#include \"TFileMergeInfo.h\"\n"
2846 <<
"#include <algorithm>\n"
2847 <<
"#include \"TCollectionProxyInfo.h\"\n"
2848 <<
"/*******************************************************************/\n\n"
2849 <<
"#include \"TDataMember.h\"\n\n";
2856 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2857 <<
"namespace std {} using namespace std;\n\n";
2863 const std::string &includeForSource,
2864 const std::string &extraIncludes)
2866 dictStream <<
"// Header files passed as explicit arguments\n"
2867 << includeForSource << std::endl
2868 <<
"// Header files passed via #pragma extra_include\n"
2869 << extraIncludes << std::endl;
2875#if defined(R__IOSSIM) || defined(R__IOS)
2900 return filename +
"_tmp_" + std::to_string(getpid());
2907 if (nameStr.empty())
return;
2909 std::string tmpNameStr(getTmpFileName(nameStr));
2912 const char *
name(nameStr.c_str());
2913 const char *tmpName(tmpNameStr.c_str());
2915 m_names.push_back(nameStr);
2916 m_tempNames.push_back(tmpNameStr);
2920 if (0 == std::rename(
name , tmpName)) {
2925 nameStr = tmpNameStr;
2936 for (
unsigned int i = 0; i < m_size; ++i) {
2937 const char *tmpName = m_tempNames[i].c_str();
2939 std::ifstream ifile(tmpName);
2944 if (ifile.is_open())
2946 if (0 != std::remove(tmpName)) {
2959 for (
unsigned int i = 0; i < m_size; ++i) {
2960 const char *tmpName = m_tempNames[i].c_str();
2961 const char *
name = m_names[i].c_str();
2963 std::ifstream ifile(tmpName);
2968 if (ifile.is_open())
2974 if (0 != std::rename(tmpName ,
name)) {
2975 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2976 llvm::sys::fs::remove(tmpName);
2980 if (0 != std::rename(tmpName ,
name)) {
2992 size_t i = std::distance(m_tempNames.begin(),
2993 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2994 if (i == m_tempNames.size())
return m_emptyString;
3001 std::cout <<
"Restoring files in temporary file catalog:\n";
3002 for (
unsigned int i = 0; i < m_size; ++i) {
3003 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3020 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
3021 const size_t dotPos = splitDictName.find_last_of(
".");
3022 splitDictName.insert(dotPos,
"_classdef");
3024 return new std::ofstream(splitDictName.c_str());
3033 std::list<std::string> &diagnosticPragmas)
3035 static const std::string pattern(
"-Wno-");
3037 if (arg.find(pattern) != 0)
3042 diagnosticPragmas.push_back(arg);
3048 cling::Interpreter &interp)
3051 std::string fwdDecl;
3052 std::string initStr(
"{");
3054 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3055 auto &clTemplDecl = *strigNargsToKeepPair.first;
3056 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3059 + std::to_string(strigNargsToKeepPair.second)
3062 if (!fwdDeclnArgsToSkipColl.empty())
3073 if (qt.isNull())
return qt;
3074 clang::QualType thisQt(qt);
3075 while (thisQt->isPointerType() ||
3076 thisQt->isReferenceType()) {
3077 thisQt = thisQt->getPointeeType();
3087 const cling::Interpreter &interp,
3088 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3090 std::list<std::string> headers;
3093 cling::Interpreter::PushTransactionRAII RAII(&interp);
3096 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3100 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3103 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3104 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3106 if (tArgQualType.isNull())
continue;
3107 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3108 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3115 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3117 if (baseQualType.isNull())
continue;
3118 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3119 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3124 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3125 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3127 if (fieldQualType.isNull()) continue ;
3128 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3129 if (fieldCxxRcd->hasDefinition())
3130 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3136 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3138 for (
auto & fPar : methodIt->parameters()) {
3140 if (fParQualType.isNull())
continue;
3141 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3142 if (fParCxxRcd->hasDefinition())
3143 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3148 if (retQualType.isNull())
continue;
3149 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3150 if (retCxxRcd->hasDefinition())
3159 headers.emplace_back(header);
3172 if (
auto dclCtxt= rcd.getDeclContext()){
3173 if (! dclCtxt->isStdNamespace()){
3182 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3183 if (!clAsTmplSpecDecl)
return false;
3188 auto& astCtxt = rcd.getASTContext();
3189 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3190 for (
auto&& arg : templInstArgs.asArray()){
3192 auto argKind = arg.getKind();
3193 if (argKind != clang::TemplateArgument::Type){
3194 if (argKind == clang::TemplateArgument::Integral)
continue;
3198 auto argQualType = arg.getAsType();
3199 auto isPOD = argQualType.isPODType(astCtxt);
3201 if (isPOD)
continue;
3203 auto argType = argQualType.getTypePtr();
3204 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3207 if (isArgGoodForAutoParseMap)
continue;
3226 const cling::Interpreter &interp)
3228 std::set<const clang::CXXRecordDecl *> visitedDecls;
3229 std::unordered_set<std::string> buffer;
3230 std::string autoParseKey;
3233 for (
auto & annotatedRcd : annotatedRcds) {
3234 if (
const clang::CXXRecordDecl *cxxRcd =
3235 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3237 visitedDecls.clear();
3241 headers.remove_if([&buffer](
const std::string & s) {
3242 return !buffer.insert(s).second;
3245 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3247 headersDeclsMap[autoParseKey] = headers;
3248 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3250 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3255 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3256 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3257 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3263 for (
auto & tDef : tDefDecls) {
3264 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3266 visitedDecls.clear();
3271 headers.remove_if([&buffer](
const std::string & s) {
3272 return !buffer.insert(s).second;
3275 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3276 headersDeclsMap[autoParseKey] = headers;
3281 for (
auto & func : funcDecls) {
3287 for (
auto & var : varDecls) {
3293 for (
auto & en : enumDecls) {
3303 const cling::Interpreter &interp)
3305 std::string newFwdDeclString;
3309 std::string fwdDeclString;
3311 std::unordered_set<std::string> fwdDecls;
3332 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3337 selectedDecls.begin(),
3341 selectedDecls.push_back(TD);
3346 std::string fwdDeclLogs;
3354 std::cout <<
"Logs from forward decl printer: \n"
3371 if (fwdDeclString.empty()) fwdDeclString =
"";
3372 return fwdDeclString;
3379 const std::string &detectedUmbrella,
3380 bool payLoadOnly =
false)
3382 std::string headerName;
3385 std::cout <<
"Class-headers Mapping:\n";
3386 std::string headersClassesMapString =
"";
3387 for (
auto const & classHeaders : headersClassesMap) {
3389 std::cout <<
" o " << classHeaders.first <<
" --> ";
3390 headersClassesMapString +=
"\"";
3391 headersClassesMapString += classHeaders.first +
"\"";
3392 for (
auto const & header : classHeaders.second) {
3393 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3394 headersClassesMapString +=
", " + headerName;
3396 std::cout <<
", " << headerName;
3401 std::cout << std::endl;
3402 headersClassesMapString +=
", \"@\",\n";
3404 headersClassesMapString +=
"nullptr";
3405 return headersClassesMapString;
3428 static const std::vector<std::string> namePrfxes {
3431 auto pos = find_if(namePrfxes.begin(),
3433 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3434 return namePrfxes.end() == pos;
3441 static const std::vector<std::string> uclNamePrfxes {
3445 static const std::set<std::string> unsupportedClassesNormNames{
3448 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3449 auto pos = find_if(uclNamePrfxes.begin(),
3450 uclNamePrfxes.end(),
3451 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3452 return uclNamePrfxes.end() == pos;
3462 for (
auto&& aRcd : annotatedRcds){
3463 auto clName = aRcd.GetNormalizedName();
3465 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3466 <<
"currently the support for its I/O is not yet available. Note that "
3467 << clName <<
", even if not selected, will be available for "
3468 <<
"interpreted code.\n";
3472 std::cerr <<
"Error: It is not necessary to explicitly select class "
3473 << clName <<
". I/O is supported for it transparently.\n";
3485 bool isLocked =
false;
3488 InterpreterCallbacks(interp),
3489 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3494 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3495 clang::OptionalFileEntryRef , llvm::StringRef ,
3496 llvm::StringRef ,
const clang::Module * ,
3497 clang::SrcMgr::CharacteristicKind )
override
3499 if (isLocked)
return;
3500 if (IsAngled)
return;
3501 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3502 auto curLexer = PP.getCurrentFileLexer();
3503 if (!curLexer)
return;
3504 auto fileEntry = curLexer->getFileEntry();
3505 if (!fileEntry)
return;
3506 auto thisFileName = fileEntry->getName();
3507 auto fileNameAsString = FileName.str();
3509 if (isThisLinkdef) {
3511 if (isTheIncludedLinkdef) {
3512 fFilesIncludedByLinkdef.clear();
3515 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3529 clang::SourceLocation ImportLoc,
3530 bool ForPragma)
override {
3532 using namespace clang;
3533 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3534 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3535 HeaderSearch& HS = PP.getHeaderSearchInfo();
3537 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3539 assert(M &&
"Must have module Core");
3540 PP.makeModuleVisible(CoreModule, ImportLoc);
3546 llvm::cl::desc(
"Allow implicit build of system modules."),
3548static llvm::cl::list<std::string>
3551 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3554static llvm::cl::opt<std::string>
3556 llvm::cl::desc(
"<output dictionary file>"),
3576 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3588 using namespace clang::diag;
3594 std::string moduleName;
3595 const clang::Module *module =
nullptr;
3598 const auto &ID =
Info.getID();
3599 if (ID == remark_module_build || ID == remark_module_build_done) {
3600 moduleName =
Info.getArgStdStr(0);
3601 module = fMap.findModule(moduleName);
3607 "Couldn't find module %s in the available modulemaps. This"
3608 "prevents us from correctly diagnosing wrongly built modules.\n",
3609 moduleName.c_str());
3622 bool isByproductModule =
false;
3626 isByproductModule =
true;
3631 isByproductModule =
true;
3634 if (!isByproductModule)
3635 fChild->HandleDiagnostic(DiagLevel,
Info);
3637 if (ID == remark_module_build && !isByproductModule) {
3639 "Building module '%s' implicitly. If '%s' requires a \n"
3640 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3641 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3643 moduleName.c_str(), moduleName.c_str());
3651 DiagnosticConsumer::clear();
3654 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3656 fChild->BeginSourceFile(LangOpts, PP);
3657 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3662 fChild->EndSourceFile();
3663 DiagnosticConsumer::EndSourceFile();
3669 DiagnosticConsumer::finish();
3676#if defined(_WIN32) && defined(_MSC_VER)
3680 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3681 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3682 ::_set_error_mode(_OUT_TO_STDERR);
3683 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3684 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3685 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3686 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3687 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3688 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3693static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3695static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3706static llvm::cl::opt<VerboseLevel>
3708 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3709 clEnumVal(
v0,
"Show only fatal errors."),
3710 clEnumVal(
v1,
"Show errors (the same as -v)."),
3711 clEnumVal(
v2,
"Show warnings (default)."),
3712 clEnumVal(
v3,
"Show notes."),
3713 clEnumVal(
v4,
"Show information.")),
3717static llvm::cl::opt<bool>
3718gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3721static llvm::cl::opt<bool>
3722gOptReflex(
"reflex", llvm::cl::desc(
"Behave internally like genreflex."),
3724static llvm::cl::opt<bool>
3725gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3728static llvm::cl::opt<std::string>
3730 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3733static llvm::cl::opt<bool>
3735 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3738static llvm::cl::opt<bool>
3739gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3741static llvm::cl::opt<bool>
3742gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3744static llvm::cl::list<std::string>
3746 llvm::cl::desc(
"Generate rootmap file."),
3748static llvm::cl::opt<std::string>
3750 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3752static llvm::cl::opt<bool>
3754 llvm::cl::desc(
"Generate a C++ module."),
3756static llvm::cl::list<std::string>
3758 llvm::cl::desc(
"Specify a C++ modulemap file."),
3761static llvm::cl::opt<bool>
3763 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3765static llvm::cl::opt<bool>
3767 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3769static llvm::cl::opt<bool>
3771 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3773static llvm::cl::opt<bool>
3775 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3777static llvm::cl::opt<bool>
3779 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3780information and another the interactivity support."),
3782static llvm::cl::opt<bool>
3785 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3787static llvm::cl::opt<std::string>
3789 llvm::cl::desc(
"The path to the library of the built dictionary."),
3791static llvm::cl::list<std::string>
3793 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3795static llvm::cl::list<std::string>
3797 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3801static llvm::cl::opt<bool>
3803 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3811static llvm::cl::opt<bool>
3814 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3816static llvm::cl::opt<bool>
3818 llvm::cl::desc(
"Check the selection syntax only."),
3820static llvm::cl::opt<bool>
3822 llvm::cl::desc(
"Fail if there are warnings."),
3824static llvm::cl::opt<bool>
3826 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3828static llvm::cl::opt<std::string>
3830 llvm::cl::desc(
"Specify an isysroot."),
3832 llvm::cl::init(
"-"));
3833static llvm::cl::list<std::string>
3835 llvm::cl::desc(
"Specify an include path."),
3837static llvm::cl::list<std::string>
3839 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3841static llvm::cl::list<std::string>
3843 llvm::cl::desc(
"Specify a system include path."),
3845static llvm::cl::list<std::string>
3847 llvm::cl::desc(
"Specify defined macros."),
3849static llvm::cl::list<std::string>
3851 llvm::cl::desc(
"Specify undefined macros."),
3853static llvm::cl::list<std::string>
3855 llvm::cl::desc(
"Specify compiler diagnostics options."),
3858static llvm::cl::list<std::string>
3860 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file | selection xml file>"),
3862static llvm::cl::list<std::string>
3864 llvm::cl::desc(
"Consumes all unrecognized options."),
3867static llvm::cl::SubCommand
3870static llvm::cl::list<std::string>
3872 llvm::cl::desc(
"Consumes options and sends them to cling."),
3882 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3885 std::vector<clang::Module::Header> moduleHeaders;
3887 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3889 bool foundAllHeaders =
true;
3891 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3892 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3893 if (header == moduleHeader.NameAsWritten)
3901 for (
const std::string &header : modGen.
GetHeaders()) {
3902 if (isHeaderInModule(header))
3905 clang::ModuleMap::KnownHeader SuggestedModule;
3906 clang::ConstSearchDirIterator *CurDir =
nullptr;
3907 if (
auto FE = headerSearch.LookupFile(
3908 header, clang::SourceLocation(),
3911 clang::ArrayRef<std::pair<clang::OptionalFileEntryRef, clang::DirectoryEntryRef>>(),
3914 0, &SuggestedModule,
3921 if (
auto OtherModule = SuggestedModule.getModule()) {
3922 std::string OtherModuleName;
3923 auto TLM = OtherModule->getTopLevelModuleName();
3925 OtherModuleName = TLM.str();
3927 OtherModuleName = OtherModule->Name;
3934 missingHeaders.push_back({header, OtherModuleName});
3937 missingHeaders.push_back({header, {}});
3939 foundAllHeaders =
false;
3941 return foundAllHeaders;
3947 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3949 clang::CompilerInstance *CI = interpreter.getCI();
3950 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3951 headerSearch.loadTopLevelSystemModules();
3954 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3959 moduleName.c_str());
3966 std::vector<std::array<std::string, 2>> missingHdrMod;
3969 std::stringstream msgStream;
3970 msgStream <<
"after creating module \"" << module->Name <<
"\" ";
3971 if (!module->PresumedModuleMapFile.empty())
3972 msgStream <<
"using modulemap \"" << module->PresumedModuleMapFile <<
"\" ";
3973 msgStream <<
"the following headers are not part of that module:\n";
3974 for (
auto &
H : missingHdrMod) {
3975 msgStream <<
" " <<
H[0];
3977 msgStream <<
" (already part of module \"" <<
H[1] <<
"\")";
3980 std::string warningMessage = msgStream.str();
3982 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3993 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3994 warningMessage.c_str(),
4001 std::vector<std::string> missingHeaders;
4002 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
4003 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
4006 module->Name.c_str());
4016 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
4017 moduleName.consume_front(
"lib");
4018 moduleName.consume_back(
".pcm");
4019 moduleName.consume_back(
"_rdict");
4027 bool isGenreflex =
false)
4038 const char *executableFileName = argv[0];
4040 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
4041 llvm::PrettyStackTraceProgram
X(argc, argv);
4044#if defined(R__WIN32) && !defined(R__WINGCC)
4049 for (
int iic = 1 ; iic < argc; ++iic) {
4050 std::string iiarg(argv[iic]);
4052 size_t len = iiarg.length();
4054 char *argviic =
new char[
len + 1];
4055 strlcpy(argviic, iiarg.c_str(),
len + 1);
4056 argv[iic] = argviic;
4065 auto &opts = llvm::cl::getRegisteredOptions();
4066 llvm::cl::Option* optHelp = opts[
"help"];
4067 llvm::cl::alias optHelpAlias1(
"h",
4068 llvm::cl::desc(
"Alias for -help"),
4069 llvm::cl::aliasopt(*optHelp));
4070 llvm::cl::alias optHelpAlias2(
"?",
4071 llvm::cl::desc(
"Alias for -help"),
4072 llvm::cl::aliasopt(*optHelp));
4074 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
4078 std::vector<const char *> clingArgsC;
4079 clingArgsC.push_back(executableFileName);
4081 clingArgsC.push_back(
"-I");
4088 clingArgsC.push_back(Opt.c_str());
4090 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
4092 llvmResourceDir.c_str());
4095 return interp->getDiagnostics().hasFatalErrorOccurred();
4098 std::string dictname;
4112 llvm::cl::PrintHelpMessage();
4127 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
4128 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4155 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4156 llvm::cl::PrintHelpMessage();
4160 std::vector<std::string> clingArgs;
4161 clingArgs.push_back(executableFileName);
4162 clingArgs.push_back(
"-iquote.");
4168 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4174 if (GetErrorIgnoreLevel() >
kWarning)
4176 GetWarningsAreErrors() =
true;
4190 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4195 clingArgs.push_back(std::string(
"-D") + PPDefine);
4198 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4201 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4208 clingArgs.push_back(
"-isystem");
4209 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4213 for (
const std::string &WDiag :
gOptWDiags) {
4214 const std::string FullWDiag = std::string(
"-W") + WDiag;
4218 clingArgs.push_back(FullWDiag);
4222 clingArgs.push_back(std::string(
"-I") + includeDir);
4224 std::vector<std::string> pcmArgs;
4225 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4226 auto thisArg = clingArgs[parg];
4228 if (thisArg ==
"-c" ||
4234 while (
c ==
' ')
c = thisArg[++
offset];
4238 [&](
const std::string& path){
4239 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4240 if (excludePathsEnd != excludePathPos)
continue;
4242 pcmArgs.push_back(thisArg);
4249 clingArgs.push_back(
"-D__ROOTCLING__");
4252 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4253#elif defined(R__WIN32)
4254 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4257 clingArgs.push_back(
"-D_XKEYCHECK_H");
4259 clingArgs.push_back(
"-DNOMINMAX");
4261 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4264 clingArgs.push_back(
"-fsyntax-only");
4266 clingArgs.push_back(
"-fPIC");
4268 clingArgs.push_back(
"-Xclang");
4269 clingArgs.push_back(
"-fmodules-embed-all-files");
4270 clingArgs.push_back(
"-Xclang");
4271 clingArgs.push_back(
"-main-file-name");
4272 clingArgs.push_back(
"-Xclang");
4273 clingArgs.push_back((dictname +
".h").c_str());
4281 std::string outputFile;
4283 llvm::StringRef moduleName;
4288 auto clingArgsInterpreter = clingArgs;
4297 clingArgsInterpreter.push_back(
"-fmodules");
4298 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4301 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4303 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4307 if (llvm::sys::fs::exists(ModuleMapCWD))
4308 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4316 clingArgsInterpreter.push_back(
"-Xclang");
4317 clingArgsInterpreter.push_back(
"-fmodule-feature");
4318 clingArgsInterpreter.push_back(
"-Xclang");
4321 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4331 if (moduleName ==
"Core") {
4333 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4334 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4335 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4336 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4338 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4339 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4343 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4345 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4347 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4348 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4349 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4350 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4351 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4352 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4353 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4354 }
else if (moduleName ==
"MathCore") {
4355 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4360 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4364 clingArgsInterpreter.push_back(
"-v");
4367 std::vector<const char *> clingArgsC;
4368 for (
auto const &clingArg : clingArgsInterpreter) {
4370 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4371 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4374 clingArgsC.push_back(clingArg.c_str());
4378 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4379 cling::Interpreter* interpPtr =
nullptr;
4381 std::list<std::string> filesIncludedByLinkdef;
4385 clingArgsC.push_back(
"-ffast-math");
4388 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4389 llvmResourceDir.c_str()));
4390 interpPtr = owningInterpPtr.get();
4393 clingArgsC.push_back(
"-resource-dir");
4394 clingArgsC.push_back(llvmResourceDir.c_str());
4395 clingArgsC.push_back(
nullptr);
4397 extraArgs = &clingArgsC[1];
4400 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4401 interpPtr->setCallbacks(std::move(callBacks));
4404 cling::Interpreter &interp = *interpPtr;
4405 clang::CompilerInstance *CI = interp.getCI();
4407 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4408 CI->getSourceManager().setAllFilesAreTransient(
true);
4410 clang::Preprocessor &PP = CI->getPreprocessor();
4411 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4412 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4413 auto &diags = interp.getDiagnostics();
4420 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4425 diags.setClient(recordingClient,
true);
4431 interp.DumpIncludePath();
4436 interp.printIncludedFiles(llvm::outs());
4437 llvm::outs() <<
"\n\n";
4438 llvm::outs().flush();
4441 const clang::LangOptions& LangOpts
4442 = interp.getCI()->getASTContext().getLangOpts();
4443#define LANGOPT(Name, Bits, Default, Description) \
4444 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4445#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4446#include "clang/Basic/LangOptions.def"
4450 interp.getOptions().ErrorOut =
true;
4451 interp.enableRawInput(
true);
4455 if (DepMod.endswith(
"_rdict.pcm")) {
4462 cling::Interpreter::PushTransactionRAII RAII(&interp);
4463 if (!interp.loadModule(DepMod.str(),
false)) {
4472 if (interp.declare(
"#include <assert.h>\n"
4473 "#include \"Rtypes.h\"\n"
4474 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4482 if (interp.declare(
"#include <string>\n"
4483 "#include <RtypesCore.h>\n"
4484 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4495 clingArgs.push_back(
"-D__CINT__");
4496 clingArgs.push_back(
"-D__MAKECINT__");
4502 std::string interpPragmaSource;
4503 std::string includeForSource;
4504 std::string interpreterDeclarations;
4505 std::string linkdef;
4511 if (isSelectionFile) {
4513 linkdef = optHeaderFileName;
4516 executableFileName, optHeaderFileName.c_str());
4522 std::string fullheader(optHeaderFileName);
4525 if (fullheader[fullheader.length() - 1] ==
'+') {
4526 fullheader.erase(fullheader.length() - 1);
4531 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4532 if (!isSelectionFile) {
4540 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4541 pcmArgs.push_back(header);
4543 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4548 bool hasSelectionFile = !linkdef.empty();
4549 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4560 if (!newName.empty())
4573 string incCurDir =
"-I";
4574 incCurDir += currentDirectory;
4575 pcmArgs.push_back(incCurDir);
4580 std::stringstream res;
4581 const char* delim=
"\n";
4582 std::copy(diagnosticPragmas.begin(),
4583 diagnosticPragmas.end(),
4584 std::ostream_iterator<std::string>(res, delim));
4585 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4591 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4593 IgnoringPragmaHandler(
const char* pragma):
4594 clang::PragmaNamespace(pragma) {}
4595 void HandlePragma(clang::Preprocessor &PP,
4596 clang::PragmaIntroducer Introducer,
4597 clang::Token &tok)
override {
4598 PP.DiscardUntilEndOfDirective();
4604 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4605 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4606 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4607 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4609 if (!interpreterDeclarations.empty() &&
4610 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4622 pcmArgs.push_back(linkdef);
4630 interp.AddIncludePath(inclPath);
4632 std::stringstream definesUndefinesStr;
4635 if (!definesUndefinesStr.str().empty()) {
4636 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4637 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4648 if (linkdef.empty()) {
4654 std::ofstream fileout;
4656 std::ostream *splitDictStream =
nullptr;
4657 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4679 splitDeleter.reset(splitDictStream);
4681 splitDictStream = &dictStream;
4684 size_t dh = main_dictname.rfind(
'.');
4685 if (dh != std::string::npos) {
4686 main_dictname.erase(dh);
4689 std::string main_dictname_copy(main_dictname);
4711 string linkdefFilename;
4712 if (linkdef.empty()) {
4713 linkdefFilename =
"in memory";
4715 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4723 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4729 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4731 std::string extraIncludes;
4736 const unsigned int selRulesInitialSize = selectionRules.
Size();
4740 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4744 int rootclingRetCode(0);
4748 std::ifstream file(linkdefFilename.c_str());
4749 if (file.is_open()) {
4762 clingArgs.push_back(
"-Ietc/cling/cint");
4764 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4765 llvmResourceDir.c_str())) {
4767 rootclingRetCode += 1;
4777 }
else if (isSelXML) {
4781 std::ifstream file(linkdefFilename.c_str());
4782 if (file.is_open()) {
4786 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4822 dictStream <<
"#include \"TBuffer.h\"\n"
4823 <<
"#include \"TVirtualObject.h\"\n"
4824 <<
"#include <vector>\n"
4825 <<
"#include \"TSchemaHelper.h\"\n\n";
4827 std::list<std::string> includes;
4829 for (
auto & incFile : includes) {
4830 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4832 dictStream << std::endl;
4837 int scannerVerbLevel = 0;
4840 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4842 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4865 scan.
Scan(CI->getASTContext());
4867 bool has_input_error =
false;
4874 !dictSelRulesPresent &&
4881 if (rootclingRetCode)
return rootclingRetCode;
4888 if (annRcd.RequestNoInputOperator()) {
4900 if (has_input_error) {
4910 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4911 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4939 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4940 constructorTypes.emplace_back(
"__void__", interp);
4941 constructorTypes.emplace_back(
"", interp);
4972 if (rootclingRetCode != 0) {
4973 return rootclingRetCode;
4992 std::string detectedUmbrella;
4993 for (
auto & arg : pcmArgs) {
4995 detectedUmbrella = arg;
5001 headersDeclsMap.clear();
5005 std::string headersClassesMapString =
"\"\"";
5006 std::string fwdDeclsString =
"\"\"";
5022 if (modGen.
IsPCH()) {
5025 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
5035 ofstream outputfile(liblist_filename.c_str(), ios::out);
5038 executableFileName, liblist_filename.c_str());
5040 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
5041 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
5043 outputfile <<
"# Now the list of classes\n";
5048 outputfile << annRcd.GetNormalizedName() << endl;
5055 if (0 != rootclingRetCode)
return rootclingRetCode;
5061 [](
const std::string &
a,
const std::string &
b) -> std::string {
5062 if (a.empty()) return b;
5063 else return a +
" " + b;
5068 std::list<std::string> classesNames;
5069 std::list<std::string> classesNamesForRootmap;
5070 std::list<std::string> classesDefsList;
5074 classesNamesForRootmap,
5078 std::list<std::string> enumNames;
5083 std::list<std::string> varNames;
5088 if (0 != rootclingRetCode)
return rootclingRetCode;
5091 if (rootMapNeeded) {
5093 std::list<std::string> nsNames;
5102 rootmapLibName.c_str());
5105 std::unordered_set<std::string> headersToIgnore;
5108 headersToIgnore.insert(optHeaderFileName.c_str());
5110 std::list<std::string> typedefsRootmapLines;
5118 classesNamesForRootmap,
5120 typedefsRootmapLines,
5126 if (0 != rootclingRetCode)
return 1;
5136 cling::Interpreter::PushTransactionRAII RAII(&interp);
5137 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5148 if(rootclingRetCode == 0) {
5149 rootclingRetCode += tmpCatalog.
commit();
5154 return rootclingRetCode;
5165 unsigned int numberOfHeaders = 0;
5166 for (std::vector<std::string>::iterator it = headersNames.begin();
5167 it != headersNames.end(); ++it) {
5168 const std::string headername(*it);
5173 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5174 headername.c_str());
5177 return numberOfHeaders;
5183 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5186 unsigned int argvCounter = 0;
5187 for (
int i = 1; i < argc; ++i) {
5190 args.push_back(argv[i]);
5192 }
else if (argvCounter) {
5193 argv[i - argvCounter] = argv[i];
5200 std::cout <<
"Args: \n";
5201 for (std::vector<std::string>::iterator it = args.begin();
5202 it < args.end(); ++it) {
5203 std::cout << i <<
") " << *it << std::endl;
5217 if (std::string::npos !=
result) {
5229 const unsigned int size(str.size());
5230 char *
a =
new char[
size + 1];
5232 memcpy(
a, str.c_str(),
size);
5248 std::vector<std::string> &ofilesnames)
5250 ofilesnames.reserve(headersNames.size());
5252 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5253 it != headersNames.end(); ++it) {
5254 std::string ofilename(*it);
5256 ofilesnames.push_back(ofilename);
5263 const std::vector<std::string> &argsToBeAdded,
5264 const std::string &optName =
"")
5266 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5267 it != argsToBeAdded.end(); ++it) {
5275 const std::vector<std::string> &argsToBeAdded,
5276 const std::string &optName =
"")
5278 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5279 it != argsToBeAdded.end(); ++it) {
5280 if (optName.length()) {
5290 const std::string &selectionFileName,
5291 const std::string &targetLibName,
5293 const std::vector<std::string> &pcmsNames,
5294 const std::vector<std::string> &includes,
5295 const std::vector<std::string> &preprocDefines,
5296 const std::vector<std::string> &preprocUndefines,
5297 const std::vector<std::string> &warnings,
5298 const std::string &rootmapFileName,
5299 const std::string &rootmapLibName,
5300 bool interpreteronly,
5303 bool writeEmptyRootPCM,
5305 bool noIncludePaths,
5306 bool noGlobalUsingStd,
5307 const std::vector<std::string> &headersNames,
5308 bool failOnWarnings,
5309 bool printRootclingInvocation,
5310 const std::string &ofilename)
5314 std::vector<char *> argvVector;
5325 std::string dictLocation;
5331 std::string newRootmapLibName(rootmapLibName);
5332 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5333 if (headersNames.size() != 1) {
5335 "*** genreflex: No rootmap lib and several header specified!\n");
5338 newRootmapLibName =
"lib";
5339 newRootmapLibName += cleanHeaderName;
5345 std::string newRootmapFileName(rootmapFileName);
5346 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5347 newRootmapFileName = dictLocation + newRootmapFileName;
5352 if (!newRootmapFileName.empty()) {
5358 if (!newRootmapLibName.empty()) {
5368 if (interpreteronly)
5376 if (!targetLibName.empty()) {
5386 if (noGlobalUsingStd)
5396 if (writeEmptyRootPCM)
5419 if (!selectionFileName.empty()) {
5423 const int argc = argvVector.size();
5428 for (
int i = 0; i < argc; i++) {
5429 cmd += argvVector[i];
5434 std::cout << cmd << std::endl;
5435 if (printRootclingInvocation)
return 0;
5438 char **argv = & (argvVector[0]);
5443 for (
int i = 0; i < argc; i++)
5444 delete [] argvVector[i];
5446 return rootclingReturnCode;
5455 const std::string &selectionFileName,
5456 const std::string &targetLibName,
5458 const std::vector<std::string> &pcmsNames,
5459 const std::vector<std::string> &includes,
5460 const std::vector<std::string> &preprocDefines,
5461 const std::vector<std::string> &preprocUndefines,
5462 const std::vector<std::string> &warnings,
5463 const std::string &rootmapFileName,
5464 const std::string &rootmapLibName,
5465 bool interpreteronly,
5468 bool writeEmptyRootPCM,
5470 bool noIncludePaths,
5471 bool noGlobalUsingStd,
5472 const std::vector<std::string> &headersNames,
5473 bool failOnWarnings,
5474 bool printRootclingInvocation,
5475 const std::string &outputDirName_const =
"")
5477 std::string outputDirName(outputDirName_const);
5479 std::vector<std::string> ofilesNames;
5486 std::vector<std::string> namesSingleton(1);
5487 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5488 namesSingleton[0] = headersNames[i];
5489 std::string ofilenameFullPath(ofilesNames[i]);
5490 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5491 ofilenameFullPath = outputDirName + ofilenameFullPath;
5512 printRootclingInvocation,
5514 if (returnCode != 0)
5529 std::vector<std::string> &values)
5532 if (options[oIndex]) {
5533 const int nVals = options[oIndex].count();
5534 values.reserve(nVals);
5535 int optionIndex = 0;
5538 << optionIndex <<
"/" << nVals <<
" "
5539 << opt->arg << std::endl;
5541 values.push_back(opt->arg);
5552 const char *descriptor)
5554 if (options[optionIndex]) {
5556 "*** genereflex: %s is not supported anymore.\n",
5613 enum optionIndex { UNKNOWN,
5614 PRINTROOTCLINGINVOCATION,
5645 enum optionTypes { NOTYPE, STRING } ;
5648 const char *genreflexUsage =
5649 "********************************************************************************\n"
5650 "* The genreflex utility does not allow to generate C++ modules containing *\n"
5651 "* reflection information required at runtime. Please use rootcling instead *\n"
5652 "* To print the rootcling invocation that corresponds to the current genreflex *\n"
5653 "* invocation please use the --print-rootcling-invocation flag. *\n"
5654 "********************************************************************************\n"
5656 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5657 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5660 const char *printRootclingInvocationUsage =
5661 "--print-rootcling-invocation\n"
5662 " Print to screen the rootcling invocation corresponding to the current \n"
5663 " genreflex invocation.\n";
5665 const char *selectionFilenameUsage =
5666 "-s, --selection_file\tSelection filename\n"
5667 " Class selection file to specify for which classes the dictionary\n"
5668 " will be generated. The final set can be crafted with exclusion and\n"
5669 " exclusion rules.\n"
5670 " Properties can be specified. Some have special meaning:\n"
5671 " - name [string] name of the entity to select with an exact matching\n"
5672 " - pattern [string] name with wildcards (*) to select entities\n"
5673 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5674 " file where the C++ entities reside and not to C++ entities themselves.\n"
5675 " - transient/persistent [string: true/false] The fields to which they are\n"
5676 " applied will not be persistified if requested.\n"
5677 " - comment [string]: what you could write in code after an inline comment\n"
5678 " without \"//\". For example comment=\"!\" or \"||\".\n"
5679 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5680 " Default value is 'false'\n"
5681 " - rntupleStreamerMode [true/false]: enforce streamed or native writing for RNTuple.\n"
5682 " If unset, RNTuple stores classes in split mode or fails if the class cannot be split.\n"
5683 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5684 " to 'true'. Default value is 'false'\n"
5688 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5689 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5690 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5691 " [noInputOperator=\"true/false\"]\n"
5692 " [rntupleStreamerMode=\"true/false\"] />\n"
5693 " <class name=\"classname\" >\n"
5694 " <field name=\"m_transient\" transient=\"true\"/>\n"
5695 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5696 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5697 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5699 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5700 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5701 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5704 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5705 " <method name=\"unwanted\" />\n"
5710 " If no selection file is specified, the class with the filename without\n"
5711 " extension will be selected, i.e. myClass.h as argument without any\n"
5712 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5714 const char *outputFilenameUsage =
5715 "-o, --output\tOutput filename\n"
5716 " Output file name. If an existing directory is specified instead of a file,\n"
5717 " then a filename will be built using the name of the input file and will\n"
5718 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5719 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5720 " have unique names.\n";
5723 const char *targetLib =
5724 "-l, --library\tTarget library\n"
5725 " The flag -l must be followed by the name of the library that will\n"
5726 " contain the object file corresponding to the dictionary produced by\n"
5727 " this invocation of genreflex.\n"
5728 " The name takes priority over the one specified for the rootmapfile.\n"
5729 " The name influences the name of the created pcm:\n"
5730 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5731 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5732 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5733 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5734 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5736 const char *rootmapUsage =
5737 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5738 " This file lists the autoload keys. For example classes for which the\n"
5739 " reflection information is provided.\n"
5740 " The format of the rootmap is the following:\n"
5741 " - Forward declarations section\n"
5742 " - Libraries sections\n"
5743 " Rootmaps can be concatenated together, for example with the cat util.\n"
5744 " In order for ROOT to pick up the information in the rootmaps, they\n"
5745 " have to be located in the library path and have the .rootmap extension.\n"
5746 " An example rootmap file could be:\n"
5748 " template <class T> class A;\n"
5749 " [ libMyLib.so ]\n"
5750 " class A<double>\n"
5755 const char *rootmapLibUsage =
5756 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5770 PRINTROOTCLINGINVOCATION,
5772 "",
"print-rootcling-invocation",
5774 printRootclingInvocationUsage
5798 "--multiDict\tSupport for many dictionaries in one library\n"
5799 " Form correct pcm names if multiple dictionaries will be in the same\n"
5800 " library (needs target library switch. See its documentation).\n"
5807 "" ,
"noGlobalUsingStd" ,
5809 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5810 " All header files must have sumbols from std:: namespace fully qualified\n"
5816 "s" ,
"selection_file" ,
5818 selectionFilenameUsage
5832 "" ,
"rootmap-lib" ,
5840 "" ,
"interpreteronly",
5842 "--interpreteronly\tDo not generate I/O related information.\n"
5843 " Generate minimal dictionary required for interactivity.\n"
5851 "--split\tSplit the dictionary\n"
5852 " Split in two the dictionary, isolating the part with\n"
5853 " ClassDef related functions in a separate file.\n"
5861 "-m \tPcm file loaded before any header (option can be repeated).\n"
5869 "-v, --verbose\tPrint some debug information.\n"
5877 "--debug\tPrint all debug information.\n"
5885 "--quiet\tPrint only warnings and errors (default).\n"
5893 "--silent\tPrint no information at all.\n"
5899 "" ,
"writeEmptyPCM",
5901 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5909 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5918 "--help\tPrint usage and exit.\n"
5924 "",
"fail_on_warnings",
5926 "--fail_on_warnings\tFail on warnings and errors.\n"
5932 "",
"selSyntaxOnly",
5934 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5940 "" ,
"noIncludePaths",
5942 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5981 "" ,
"no_membertypedefs" ,
5989 "" ,
"no_templatetypedefs" ,
5994 {0, 0,
nullptr,
nullptr,
nullptr,
nullptr}
5997 std::vector<std::string> headersNames;
5998 const int originalArgc = argc;
6000 const int extractedArgs = extractArgs(argc, argv, headersNames);
6003 argc -=
offset + extractedArgs;
6008 std::vector<ROOT::option::Option> options(stats.
options_max);
6009 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
6015 if (parse.
error()) {
6021 if (options[HELP] || originalArgc == 1) {
6026 int numberOfHeaders = checkHeadersNames(headersNames);
6027 if (0 == numberOfHeaders) {
6038 std::string verbosityOption(
"-v2");
6039 if (options[SILENT]) verbosityOption =
"-v0";
6040 if (options[VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
6041 if (options[
DEBUG]) verbosityOption =
"-v4";
6046 std::string selectionFileName;
6047 if (options[SELECTIONFILENAME]) {
6048 selectionFileName = options[SELECTIONFILENAME].arg;
6051 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
6052 selectionFileName.c_str());
6067 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
6068 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
6071 std::string targetLibName;
6072 if (options[TARGETLIB]) {
6073 targetLibName = options[TARGETLIB].arg;
6076 "Invalid target library extension: filename is %s and extension %s is expected!\n",
6077 targetLibName.c_str(),
6081 if (options[ROOTMAP]) {
6086 bool isCxxmodule = options[CXXMODULE];
6088 bool multidict =
false;
6089 if (options[MULTIDICT]) multidict =
true;
6091 bool noGlobalUsingStd =
false;
6092 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
6094 if (multidict && targetLibName.empty()) {
6096 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
6100 bool printRootclingInvocation =
false;
6101 if (options[PRINTROOTCLINGINVOCATION])
6102 printRootclingInvocation =
true;
6104 bool interpreteronly =
false;
6105 if (options[INTERPRETERONLY])
6106 interpreteronly =
true;
6108 bool doSplit =
false;
6112 bool writeEmptyRootPCM =
false;
6113 if (options[WRITEEMPTYROOTPCM])
6114 writeEmptyRootPCM =
true;
6116 bool selSyntaxOnly =
false;
6117 if (options[SELSYNTAXONLY]) {
6118 selSyntaxOnly =
true;
6121 bool noIncludePaths =
false;
6122 if (options[NOINCLUDEPATHS]) {
6123 noIncludePaths =
true;
6126 bool failOnWarnings =
false;
6127 if (options[FAILONWARNINGS]) {
6128 failOnWarnings =
true;
6137 std::vector<std::string> pcmsNames;
6141 std::vector<std::string> preprocDefines;
6145 std::vector<std::string> preprocUndefines;
6149 std::vector<std::string> includes;
6153 std::vector<std::string> warnings;
6164 int returnValue = 0;
6165 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6169 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6170 returnValue = invokeRootCling(verbosityOption,
6190 printRootclingInvocation,
6194 returnValue = invokeManyRootCling(verbosityOption,
6214 printRootclingInvocation,
6228 assert(!
gDriverConfig &&
"Driver configuration already set!");
6248 if (std::string::npos != exeName.find(
"genreflex"))
6256 ROOT::TMetaUtils::Info(
nullptr,
"Problems have been detected during the generation of the dictionary.\n");
Select classes and assign properties using C++ syntax.
The file contains utilities which are foundational and could be used across the core component of ROO...
This is the only file required to use The Lean Mean C++ Option Parser.
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
const AttributesMap_t & GetAttributes() const
std::unordered_map< std::string, std::string > AttributesMap_t
Custom diag client for clang that verifies that each implicitly build module is a system module.
CheckModuleBuildClient(clang::DiagnosticConsumer *Child, bool OwnsChild, clang::ModuleMap &Map)
clang::DiagnosticConsumer * fChild
~CheckModuleBuildClient()
virtual void BeginSourceFile(const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) override
virtual void finish() override
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
virtual void clear() override
virtual bool IncludeInDiagnosticCounts() const override
virtual void EndSourceFile() override
const std::list< VariableSelectionRule > & GetFieldSelectionRules() const
bool LoadIncludes(std::string &extraInclude)
bool Parse(SelectionRules &sr, llvm::StringRef code, const std::vector< std::string > &parserArgs, const char *llvmdir)
void GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlClass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
void WriteClassInit(std::ostream &strm, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const ROOT::TMetaUtils::RConstructorTypes &, bool &needCollectionProxy, void(*emitStreamerInfo)(const char *))
void WriteUmbrellaHeader(std::ostream &out) const
Write a header file pulling in the content of this module through a series of #defined,...
const std::string & GetUmbrellaName() const
const std::vector< std::string > & GetIncludePaths() const
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes, bool hasCxxModule) const
const std::vector< std::string > & GetHeaders() const
void WriteContentHeader(std::ostream &out) const
Write a header file describing the content of this module through a series of variables inside the na...
int GetErrorCount() const
const std::string & GetModuleFileName() const
std::ostream & WritePPUndefines(std::ostream &out) const
Write #ifdef FOO # undef FOO #endif
void ParseArgs(const std::vector< std::string > &args)
Parse -I -D -U headers.h SomethingLinkdef.h.
const std::string & GetContentName() const
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO # define FOO=bar #endif
A parsed option from the command line together with its argument if it has one.
Option * next()
Returns a pointer to the next element of the linked list or NULL if called on last().
Checks argument vectors for validity and parses them into data structures that are easier to work wit...
bool error()
Returns true if an unrecoverable error occurred while parsing options.
void Scan(const clang::ASTContext &C)
std::vector< ROOT::TMetaUtils::AnnotatedRecordDecl > ClassColl_t
const DeclsSelRulesMap_t & GetDeclsSelRulesMap() const
FunctionColl_t fSelectedFunctions
std::vector< const clang::FunctionDecl * > FunctionColl_t
NamespaceColl_t fSelectedNamespaces
TypedefColl_t fSelectedTypedefs
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
std::map< const clang::Decl *, const BaseSelectionRule * > DeclsSelRulesMap_t
EnumColl_t fSelectedEnums
std::vector< const clang::TypedefNameDecl * > TypedefColl_t
std::vector< const clang::VarDecl * > VariableColl_t
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
VariableColl_t fSelectedVariables
std::vector< const clang::EnumDecl * > EnumColl_t
ClassColl_t fSelectedClasses
The class representing the collection of selection rules.
bool AreAllSelectionRulesUsed() const
bool SearchNames(cling::Interpreter &interp)
void PrintSelectionRules() const
unsigned int Size() const
void SetSelectionFileType(ESelectionFileTypes fileType)
void InclusionDirective(clang::SourceLocation, const clang::Token &, llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange, clang::OptionalFileEntryRef, llvm::StringRef, llvm::StringRef, const clang::Module *, clang::SrcMgr::CharacteristicKind) override
std::list< std::string > & fFilesIncludedByLinkdef
void EnteredSubmodule(clang::Module *M, clang::SourceLocation ImportLoc, bool ForPragma) override
TRootClingCallbacks(cling::Interpreter *interp, std::list< std::string > &filesIncludedByLinkdef)
bool Parse(const std::string &fileName, SelectionRules &out)
Little helper class to bookkeep the files names which we want to make temporary.
void addFileName(std::string &nameStr)
Adds the name and the associated temp name to the catalog.
const std::string & getFileName(const std::string &tmpFileName)
std::vector< std::string > m_names
std::vector< std::string > m_tempNames
const std::string m_emptyString
std::string getTmpFileName(const std::string &filename)
static bool FromCygToNativePath(std::string &path)
std::string GetCurrentDir()
std::string MakePathRelative(const std::string &path, const std::string &base, bool isBuildingROOT=false)
void printUsage(OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN SchemaRuleClassMap_t gReadRules
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
R__EXTERN SchemaRuleClassMap_t gReadRawRules
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
void Init(TClassEdit::TInterpreterLookupHelper *helper)
void header2outputName(std::string &fileName)
Replace the extension with "_rflx.cpp".
void AddToArgVectorSplit(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
void changeExtension(std::string &filename, const std::string &newExtension)
int invokeManyRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, bool printRootclingInvocation, const std::string &outputDirName_const="")
Get the right ofilenames and invoke several times rootcling One invokation per header.
int invokeRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, bool printRootclingInvocation, const std::string &ofilename)
unsigned int checkHeadersNames(std::vector< std::string > &headersNames)
Loop on arguments: stop at the first which starts with -.
void headers2outputsNames(const std::vector< std::string > &headersNames, std::vector< std::string > &ofilesnames)
Get a proper name for the output file.
char * string2charptr(const std::string &str)
The caller is responsible for deleting the string!
unsigned int extractArgs(int argc, char **argv, std::vector< std::string > &args)
Extract the arguments from the command line.
void AddToArgVector(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
int FinalizeStreamerInfoWriting(cling::Interpreter &interp, bool writeEmptyRootPCM=false)
Make up for skipping RegisterModule, now that dictionary parsing is done and these headers cannot be ...
std::list< std::string > CollapseIdenticalNamespaces(const std::list< std::string > &fwdDeclarationsList)
If two identical namespaces are there, just declare one only Example: namespace A { namespace B { fwd...
static llvm::cl::opt< bool > gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
int RootClingMain(int argc, char **argv, bool isGenreflex=false)
static llvm::StringRef GetModuleNameFromRdictName(llvm::StringRef rdictName)
static llvm::cl::opt< bool > gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), llvm::cl::cat(gRootclingOptions), llvm::cl::init("-"))
int STLContainerStreamer(const clang::FieldDecl &m, int rwmode, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
Create Streamer code for an STL container.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static llvm::cl::opt< bool > gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
static llvm::cl::list< std::string > gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), llvm::cl::cat(gRootclingOptions))
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
static void MaybeSuppressWin32CrashDialogs()
void RecordDeclCallback(const clang::RecordDecl *recordDecl)
void CheckClassNameForRootMap(const std::string &classname, map< string, string > &autoloads)
bool Which(cling::Interpreter &interp, const char *fname, string &pname)
Find file name in path specified via -I statements to Cling.
void AdjustRootMapNames(std::string &rootmapFileName, std::string &rootmapLibName)
void AddNamespaceSTDdeclaration(std::ostream &dictStream)
static llvm::cl::list< std::string > gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptModuleByproducts("mByproduct", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("The list of the expected implicit modules build as part of building the current module."), llvm::cl::cat(gRootclingOptions))
map< string, string > gAutoloads
static llvm::cl::opt< bool > gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), llvm::cl::cat(gRootclingOptions))
static bool CheckModuleValid(TModuleGenerator &modGen, const std::string &resourceDir, cling::Interpreter &interpreter, llvm::StringRef LinkdefPath, const std::string &moduleName)
Check moduleName validity from modulemap. Check if this module is defined or not.
static void CheckForMinusW(std::string arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance, llvm::StringRef iSysRoot, clang::Module *module=nullptr)
Write the AST of the given CompilerInstance to the given File while respecting the given isysroot.
static llvm::cl::opt< bool > gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), llvm::cl::cat(gRootclingOptions))
void ExtractFilePath(const std::string &path, std::string &dirname)
Extract the path from a fullpath finding the last \ or / according to the content in gPathSeparator.
int STLStringStreamer(const clang::FieldDecl &m, int rwmode, std::ostream &dictStream)
Create Streamer code for a standard string object.
void CreateDictHeader(std::ostream &dictStream, const std::string &main_dictname)
const char * GetExePath()
Returns the executable path name, used e.g. by SetRootSys().
const std::string gPathSeparator(ROOT::TMetaUtils::GetPathSeparator())
static llvm::cl::list< std::string > gOptBareClingSink(llvm::cl::OneOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes options and sends them to cling."), llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gBareClingSubcommand))
bool InheritsFromTObject(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static bool InjectModuleUtilHeader(const char *argv0, TModuleGenerator &modGen, cling::Interpreter &interp, bool umbrella)
Write the extra header injected into the module: umbrella header if (umbrella) else content header.
static llvm::cl::list< std::string > gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), llvm::cl::cat(gRootclingOptions))
int ExtractClassesListAndDeclLines(RScanner &scan, std::list< std::string > &classesList, std::list< std::string > &classesListForRootmap, std::list< std::string > &fwdDeclarationsList, const cling::Interpreter &interpreter)
void ParseRootMapFileNewFormat(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map, using the new format.
static llvm::cl::OptionCategory gRootclingOptions("rootcling common options")
static llvm::cl::list< std::string > gOptSysIncludePaths("isystem", llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a system include path."), llvm::cl::cat(gRootclingOptions))
void ExtractHeadersForDecls(const RScanner::ClassColl_t &annotatedRcds, const RScanner::TypedefColl_t tDefDecls, const RScanner::FunctionColl_t funcDecls, const RScanner::VariableColl_t varDecls, const RScanner::EnumColl_t enumDecls, HeadersDeclsMap_t &headersClassesMap, HeadersDeclsMap_t &headersDeclsMap, const cling::Interpreter &interp)
bool ParsePragmaLine(const std::string &line, const char *expectedTokens[], size_t *end=nullptr)
Check whether the #pragma line contains expectedTokens (0-terminated array).
static llvm::cl::opt< bool > gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static bool ModuleContainsHeaders(TModuleGenerator &modGen, clang::HeaderSearch &headerSearch, clang::Module *module, std::vector< std::array< std::string, 2 > > &missingHeaders)
Returns true iff a given module (and its submodules) contains all headers needed by the given ModuleG...
static bool GenerateAllDict(TModuleGenerator &modGen, clang::CompilerInstance *compilerInstance, const std::string ¤tDirectory)
Generates a PCH from the given ModuleGenerator and CompilerInstance.
void LoadLibraryMap(const std::string &fileListName, map< string, string > &autoloads)
Fill the map of libraries to be loaded in presence of a class Transparently support the old and new r...
std::ostream * CreateStreamPtrForSplitDict(const std::string &dictpathname, tempFileNamesCatalog &tmpCatalog)
Transform name of dictionary.
void WriteNamespaceInit(const clang::NamespaceDecl *cl, cling::Interpreter &interp, std::ostream &dictStream)
Write the code to initialize the namespace name and the initialization object.
static llvm::cl::list< std::string > gOptCompDefaultIncludePaths("compilerI", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a compiler default include path, to suppress unneeded `-isystem` arguments."), llvm::cl::cat(gRootclingOptions))
void AnnotateAllDeclsForPCH(cling::Interpreter &interp, RScanner &scan)
We need annotations even in the PCH: // !, // || etc.
size_t GetFullArrayLength(const clang::ConstantArrayType *arrayType)
static llvm::cl::opt< bool > gOptSplit("split", llvm::cl::desc("Split the dictionary into two parts: one containing the IO (ClassDef)\
information and another the interactivity support."), llvm::cl::cat(gRootclingOptions))
bool ProcessAndAppendIfNotThere(const std::string &el, std::list< std::string > &el_list, std::unordered_set< std::string > &el_set)
Separate multiline strings.
static llvm::cl::opt< bool > gOptNoGlobalUsingStd("noGlobalUsingStd", llvm::cl::desc("Do not declare {using namespace std} in dictionary global scope."), llvm::cl::cat(gRootclingOptions))
const ROOT::Internal::RootCling::DriverConfig * gDriverConfig
static llvm::cl::list< std::string > gOptModuleDependencies("m", llvm::cl::desc("The list of dependent modules of the dictionary."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::SubCommand gBareClingSubcommand("bare-cling", "Call directly cling and exit.")
static llvm::cl::opt< bool > gOptInterpreterOnly("interpreteronly", llvm::cl::desc("Generate minimal dictionary for interactivity (without IO information)."), llvm::cl::cat(gRootclingOptions))
void WriteArrayDimensions(const clang::QualType &type, std::ostream &dictStream)
Write "[0]" for all but the 1st dimension.
static llvm::cl::opt< bool > gOptReflex("reflex", llvm::cl::desc("Behave internally like genreflex."), llvm::cl::cat(gRootclingOptions))
void GetMostExternalEnclosingClassName(const clang::DeclContext &theContext, std::string &ctxtName, const cling::Interpreter &interpreter, bool treatParent=true)
Extract the proper autoload key for nested classes The routine does not erase the name,...
std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, cling::Interpreter &interp)
int ExtractAutoloadKeys(std::list< std::string > &names, const COLL &decls, const cling::Interpreter &interp)
static llvm::cl::opt< std::string > gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), llvm::cl::cat(gRootclingOptions))
void WriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
#define rootclingStringify(s)
void GetMostExternalEnclosingClassNameFromDecl(const clang::Decl &theDecl, std::string &ctxtName, const cling::Interpreter &interpreter)
static llvm::cl::opt< bool > gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void SetRootSys()
Set the ROOTSYS env var based on the executable location.
bool CheckInputOperator(const char *what, const char *proto, const string &fullname, const clang::RecordDecl *cl, cling::Interpreter &interp)
Check if the specified operator (what) has been properly declared if the user has requested a custom ...
void GenerateNecessaryIncludes(std::ostream &dictStream, const std::string &includeForSource, const std::string &extraIncludes)
void StrcpyArg(string &dest, const char *original)
Copy the command line argument, stripping MODULE/inc if necessary.
static llvm::cl::list< std::string > gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), llvm::cl::cat(gRootclingOptions))
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
static llvm::cl::opt< bool > gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), llvm::cl::cat(gRootclingOptions))
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
static std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
static llvm::cl::opt< bool > gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), llvm::cl::cat(gRootclingOptions))
const char * CopyArg(const char *original)
If the argument starts with MODULE/inc, strip it to make it the name we can use in #includes.
string GetNonConstMemberName(const clang::FieldDecl &m, const string &prefix="")
Return the name of the data member so that it can be used by non-const operation (so it includes a co...
static llvm::cl::list< std::string > gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), llvm::cl::cat(gRootclingOptions))
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
void ExtractSelectedNamespaces(RScanner &scan, std::list< std::string > &nsList)
Loop on selected classes and put them in a list.
static bool IncludeHeaders(const std::vector< std::string > &headers, cling::Interpreter &interpreter)
Includes all given headers in the interpreter.
clang::QualType GetPointeeTypeIfPossible(const clang::QualType &qt)
Get the pointee type if possible.
void AnnotateDecl(clang::CXXRecordDecl &CXXRD, const RScanner::DeclsSelRulesMap_t &declSelRulesMap, cling::Interpreter &interpreter, bool isGenreflex)
static llvm::cl::opt< VerboseLevel > gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), llvm::cl::values(clEnumVal(v, "Show errors."), clEnumVal(v0, "Show only fatal errors."), clEnumVal(v1, "Show errors (the same as -v)."), clEnumVal(v2, "Show warnings (default)."), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), llvm::cl::cat(gRootclingOptions))
void GenerateLinkdef(llvm::cl::list< std::string > &InputFiles, std::string &code_for_parser)
static llvm::cl::opt< std::string > gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include <header> but expands the header content."), llvm::cl::cat(gRootclingOptions))
bool isPointerToPointer(const clang::FieldDecl &m)
int CreateNewRootMapFile(const std::string &rootmapFileName, const std::string &rootmapLibName, const std::list< std::string > &classesDefsList, const std::list< std::string > &classesNames, const std::list< std::string > &nsNames, const std::list< std::string > &tdNames, const std::list< std::string > &enNames, const std::list< std::string > &varNames, const HeadersDeclsMap_t &headersClassesMap, const std::unordered_set< std::string > headersToIgnore)
Generate a rootmap file in the new format, like { decls } namespace A { namespace B { template <typen...
static llvm::cl::opt< std::string > gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::desc("<output dictionary file>"), llvm::cl::cat(gRootclingOptions))
bool IsSelectionXml(const char *filename)
bool IsGoodLibraryName(const std::string &name)
llvm::StringRef GrabIndex(const cling::Interpreter &interp, const clang::FieldDecl &member, int printError)
GrabIndex returns a static string (so use it or copy it immediately, do not call GrabIndex twice in t...
static llvm::cl::opt< bool > gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), llvm::cl::cat(gRootclingOptions))
bool IsSelectionFile(const char *filename)
const std::string GenerateStringFromHeadersForClasses(const HeadersDeclsMap_t &headersClassesMap, const std::string &detectedUmbrella, bool payLoadOnly=false)
Generate a string for the dictionary from the headers-classes map.
bool IsSupportedClassName(const char *name)
static llvm::cl::opt< bool > gOptIgnoreExistingDict("r", llvm::cl::desc("Deprecated. Similar to -f but it ignores the dictionary generation. \
When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptForce("f", llvm::cl::desc("Overwrite <file>s."), llvm::cl::cat(gRootclingOptions))
static void AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules)
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
static llvm::cl::list< std::string > gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), llvm::cl::cat(gRootclingOptions))
int CheckClassesForInterpreterOnlyDicts(cling::Interpreter &interp, RScanner &scan)
bool InheritsFromTSelector(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static void EmitTypedefs(const std::vector< const clang::TypedefNameDecl * > &tdvec)
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
bool Namespace__HasMethod(const clang::NamespaceDecl *cl, const char *name, const cling::Interpreter &interp)
static llvm::cl::list< std::string > gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), llvm::cl::cat(gRootclingOptions))
bool IsCorrectClingArgument(const std::string &argument)
Check if the argument is a sane cling argument.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)
void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream &dictStream, bool autoLoad=false)
Write the code to set the class name and the initialization object.
static llvm::cl::list< std::string > gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the <path> in the dictionary."), llvm::cl::cat(gRootclingOptions))
std::list< std::string > RecordDecl2Headers(const clang::CXXRecordDecl &rcd, const cling::Interpreter &interp, std::set< const clang::CXXRecordDecl * > &visitedDecls)
Extract the list of headers necessary for the Decl.
void EmitStreamerInfo(const char *normName)
static llvm::cl::opt< bool > gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), llvm::cl::cat(gRootclingOptions))
bool HasPath(const std::string &name)
Check if file has a path.
static llvm::cl::opt< std::string > gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::ZeroOrMore, llvm::cl::desc("<list of dictionary header files> <LinkDef file | selection xml file>"), llvm::cl::cat(gRootclingOptions))
int CheckForUnsupportedClasses(const RScanner::ClassColl_t &annotatedRcds)
Check if the list of selected classes contains any class which is not supported.
static void EmitEnums(const std::vector< const clang::EnumDecl * > &enumvec)
int GenerateFullDict(std::ostream &dictStream, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool isSelXML, bool writeEmptyRootPCM)
static llvm::cl::opt< bool > gOptSystemModuleByproducts("mSystemByproducts", llvm::cl::Hidden, llvm::cl::desc("Allow implicit build of system modules."), llvm::cl::cat(gRootclingOptions))
bool CheckClassDef(const clang::RecordDecl &cl, const cling::Interpreter &interp)
Return false if the class does not have ClassDef even-though it should.
bool NeedsSelection(const char *name)
int extractMultipleOptions(std::vector< ROOT::option::Option > &options, int oIndex, std::vector< std::string > &values)
Extract from options multiple values with the same option.
int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
cling::Interpreter *(* fTCling__GetInterpreter)()
bool(* fCloseStreamerInfoROOTFile)(bool writeEmptyRootPCM)
void(* fAddEnumToROOTFile)(const char *tdname)
void(* fInitializeStreamerInfoROOTFile)(const char *filename)
const char *(* fTROOT__GetIncludeDir)()
void(* fAddTypedefToROOTFile)(const char *tdname)
const char *(* fTROOT__GetEtcDir)()
void(* fAddStreamerInfoToROOTFile)(const char *normName)
const char ***(* fTROOT__GetExtraInterpreterArgs)()
static ArgStatus None(const Option &, bool)
For options that don't take an argument: Returns ARG_NONE.
Describes an option, its help text (usage) and how it should be parsed.
static option::ArgStatus Required(const option::Option &option, bool msg)
Determines the minimum lengths of the buffer and options arrays used for Parser.
unsigned options_max
Number of elements needed for an options[] array to be used for parsing the same argument vectors tha...
unsigned buffer_max
Number of elements needed for a buffer[] array to be used for parsing the same argument vectors that ...
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.