12#include "rootclingCommandLineOptionsHelp.h"
14#include "RConfigure.h"
32#include <unordered_map>
33#include <unordered_set>
45#define PATH_MAX _MAX_PATH
53#include <mach-o/dyld.h>
61#include <libprocstat.h>
70#include "cling/Interpreter/Interpreter.h"
71#include "cling/Interpreter/InterpreterCallbacks.h"
72#include "cling/Interpreter/LookupHelper.h"
73#include "cling/Interpreter/Value.h"
74#include "clang/AST/CXXInheritance.h"
75#include "clang/Basic/Diagnostic.h"
76#include "clang/Frontend/CompilerInstance.h"
77#include "clang/Frontend/FrontendActions.h"
78#include "clang/Frontend/FrontendDiagnostic.h"
79#include "clang/Lex/HeaderSearch.h"
80#include "clang/Lex/Preprocessor.h"
81#include "clang/Lex/ModuleMap.h"
82#include "clang/Lex/Pragma.h"
83#include "clang/Sema/Sema.h"
84#include "clang/Serialization/ASTWriter.h"
85#include "cling/Utils/AST.h"
87#include "llvm/ADT/StringRef.h"
89#include "llvm/Support/CommandLine.h"
90#include "llvm/Support/Path.h"
91#include "llvm/Support/PrettyStackTrace.h"
92#include "llvm/Support/Signals.h"
106#include "OptionParser.h"
116#include <mach-o/dyld.h>
121#define strcasecmp _stricmp
122#define strncasecmp _strnicmp
130#define rootclingStringify(s) rootclingStringifyx(s)
131#define rootclingStringifyx(s) #s
138using std::string, std::map, std::ifstream, std::ofstream, std::endl, std::ios, std::vector;
155static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
159 for (
const auto td : tdvec)
162static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
166 for (
const auto en : enumvec) {
168 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
169 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
170 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
180 static std::string exepath;
183 exepath = _dyld_get_image_name(0);
185#if defined(__linux) || defined(__linux__)
186 char linkname[PATH_MAX];
192 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
193 int ret = readlink(linkname, buf, 1024);
194 if (ret > 0 && ret < 1024) {
200 procstat* ps = procstat_open_sysctl();
201 kinfo_proc* kp = kinfo_getproc(getpid());
204 char path_str[PATH_MAX] =
"";
205 procstat_getpathname(ps, kp, path_str,
sizeof(path_str));
213 char *buf =
new char[MAX_MODULE_NAME32 + 1];
214 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
216 while ((
p = strchr(
p,
'\\')))
222 return exepath.c_str();
228 const cling::Interpreter &interp)
236 const std::list<VariableSelectionRule> &fieldSelRules)
244 if (fieldSelRules.empty())
return;
246 clang::ASTContext &C = decl.getASTContext();
248 const std::string declName(decl.getNameAsString());
250 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
251 it != fieldSelRules.end(); ++it) {
252 if (! it->GetAttributeValue(propNames::name, varName))
continue;
253 if (declName == varName) {
256 BaseSelectionRule::AttributesMap_t::iterator iter;
257 std::string userDefinedProperty;
258 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
259 const std::string &
name = iter->first;
260 const std::string &
value = iter->second;
262 if (
name == propNames::name)
continue;
267 if (
name == propNames::iotype &&
268 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
269 const char *msg =
"Data member \"%s\" is an array or a pointer. "
270 "It is not possible to assign to it the iotype \"%s\". "
271 "This transformation is possible only with data members "
272 "which are not pointers or arrays.\n";
274 msg, varName.c_str(),
value.c_str());
282 if (
name == propNames::comment) {
283 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
value,
nullptr, 0));
287 if ((
name == propNames::transient &&
value ==
"true") ||
288 (
name == propNames::persistent &&
value ==
"false")) {
289 userDefinedProperty = propNames::comment + propNames::separator +
"!";
293 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
"!",
nullptr, 0));
298 userDefinedProperty =
name + propNames::separator +
value;
301 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
311 cling::Interpreter &interpreter,
319 using namespace clang;
320 SourceLocation commentSLoc;
321 llvm::StringRef comment;
323 ASTContext &C = CXXRD.getASTContext();
326 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
327 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
328 if (declSelRulePair == declSelRulesMap.end()){
329 const std::string thisClassName(CXXRD.getName());
330 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
335 if (thisClassBaseSelectionRule) {
338 BaseSelectionRule::AttributesMap_t::iterator iter;
339 std::string userDefinedProperty;
340 for (
auto const &
attr : thisClassBaseSelectionRule->GetAttributes()) {
341 const std::string &
name =
attr.first;
346 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
353 for (CXXRecordDecl::decl_iterator I = CXXRD.decls_begin(),
354 E = CXXRD.decls_end(); I != E; ++I) {
358 if (!(*I)->isImplicit()
359 && (isa<CXXMethodDecl>(*I) || isa<FieldDecl>(*I) || isa<VarDecl>(*I))) {
363 if (isClassDefMacro) {
364 while (isa<NamedDecl>(*I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
370 if (comment.size()) {
372 if (isClassDefMacro) {
373 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
374 }
else if (!isGenreflex) {
380 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
385 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
386 const std::list<VariableSelectionRule> &fieldSelRules = thisClassSelectionRule->GetFieldSelectionRules();
389 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*I)) {
403 llvm::APInt
len = arrayType->getSize();
404 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
405 len *= subArrayType->getSize();
406 arrayType = subArrayType;
408 return len.getLimitedValue();
414 const cling::Interpreter &interp)
416 static const clang::CXXRecordDecl *TObject_decl
419 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
426 const cling::Interpreter &interp)
428 static const clang::CXXRecordDecl *TObject_decl
441 return (0 == strcasecmp(
filename + (
len - xmllen),
".xml"));
465 const char *expectedTokens[],
466 size_t *end =
nullptr)
469 if (
line[0] !=
'#')
return false;
471 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
472 while (isspace(
line[pos])) ++pos;
473 size_t lenToken = strlen(*iToken);
474 if (
line.compare(pos, lenToken, *iToken)) {
493 if (recordDecl->hasOwningModule()) {
494 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
497 std::string qual_name;
503 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
512 if (classname.find(
':') == std::string::npos)
return;
515 int slen = classname.size();
516 for (
int k = 0; k < slen; ++k) {
517 if (classname[k] ==
':') {
518 if (k + 1 >= slen || classname[k + 1] !=
':') {
523 string base = classname.substr(0, k);
528 autoloads[base] =
"";
532 }
else if (classname[k] ==
'<') {
544 std::string classname;
546 while (file >>
line) {
548 if (
line.find(
"Library.") != 0)
continue;
550 int pos =
line.find(
":", 8);
551 classname =
line.substr(8, pos - 8);
556 getline(file,
line,
'\n');
557 while (
line[0] ==
' ')
line.replace(0, 1,
"");
561 if (classname ==
"ROOT::TImpProxy") {
565 autoloads[classname] =
line;
580 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
582 while (getline(file,
line,
'\n')) {
583 if (
line ==
"{ decls }") {
584 while (getline(file,
line,
'\n')) {
585 if (
line[0] ==
'[')
break;
588 const char firstChar =
line[0];
589 if (firstChar ==
'[') {
591 libs =
line.substr(1,
line.find(
']') - 1);
592 while (libs[0] ==
' ') libs.replace(0, 1,
"");
593 }
else if (0 != keyLenMap.count(firstChar)) {
594 unsigned int keyLen = keyLenMap.at(firstChar);
595 keyname =
line.substr(keyLen,
line.length() - keyLen);
597 autoloads[keyname] = libs;
607void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
609 std::ifstream filelist(fileListName.c_str());
616 if (llvm::sys::fs::is_directory(
filename))
continue;
622 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
624 file.seekg(0, std::ios::beg);
645 const string &fullname,
646 const clang::RecordDecl *cl,
647 cling::Interpreter &interp)
650 const clang::FunctionDecl *method
655 clang::TranslationUnitDecl *TU =
656 cl->getASTContext().getTranslationUnitDecl();
660 bool has_input_error =
false;
661 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
663 if (strstr(
filename.c_str(),
"TBuffer.h") !=
nullptr ||
664 strstr(
filename.c_str(),
"Rtypes.h") !=
nullptr) {
666 has_input_error =
true;
669 has_input_error =
true;
671 if (has_input_error) {
673 const char *maybeconst =
"";
674 const char *mayberef =
"&";
675 if (
what[strlen(
what) - 1] ==
'<') {
676 maybeconst =
"const ";
680 "in this version of ROOT, the option '!' used in a linkdef file\n"
681 " implies the actual existence of customized operators.\n"
682 " The following declaration is now required:\n"
683 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
685 return has_input_error;
697 int ncha = fullname.length() + 13;
698 char *proto =
new char[ncha];
699 snprintf(proto, ncha,
"TBuffer&,%s*&", fullname.c_str());
706 has_input_error =
CheckInputOperator(
"operator<<", proto, fullname, cl, interp) || has_input_error;
710 return has_input_error;
716bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
722 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
726 bool isAbstract = clxx->isAbstract();
729 std::string qualName;
731 const char *qualName_c = qualName.c_str();
733 "because it inherits from TObject but does not "
734 "have its own ClassDef.\n",
747 if (
m.getType().isConstQualified()) {
748 string ret =
"const_cast< ";
751 if (type_name.substr(0,6)==
"const ") {
752 ret += type_name.c_str()+6;
758 ret +=
m.getName().str();
762 return prefix +
m.getName().str();
772 const cling::Interpreter &interp,
774 std::ostream &dictStream)
777 std::string mTypename;
790 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
792 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
793 if (!tmplt_specialization)
return 0;
799 string fulName1, fulName2;
800 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
801 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
802 clang::QualType ti = arg0.getAsType();
806 fulName1 = ti.getAsString();
809 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
810 clang::QualType tmplti = arg1.getAsType();
813 fulName2 = tmplti.getAsString();
820 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
826 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
830 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
832 }
else if (
m.getType()->isPointerType()) {
837 dictStream <<
" {" << std::endl;
839 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
844 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
847 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
850 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
851 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
852 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
855 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
856 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
857 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
861 dictStream <<
" R__stl.clear();" << std::endl;
864 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
865 <<
" if (R__tcl1==0) {" << std::endl
866 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
867 << fulName1.c_str() <<
"!\");" << std::endl
868 <<
" return;" << std::endl
869 <<
" }" << std::endl;
872 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
873 <<
" if (R__tcl2==0) {" << std::endl
874 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
875 << fulName2.c_str() <<
"!\");" << std::endl
876 <<
" return;" << std::endl
877 <<
" }" << std::endl;
880 dictStream <<
" int R__i, R__n;" << std::endl
881 <<
" R__b >> R__n;" << std::endl;
884 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
886 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
890 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
910 std::string keyName(ti.getAsString());
911 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
912 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
913 <<
" R__stl.insert(R__t3);" << std::endl;
921 dictStream <<
" R__stl.insert(R__t);" << std::endl;
926 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
929 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
934 dictStream <<
" }" << std::endl
935 <<
" }" << std::endl;
936 if (isArr) dictStream <<
" }" << std::endl;
942 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
944 dictStream <<
" {" << std::endl;
947 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
950 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
953 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
956 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
960 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
961 <<
" R__b << R__n;" << std::endl
962 <<
" if(R__n) {" << std::endl;
965 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
966 <<
" if (R__tcl1==0) {" << std::endl
967 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
968 << fulName1.c_str() <<
"!\");" << std::endl
969 <<
" return;" << std::endl
970 <<
" }" << std::endl;
973 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
974 <<
" if (R__tcl2==0) {" << std::endl
975 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
976 <<
" return;" << std::endl
977 <<
" }" << std::endl;
980 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
981 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
983 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
984 clang::QualType tmplti = arg1.getAsType();
991 dictStream <<
" }" << std::endl
993 <<
" }" << std::endl;
994 if (isArr) dictStream <<
" }" << std::endl;
1006 std::string mTypenameStr;
1010 if (!strcmp(mTypeName,
"string")) {
1012 std::string fieldname =
m.getName().str();
1015 if (
m.getType()->isConstantArrayType()) {
1016 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1017 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1019 std::stringstream fullIdx;
1020 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1023 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1024 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1025 fullIdx <<
"[R__i" << dim <<
"]";
1026 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1029 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1030 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1033 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1034 if (
m.getType()->isPointerType())
1035 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1036 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1038 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1042 if (
m.getType()->isPointerType())
1043 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1044 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1045 else if (
m.getType()->isConstantArrayType()) {
1046 std::stringstream fullIdx;
1047 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1050 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1051 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1052 fullIdx <<
"[R__i" << dim <<
"]";
1053 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1056 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1058 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1069 if (
m.getType()->isPointerType()) {
1070 if (
m.getType()->getPointeeType()->isPointerType()) {
1082 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1084 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1086 dictStream <<
"[0]";
1087 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1102 int enclSpaceNesting = 0;
1109 dictStream <<
"#include \"TInterpreter.h\"\n";
1111 dictStream <<
"//_______________________________________"
1112 <<
"_______________________________________" << std::endl;
1113 if (add_template_keyword) dictStream <<
"template <> ";
1114 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1117 <<
"//_______________________________________"
1118 <<
"_______________________________________" << std::endl;
1119 if (add_template_keyword) dictStream <<
"template <> ";
1120 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1121 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1123 dictStream <<
"//_______________________________________"
1124 <<
"_______________________________________" << std::endl;
1125 if (add_template_keyword) dictStream <<
"template <> ";
1126 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1127 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1128 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1130 <<
"//_______________________________________"
1131 <<
"_______________________________________" << std::endl;
1132 if (add_template_keyword) dictStream <<
"template <> ";
1133 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1134 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1135 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1137 <<
"//_______________________________________"
1138 <<
"_______________________________________" << std::endl;
1139 if (add_template_keyword) dictStream <<
"template <> ";
1140 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1144 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1145 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1146 <<
"*)nullptr)->GetClass();" << std::endl
1147 <<
" return fgIsA;\n"
1148 <<
"}" << std::endl << std::endl
1150 <<
"//_______________________________________"
1151 <<
"_______________________________________" << std::endl;
1152 if (add_template_keyword) dictStream <<
"template <> ";
1153 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1155 dictStream <<
" Dictionary();\n";
1157 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1158 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1160 dictStream <<
" return fgIsA;" << std::endl
1161 <<
"}" << std::endl << std::endl;
1163 while (enclSpaceNesting) {
1164 dictStream <<
"} // namespace " << nsname << std::endl;
1173 cling::Interpreter &interp,
1174 std::ostream &dictStream)
1176 if (cl->isAnonymousNamespace()) {
1188 if (classname !=
"ROOT") {
1192 dictStream <<
" namespace ROOTDict {" << std::endl;
1194 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1197 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1198 dictStream << std::endl
1200 <<
" // Function generating the singleton type initializer" << std::endl
1202 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1203 <<
" {" << std::endl
1205 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1207 <<
" instance(\"" << classname.c_str() <<
"\", ";
1210 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1212 dictStream <<
"0 /*version*/, ";
1216 for (
unsigned int i = 0; i <
filename.length(); i++) {
1220 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1224 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1226 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1229 dictStream << 0 <<
");" << std::endl
1231 <<
" return &instance;" << std::endl
1232 <<
" }" << std::endl
1233 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1234 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1235 <<
" // Static variable to force the class initialization" << std::endl
1237 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1238 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1241 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1242 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1243 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1244 <<
" }" << std::endl << std::endl;
1247 dictStream <<
" }" << std::endl;
1249 dictStream <<
"}" << std::endl;
1251 dictStream << std::endl;
1260llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1263 llvm::StringRef where;
1266 if (
index.size() == 0 && printError) {
1267 const char *errorstring;
1270 errorstring =
"is not an integer";
1273 errorstring =
"has not been defined before the array";
1276 errorstring =
"is a private member of a parent class";
1279 errorstring =
"is not known";
1282 errorstring =
"UNKNOWN ERROR!!!!";
1285 if (where.size() == 0) {
1287 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1290 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1299 const cling::Interpreter &interp,
1301 std::ostream &dictStream)
1303 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1304 if (clxx ==
nullptr)
return;
1311 int enclSpaceNesting = 0;
1317 dictStream <<
"//_______________________________________"
1318 <<
"_______________________________________" << std::endl;
1319 if (add_template_keyword) dictStream <<
"template <> ";
1320 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1321 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1329 int basestreamer = 0;
1330 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1334 string base_fullname;
1337 if (strstr(base_fullname.c_str(),
"::")) {
1339 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1340 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1341 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1343 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1348 if (!basestreamer) {
1349 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1350 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1352 dictStream <<
"}" << std::endl << std::endl;
1353 while (enclSpaceNesting) {
1354 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1361 string classname = fullname;
1362 if (strstr(fullname.c_str(),
"::")) {
1364 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1365 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1366 classname =
"thisClass";
1368 for (
int i = 0; i < 2; i++) {
1373 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1374 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1375 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1377 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1378 dictStream <<
" } else {" << std::endl;
1379 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1384 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1388 string base_fullname;
1391 if (strstr(base_fullname.c_str(),
"::")) {
1393 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1394 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1395 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1398 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1404 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1409 clang::QualType
type = field_iter->getType();
1410 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1420 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1424 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1427 if (strncmp(comment,
"!", 1)) {
1430 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1431 if (
type.getTypePtr()->isConstantArrayType() &&
1432 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1433 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1437 dictStream <<
" int R__i;" << std::endl;
1440 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1442 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());
1443 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1445 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1447 }
else if (
type.getTypePtr()->isPointerType()) {
1448 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1449 if (indexvar.size() == 0) {
1451 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1452 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1454 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1458 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1463 <<
"," << indexvar.str() <<
");" << std::endl;
1464 }
else if (isDouble32) {
1466 <<
"," << indexvar.str() <<
");" << std::endl;
1469 <<
"," << indexvar.str() <<
");" << std::endl;
1473 dictStream <<
" R__b.WriteFastArrayFloat16("
1474 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1475 }
else if (isDouble32) {
1476 dictStream <<
" R__b.WriteFastArrayDouble32("
1477 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1479 dictStream <<
" R__b.WriteFastArray("
1480 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1484 }
else if (
type.getTypePtr()->isArrayType()) {
1486 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1487 if (underling_type->isEnumeralType())
1488 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1492 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1493 }
else if (isDouble32) {
1495 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1498 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1502 if (underling_type->isEnumeralType()) {
1503 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1506 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1507 }
else if (isDouble32) {
1508 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1511 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1516 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1519 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1520 if (underling_type->isEnumeralType())
1521 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1522 << s <<
");" << std::endl;
1523 else if (isFloat16) {
1525 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1526 }
else if (isDouble32) {
1528 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1531 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1534 if (underling_type->isEnumeralType())
1535 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1536 else if (isFloat16) {
1537 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1538 }
else if (isDouble32) {
1539 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1541 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1545 }
else if (underling_type->isEnumeralType()) {
1547 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1548 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1550 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1555 <<
"=Float16_t(R_Dummy);}" << std::endl;
1558 }
else if (isDouble32) {
1561 <<
"=Double32_t(R_Dummy);}" << std::endl;
1583 if (
type.getTypePtr()->isConstantArrayType() &&
1584 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1585 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1589 dictStream <<
" int R__i;" << std::endl;
1592 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1597 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1602 dictStream <<
"[R__i];" << std::endl;
1603 }
else if (
type.getTypePtr()->isPointerType()) {
1611 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1612 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1614 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1618 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1632 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1638 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1642 dictStream <<
" int R__i;" << std::endl;
1645 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1646 std::string mTypeNameStr;
1648 const char *mTypeName = mTypeNameStr.c_str();
1649 const char *constwd =
"const ";
1650 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1651 mTypeName += strlen(constwd);
1652 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1654 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1658 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1664 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1665 << field_iter->getName().str() <<
"));" << std::endl;
1676 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1677 <<
" }" << std::endl
1678 <<
"}" << std::endl << std::endl;
1680 while (enclSpaceNesting) {
1681 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1689 const cling::Interpreter &interp,
1691 std::ostream &dictStream)
1695 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1696 if (clxx ==
nullptr)
return;
1701 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1713 int enclSpaceNesting = 0;
1719 dictStream <<
"//_______________________________________"
1720 <<
"_______________________________________" << std::endl;
1721 if (add_template_keyword) dictStream <<
"template <> ";
1722 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1724 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1725 <<
" if (R__b.IsReading()) {" << std::endl
1726 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1727 <<
" } else {" << std::endl
1728 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1729 <<
" }" << std::endl
1730 <<
"}" << std::endl << std::endl;
1732 while (enclSpaceNesting) {
1733 dictStream <<
"} // namespace " << nsname << std::endl;
1741 const cling::Interpreter &interp,
1743 std::ostream &dictStream,
1744 bool isAutoStreamer)
1746 if (isAutoStreamer) {
1758bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1763 static const char *fopenopts =
"rb";
1765 static const char *fopenopts =
"r";
1769 fp = fopen(pname.c_str(), fopenopts);
1775 llvm::SmallVector<std::string, 10> includePaths;
1777 interp.GetIncludePaths(includePaths,
false,
false);
1779 const size_t nPaths = includePaths.size();
1780 for (
size_t i = 0; i < nPaths; i += 1 ) {
1784 fp = fopen(pname.c_str(), fopenopts);
1806 const char *inc = strstr(original,
"\\inc\\");
1808 inc = strstr(original,
"/inc/");
1809 if (inc && strlen(inc) > 5)
1829 cling::Interpreter &interp,
1832 std::ostringstream out;
1836 modGen.WriteUmbrellaHeader(out);
1837 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1838 const std::string &hdrName
1839 = umbrella ? modGen.GetUmbrellaName() : modGen.GetContentName();
1845 modGen.WriteContentHeader(out);
1856static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
1857 llvm::StringRef iSysRoot,
1858 clang::Module *module =
nullptr)
1861 llvm::SmallVector<char, 128> buffer;
1862 llvm::BitstreamWriter stream(buffer);
1863 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), compilerInstance->getCodeGenOpts(), {});
1864 std::unique_ptr<llvm::raw_ostream> out =
1865 compilerInstance->createOutputFile(fileName,
true,
1874 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
1876 writer.WriteAST(&compilerInstance->getSema(), fileName.str(), module, iSysRoot);
1879 out->write(&buffer.front(), buffer.size());
1891 const std::string ¤tDirectory)
1893 assert(modGen.IsPCH() &&
"modGen must be in PCH mode");
1895 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
1897 return WriteAST(modGen.GetModuleFileName(), compilerInstance, iSysRoot);
1903static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
1906 if (headers.empty())
1910 std::stringstream includes;
1911 for (
const std::string &header : headers) {
1912 includes <<
"#include \"" << header <<
"\"\n";
1914 std::string includeListStr = includes.str();
1915 auto result = interpreter.declare(includeListStr);
1916 return result == cling::Interpreter::CompilationResult::kSuccess;
1924 char platformDefines[64] = {0};
1925#ifdef __INTEL_COMPILER
1926 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
1927 clingArgs.push_back(platformDefines);
1930 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
1931 clingArgs.push_back(platformDefines);
1934 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
1935 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
1936 clingArgs.push_back(platformDefines);
1938#ifdef __GNUC_MINOR__
1939 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
1940 clingArgs.push_back(platformDefines);
1943 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
1944 clingArgs.push_back(platformDefines);
1947 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
1948 clingArgs.push_back(platformDefines);
1951 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
1952 clingArgs.push_back(platformDefines);
1954#ifdef _STLPORT_VERSION
1956 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
1957 clingArgs.push_back(platformDefines);
1960 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
1961 clingArgs.push_back(platformDefines);
1964 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
1965 clingArgs.push_back(platformDefines);
1968 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
1969 clingArgs.push_back(platformDefines);
1972 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
1973 clingArgs.push_back(platformDefines);
1976 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
1977 clingArgs.push_back(platformDefines);
1980 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
1981 clingArgs.push_back(platformDefines);
1985 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
1986 clingArgs.push_back(platformDefines);
1989 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
1990 clingArgs.push_back(platformDefines);
1991 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
1992 clingArgs.push_back(platformDefines);
2001 return llvm::sys::path::filename(path).str();
2011 if (std::string::npos != pos) {
2012 dirname.assign(path.begin(), path.begin() + pos + 1);
2023 std::string dictLocation;
2025 return !dictLocation.empty();
2031 std::string &rootmapLibName)
2035 if (rootmapFileName.empty()) {
2037 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2038 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2039 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2041 rootmapLibName.c_str(),
2042 rootmapFileName.c_str());
2051 std::string &ctxtName,
2052 const cling::Interpreter &interpreter,
2053 bool treatParent =
true)
2055 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2057 if (!outerCtxt)
return;
2059 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2069 std::string &ctxtName,
2070 const cling::Interpreter &interpreter)
2072 const clang::DeclContext *theContext = theDecl.getDeclContext();
2080 const cling::Interpreter &interp)
2082 if (!decls.empty()) {
2083 std::string autoLoadKey;
2084 for (
auto &
d : decls) {
2088 if (autoLoadKey.empty()) {
2089 names.push_back(
d->getQualifiedNameAsString());
2107 const std::string &rootmapLibName,
2108 const std::list<std::string> &classesDefsList,
2109 const std::list<std::string> &classesNames,
2110 const std::list<std::string> &nsNames,
2111 const std::list<std::string> &tdNames,
2112 const std::list<std::string> &enNames,
2113 const std::list<std::string> &varNames,
2115 const std::unordered_set<std::string> headersToIgnore)
2118 std::ofstream rootmapFile(rootmapFileName.c_str());
2126 std::unordered_set<std::string> classesKeys;
2130 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2131 !enNames.empty() || !varNames.empty()) {
2134 if (!classesDefsList.empty()) {
2135 rootmapFile <<
"{ decls }\n";
2136 for (
auto & classDef : classesDefsList) {
2137 rootmapFile << classDef << std::endl;
2139 rootmapFile <<
"\n";
2141 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2144 if (!classesNames.empty()) {
2145 rootmapFile <<
"# List of selected classes\n";
2146 for (
auto & className : classesNames) {
2147 rootmapFile <<
"class " << className << std::endl;
2148 classesKeys.insert(className);
2151 std::unordered_set<std::string> treatedHeaders;
2152 for (
auto & className : classesNames) {
2154 if (className.find(
"<") != std::string::npos)
continue;
2155 if (headersClassesMap.count(className)) {
2156 auto &headers = headersClassesMap.at(className);
2157 if (!headers.empty()){
2158 auto &header = headers.front();
2159 if (treatedHeaders.insert(header).second &&
2160 headersToIgnore.find(header) == headersToIgnore.end() &&
2162 rootmapFile <<
"header " << header << std::endl;
2170 if (!nsNames.empty()) {
2171 rootmapFile <<
"# List of selected namespaces\n";
2172 for (
auto & nsName : nsNames) {
2173 rootmapFile <<
"namespace " << nsName << std::endl;
2178 if (!tdNames.empty()) {
2179 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2180 for (
const auto & autoloadKey : tdNames)
2181 if (classesKeys.insert(autoloadKey).second)
2182 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2187 if (!enNames.empty()){
2188 rootmapFile <<
"# List of selected enums and outer classes\n";
2189 for (
const auto & autoloadKey : enNames)
2190 if (classesKeys.insert(autoloadKey).second)
2191 rootmapFile <<
"enum " << autoloadKey << std::endl;
2195 if (!varNames.empty()){
2196 rootmapFile <<
"# List of selected vars\n";
2197 for (
const auto & autoloadKey : varNames)
2198 if (classesKeys.insert(autoloadKey).second)
2199 rootmapFile <<
"var " << autoloadKey << std::endl;
2213 auto nsPattern =
'{';
auto nsPatternLength = 1;
2214 auto foundNsPos =
line.find_last_of(nsPattern);
2215 if (foundNsPos == std::string::npos)
return {
"",
""};
2216 foundNsPos+=nsPatternLength;
2217 auto extNs =
line.substr(0,foundNsPos);
2219 auto nsEndPattern =
'}';
2220 auto foundEndNsPos =
line.find(nsEndPattern);
2221 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2223 return {extNs, contained};
2239 std::map<std::string, std::string> nsEntitiesMap;
2240 std::list<std::string> optFwdDeclList;
2241 for (
auto const & fwdDecl : fwdDeclarationsList){
2244 if (extNsAndEntities.first.empty()) {
2246 optFwdDeclList.push_front(fwdDecl);
2248 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2249 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2253 std::string optFwdDecl;
2254 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2255 optFwdDecl = extNsAndEntities.first;
2256 optFwdDecl += extNsAndEntities.second;
2257 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2260 optFwdDeclList.push_front(optFwdDecl);
2263 return optFwdDeclList;
2271 std::list<std::string> &el_list,
2272 std::unordered_set<std::string> &el_set)
2274 std::stringstream elStream(el);
2277 while (getline(elStream, tmp,
'\n')) {
2279 if (el_set.insert(tmp).second && !tmp.empty()) {
2280 el_list.push_back(tmp);
2291 std::list<std::string> &classesList,
2292 std::list<std::string> &classesListForRootmap,
2293 std::list<std::string> &fwdDeclarationsList,
2294 const cling::Interpreter &interpreter)
2302 std::unordered_set<std::string> classesSet;
2303 std::unordered_set<std::string> outerMostClassesSet;
2305 std::string attrName, attrValue;
2306 bool isClassSelected;
2307 std::unordered_set<std::string> availableFwdDecls;
2308 std::string fwdDeclaration;
2310 fwdDeclaration =
"";
2316 fwdDeclaration =
"";
2323 isClassSelected =
true;
2324 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2325 std::string normalizedName;
2326 normalizedName = selClass.GetNormalizedName();
2327 if (!normalizedName.empty() &&
2328 !classesSet.insert(normalizedName).second &&
2329 outerMostClassesSet.count(normalizedName) == 0) {
2330 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2331 <<
" was already selected. This means that two different instances of"
2332 <<
" clang::RecordDecl had the same name, which is not possible."
2333 <<
" This can be a hint of a serious problem in the class selection."
2334 <<
" In addition, the generated dictionary would not even compile.\n";
2337 classesList.push_back(normalizedName);
2340 const char *reqName(selClass.GetRequestedName());
2343 fwdDeclaration =
"";
2348 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2349 fwdDeclaration =
"";
2352 std::string fwdDeclarationTemplateSpec;
2354 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2362 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2364 attrName ==
"rootmap" &&
2365 attrValue ==
"false") {
2366 attrName = attrValue =
"";
2367 isClassSelected =
false;
2371 if (isClassSelected) {
2387 std::string outerMostClassName;
2389 if (!outerMostClassName.empty() &&
2390 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2391 classesSet.insert(outerMostClassName).second &&
2392 outerMostClassesSet.insert(outerMostClassName).second) {
2393 classesListForRootmap.push_back(outerMostClassName);
2395 classesListForRootmap.push_back(normalizedName);
2396 if (reqName && reqName[0] && reqName != normalizedName) {
2397 classesListForRootmap.push_back(reqName);
2402 std::string demangledName = selClass.GetDemangledTypeInfo();
2403 if (!demangledName.empty()) {
2408 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2410 classesListForRootmap.push_back(demangledName);
2416 classesListForRootmap.sort();
2429 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2444 if (clang::CXXRecordDecl *CXXRD =
2445 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2457 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2460 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2463 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2479 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2480 "#include \"TFile.h\"\n"
2481 "#include \"TObjArray.h\"\n"
2482 "#include \"TVirtualArray.h\"\n"
2483 "#include \"TStreamerElement.h\"\n"
2484 "#include \"TProtoClass.h\"\n"
2485 "#include \"TBaseClass.h\"\n"
2486 "#include \"TListOfDataMembers.h\"\n"
2487 "#include \"TListOfEnums.h\"\n"
2488 "#include \"TListOfEnumsWithLock.h\"\n"
2489 "#include \"TDataMember.h\"\n"
2490 "#include \"TEnum.h\"\n"
2491 "#include \"TEnumConstant.h\"\n"
2492 "#include \"TDictAttributeMap.h\"\n"
2493 "#include \"TMessageHandler.h\"\n"
2494 "#include \"TArray.h\"\n"
2495 "#include \"TRefArray.h\"\n"
2496 "#include \"root_std_complex.h\"\n")
2497 != cling::Interpreter::kSuccess)
2509 bool isSelXML,
bool writeEmptyRootPCM)
2513 bool needsCollectionProxy =
false;
2533 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2534 if (nsName.find(
"(anonymous)") == std::string::npos)
2539 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2543 if (selClass.RequestOnlyTClass()) {
2551 if (clang::CXXRecordDecl *CXXRD =
2552 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2556 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2564 }
else if (CRD->getName() ==
"RVec") {
2565 static const clang::DeclContext *vecOpsDC =
nullptr;
2567 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2568 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2569 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2576 needsCollectionProxy);
2590 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2594 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2606 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2610 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2614 needsCollectionProxy);
2635 std::vector<std::string> standaloneTargets;
2646 if (finRetCode != 0)
return finRetCode;
2656 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2657 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2660 <<
"#define R__NO_DEPRECATION" << std::endl
2665 <<
"\n/*******************************************************************/\n"
2666 <<
"#include <cstddef>\n"
2667 <<
"#include <cstdio>\n"
2668 <<
"#include <cstdlib>\n"
2669 <<
"#include <cstring>\n"
2670 <<
"#include <cassert>\n"
2671 <<
"#define G__DICTIONARY\n"
2672 <<
"#include \"ROOT/RConfig.hxx\"\n"
2673 <<
"#include \"TClass.h\"\n"
2674 <<
"#include \"TDictAttributeMap.h\"\n"
2675 <<
"#include \"TInterpreter.h\"\n"
2676 <<
"#include \"TROOT.h\"\n"
2677 <<
"#include \"TBuffer.h\"\n"
2678 <<
"#include \"TMemberInspector.h\"\n"
2679 <<
"#include \"TInterpreter.h\"\n"
2680 <<
"#include \"TVirtualMutex.h\"\n"
2681 <<
"#include \"TError.h\"\n\n"
2682 <<
"#ifndef G__ROOT\n"
2683 <<
"#define G__ROOT\n"
2685 <<
"#include \"RtypesImp.h\"\n"
2686 <<
"#include \"TIsAProxy.h\"\n"
2687 <<
"#include \"TFileMergeInfo.h\"\n"
2688 <<
"#include <algorithm>\n"
2689 <<
"#include \"TCollectionProxyInfo.h\"\n"
2690 <<
"/*******************************************************************/\n\n"
2691 <<
"#include \"TDataMember.h\"\n\n";
2698 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2699 <<
"namespace std {} using namespace std;\n\n";
2705 const std::string &includeForSource,
2706 const std::string &extraIncludes)
2708 dictStream <<
"// Header files passed as explicit arguments\n"
2709 << includeForSource << std::endl
2710 <<
"// Header files passed via #pragma extra_include\n"
2711 << extraIncludes << std::endl;
2717#if defined(R__IOSSIM) || defined(R__IOS)
2742 return filename +
"_tmp_" + std::to_string(getpid());
2749 if (nameStr.empty())
return;
2754 const char *
name(nameStr.c_str());
2755 const char *tmpName(tmpNameStr.c_str());
2762 if (0 == std::rename(
name , tmpName)) {
2767 nameStr = tmpNameStr;
2778 for (
unsigned int i = 0; i <
m_size; ++i) {
2781 std::ifstream ifile(tmpName);
2786 if (ifile.is_open())
2788 if (0 != std::remove(tmpName)) {
2801 for (
unsigned int i = 0; i <
m_size; ++i) {
2805 std::ifstream ifile(tmpName);
2810 if (ifile.is_open())
2816 if (0 != std::rename(tmpName ,
name)) {
2817 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2818 llvm::sys::fs::remove(tmpName);
2822 if (0 != std::rename(tmpName ,
name)) {
2843 std::cout <<
"Restoring files in temporary file catalog:\n";
2844 for (
unsigned int i = 0; i <
m_size; ++i) {
2862 std::string splitDictName(tmpCatalog.getFileName(dictpathname));
2863 const size_t dotPos = splitDictName.find_last_of(
".");
2864 splitDictName.insert(dotPos,
"_classdef");
2865 tmpCatalog.addFileName(splitDictName);
2866 return new std::ofstream(splitDictName.c_str());
2875 std::list<std::string> &diagnosticPragmas)
2877 static const std::string pattern(
"-Wno-");
2879 if (arg.find(pattern) != 0)
2884 diagnosticPragmas.push_back(arg);
2890 cling::Interpreter &interp)
2893 std::string fwdDecl;
2894 std::string initStr(
"{");
2895 auto &fwdDeclnArgsToSkipColl = normCtxt.GetTemplNargsToKeepMap();
2896 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
2897 auto &clTemplDecl = *strigNargsToKeepPair.first;
2898 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
2901 + std::to_string(strigNargsToKeepPair.second)
2904 if (!fwdDeclnArgsToSkipColl.empty())
2915 if (qt.isNull())
return qt;
2916 clang::QualType thisQt(qt);
2917 while (thisQt->isPointerType() ||
2918 thisQt->isReferenceType()) {
2919 thisQt = thisQt->getPointeeType();
2929 const cling::Interpreter &interp,
2930 std::set<const clang::CXXRecordDecl *> &visitedDecls)
2932 std::list<std::string> headers;
2935 cling::Interpreter::PushTransactionRAII RAII(&interp);
2938 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
2942 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
2945 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
2946 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
2948 if (tArgQualType.isNull())
continue;
2949 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
2950 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
2957 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
2959 if (baseQualType.isNull())
continue;
2960 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
2961 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
2966 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
2967 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
2969 if (fieldQualType.isNull()) continue ;
2970 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
2971 if (fieldCxxRcd->hasDefinition())
2972 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
2978 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
2980 for (
auto & fPar : methodIt->parameters()) {
2982 if (fParQualType.isNull())
continue;
2983 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
2984 if (fParCxxRcd->hasDefinition())
2985 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
2990 if (retQualType.isNull())
continue;
2991 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
2992 if (retCxxRcd->hasDefinition())
3001 headers.emplace_back(header);
3014 if (
auto dclCtxt= rcd.getDeclContext()){
3015 if (! dclCtxt->isStdNamespace()){
3024 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3025 if (!clAsTmplSpecDecl)
return false;
3030 auto& astCtxt = rcd.getASTContext();
3031 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3032 for (
auto&& arg : templInstArgs.asArray()){
3034 auto argKind = arg.getKind();
3035 if (argKind != clang::TemplateArgument::Type){
3036 if (argKind == clang::TemplateArgument::Integral)
continue;
3040 auto argQualType = arg.getAsType();
3041 auto isPOD = argQualType.isPODType(astCtxt);
3043 if (isPOD)
continue;
3045 auto argType = argQualType.getTypePtr();
3046 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3049 if (isArgGoodForAutoParseMap)
continue;
3068 const cling::Interpreter &interp)
3070 std::set<const clang::CXXRecordDecl *> visitedDecls;
3071 std::unordered_set<std::string> buffer;
3072 std::string autoParseKey;
3075 for (
auto & annotatedRcd : annotatedRcds) {
3076 if (
const clang::CXXRecordDecl *cxxRcd =
3077 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3079 visitedDecls.clear();
3083 headers.remove_if([&buffer](
const std::string & s) {
3084 return !buffer.insert(s).second;
3087 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3089 headersDeclsMap[autoParseKey] = headers;
3090 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3092 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3097 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3098 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3099 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3105 for (
auto & tDef : tDefDecls) {
3106 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3108 visitedDecls.clear();
3113 headers.remove_if([&buffer](
const std::string & s) {
3114 return !buffer.insert(s).second;
3117 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3118 headersDeclsMap[autoParseKey] = headers;
3123 for (
auto & func : funcDecls) {
3129 for (
auto & var : varDecls) {
3135 for (
auto & en : enumDecls) {
3145 const cling::Interpreter &interp)
3147 std::string newFwdDeclString;
3151 std::string fwdDeclString;
3153 std::unordered_set<std::string> fwdDecls;
3174 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3179 selectedDecls.begin(),
3183 selectedDecls.push_back(TD);
3188 std::string fwdDeclLogs;
3196 std::cout <<
"Logs from forward decl printer: \n"
3213 if (fwdDeclString.empty()) fwdDeclString =
"";
3214 return fwdDeclString;
3221 const std::string &detectedUmbrella,
3222 bool payLoadOnly =
false)
3224 std::string headerName;
3227 std::cout <<
"Class-headers Mapping:\n";
3228 std::string headersClassesMapString =
"";
3229 for (
auto const & classHeaders : headersClassesMap) {
3231 std::cout <<
" o " << classHeaders.first <<
" --> ";
3232 headersClassesMapString +=
"\"";
3233 headersClassesMapString += classHeaders.first +
"\"";
3234 for (
auto const & header : classHeaders.second) {
3235 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3236 headersClassesMapString +=
", " + headerName;
3238 std::cout <<
", " << headerName;
3243 std::cout << std::endl;
3244 headersClassesMapString +=
", \"@\",\n";
3246 headersClassesMapString +=
"nullptr";
3247 return headersClassesMapString;
3270 static const std::vector<std::string> namePrfxes {
3273 auto pos = find_if(namePrfxes.begin(),
3275 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3276 return namePrfxes.end() == pos;
3283 static const std::vector<std::string> uclNamePrfxes {
3287 static const std::set<std::string> unsupportedClassesNormNames{
3290 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3291 auto pos = find_if(uclNamePrfxes.begin(),
3292 uclNamePrfxes.end(),
3293 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3294 return uclNamePrfxes.end() == pos;
3304 for (
auto&& aRcd : annotatedRcds){
3305 auto clName = aRcd.GetNormalizedName();
3307 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3308 <<
"currently the support for its I/O is not yet available. Note that "
3309 << clName <<
", even if not selected, will be available for "
3310 <<
"interpreted code.\n";
3314 std::cerr <<
"Error: It is not necessary to explicitly select class "
3315 << clName <<
". I/O is supported for it transparently.\n";
3330 InterpreterCallbacks(interp),
3336 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3337 clang::OptionalFileEntryRef , llvm::StringRef ,
3338 llvm::StringRef ,
const clang::Module * ,
bool ,
3339 clang::SrcMgr::CharacteristicKind )
override
3342 if (IsAngled)
return;
3343 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3344 auto curLexer = PP.getCurrentFileLexer();
3345 if (!curLexer)
return;
3346 auto fileEntry = curLexer->getFileEntry();
3347 if (!fileEntry)
return;
3348 auto thisFileName = fileEntry->getName();
3349 auto fileNameAsString = FileName.str();
3351 if (isThisLinkdef) {
3353 if (isTheIncludedLinkdef) {
3371 clang::SourceLocation ImportLoc,
3372 bool ForPragma)
override {
3374 using namespace clang;
3375 if (llvm::StringRef(M->Name).ends_with(
"ACLiC_dict")) {
3376 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3377 HeaderSearch& HS = PP.getHeaderSearchInfo();
3379 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3381 assert(M &&
"Must have module Core");
3382 PP.makeModuleVisible(CoreModule, ImportLoc);
3388 llvm::cl::desc(
"Allow implicit build of system modules."),
3390static llvm::cl::list<std::string>
3393 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3396static llvm::cl::opt<std::string>
3398 llvm::cl::desc(
"<output dictionary file>"),
3430 using namespace clang::diag;
3436 std::string moduleName;
3437 const clang::Module *
module = nullptr;
3440 const auto &ID =
Info.getID();
3441 if (ID == remark_module_build || ID == remark_module_build_done) {
3442 moduleName =
Info.getArgStdStr(0);
3443 module = fMap.findModule(moduleName);
3449 "Couldn't find module %s in the available modulemaps. This"
3450 "prevents us from correctly diagnosing wrongly built modules.\n",
3451 moduleName.c_str());
3464 bool isByproductModule =
false;
3468 isByproductModule =
true;
3473 isByproductModule =
true;
3476 if (!isByproductModule)
3479 if (ID == remark_module_build && !isByproductModule) {
3481 "Building module '%s' implicitly. If '%s' requires a \n"
3482 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3483 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3485 moduleName.c_str(), moduleName.c_str());
3493 DiagnosticConsumer::clear();
3496 void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3498 fChild->BeginSourceFile(LangOpts, PP);
3499 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3505 DiagnosticConsumer::EndSourceFile();
3511 DiagnosticConsumer::finish();
3518#if defined(_WIN32) && defined(_MSC_VER)
3522 const char *EnablePopups = std::getenv(
"Cling_GuiOnAssert");
3523 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3524 ::_set_error_mode(_OUT_TO_STDERR);
3525 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3526 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3527 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3528 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3529 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3530 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3535static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3537static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3548static llvm::cl::opt<VerboseLevel>
3550 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3551 clEnumVal(
v0,
"Show only fatal errors."),
3552 clEnumVal(
v1,
"Show errors (the same as -v)."),
3553 clEnumVal(
v2,
"Show warnings (default)."),
3554 clEnumVal(
v3,
"Show notes."),
3555 clEnumVal(
v4,
"Show information.")),
3559static llvm::cl::opt<bool>
3560gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3563static llvm::cl::opt<bool>
3564gOptReflex(
"reflex", llvm::cl::desc(
"Behave internally like genreflex."),
3566static llvm::cl::opt<bool>
3567gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3570static llvm::cl::opt<std::string>
3572 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3575static llvm::cl::opt<bool>
3577 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3580static llvm::cl::opt<bool>
3581gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3583static llvm::cl::opt<bool>
3584gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3586static llvm::cl::list<std::string>
3588 llvm::cl::desc(
"Generate rootmap file."),
3590static llvm::cl::opt<std::string>
3592 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3594static llvm::cl::opt<bool>
3596 llvm::cl::desc(
"Generate a C++ module."),
3598static llvm::cl::list<std::string>
3600 llvm::cl::desc(
"Specify a C++ modulemap file."),
3603static llvm::cl::opt<bool>
3605 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3607static llvm::cl::opt<bool>
3609 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3611static llvm::cl::opt<bool>
3613 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3615static llvm::cl::opt<bool>
3617 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3619static llvm::cl::opt<bool>
3621 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3622information and another the interactivity support."),
3624static llvm::cl::opt<bool>
3627 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3629static llvm::cl::opt<std::string>
3631 llvm::cl::desc(
"The path to the library of the built dictionary."),
3633static llvm::cl::list<std::string>
3635 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3637static llvm::cl::list<std::string>
3639 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3643static llvm::cl::opt<bool>
3645 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3653static llvm::cl::opt<bool>
3656 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3658static llvm::cl::opt<bool>
3660 llvm::cl::desc(
"Check the selection syntax only."),
3662static llvm::cl::opt<bool>
3664 llvm::cl::desc(
"Fail if there are warnings."),
3666static llvm::cl::opt<bool>
3668 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3670static llvm::cl::opt<std::string>
3672 llvm::cl::desc(
"Specify an isysroot."),
3674 llvm::cl::init(
"-"));
3675static llvm::cl::list<std::string>
3677 llvm::cl::desc(
"Specify an include path."),
3679static llvm::cl::list<std::string>
3681 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3683static llvm::cl::list<std::string>
3685 llvm::cl::desc(
"Specify a system include path."),
3687static llvm::cl::list<std::string>
3689 llvm::cl::desc(
"Specify defined macros."),
3691static llvm::cl::list<std::string>
3693 llvm::cl::desc(
"Specify undefined macros."),
3695static llvm::cl::list<std::string>
3697 llvm::cl::desc(
"Specify compiler diagnostics options."),
3699static llvm::cl::opt<std::string>
3701 llvm::cl::desc(
"Write dependency output to the specified file."),
3704static llvm::cl::list<std::string>
3706 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file | selection xml file>"),
3708static llvm::cl::list<std::string>
3710 llvm::cl::desc(
"Consumes all unrecognized options."),
3713static llvm::cl::SubCommand
3716static llvm::cl::list<std::string>
3718 llvm::cl::desc(
"Consumes options and sends them to cling."),
3728 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3731 std::vector<clang::Module::Header> moduleHeaders;
3733 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3735 bool foundAllHeaders =
true;
3737 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3738 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3739 if (header == moduleHeader.NameAsWritten)
3747 for (
const std::string &header : modGen.GetHeaders()) {
3748 if (isHeaderInModule(header))
3751 clang::ModuleMap::KnownHeader SuggestedModule;
3752 clang::ConstSearchDirIterator *CurDir =
nullptr;
3753 if (
auto FE = headerSearch.LookupFile(
3754 header, clang::SourceLocation(),
3757 clang::ArrayRef<std::pair<clang::OptionalFileEntryRef, clang::DirectoryEntryRef>>(),
3760 nullptr, &SuggestedModule,
3767 if (
auto OtherModule = SuggestedModule.getModule()) {
3768 std::string OtherModuleName;
3769 auto TLM = OtherModule->getTopLevelModuleName();
3771 OtherModuleName = TLM.str();
3773 OtherModuleName = OtherModule->Name;
3780 missingHeaders.push_back({header, OtherModuleName});
3783 missingHeaders.push_back({header, {}});
3785 foundAllHeaders =
false;
3787 return foundAllHeaders;
3793 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3795 clang::CompilerInstance *CI = interpreter.getCI();
3796 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3797 headerSearch.loadTopLevelSystemModules();
3800 clang::Module *
module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3805 moduleName.c_str());
3812 std::vector<std::array<std::string, 2>> missingHdrMod;
3815 std::stringstream msgStream;
3816 msgStream <<
"after creating module \"" <<
module->Name << "\" ";
3817 if (!module->PresumedModuleMapFile.empty())
3818 msgStream <<
"using modulemap \"" <<
module->PresumedModuleMapFile << "\" ";
3819 msgStream <<
"the following headers are not part of that module:\n";
3820 for (
auto &H : missingHdrMod) {
3821 msgStream <<
" " << H[0];
3823 msgStream <<
" (already part of module \"" << H[1] <<
"\")";
3826 std::string warningMessage = msgStream.str();
3828 bool maybeUmbrella = modGen.GetHeaders().size() == 1;
3839 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3840 warningMessage.c_str(),
3847 std::vector<std::string> missingHeaders;
3848 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
3849 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
3852 module->Name.c_str());
3862 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
3863 moduleName.consume_front(
"lib");
3864 moduleName.consume_back(
".pcm");
3865 moduleName.consume_back(
"_rdict");
3873 bool isGenreflex =
false)
3884 const char *executableFileName = argv[0];
3886 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
3887 llvm::PrettyStackTraceProgram
X(argc, argv);
3890#if defined(R__WIN32) && !defined(R__WINGCC)
3895 for (
int iic = 1 ; iic < argc; ++iic) {
3896 std::string iiarg(argv[iic]);
3898 size_t len = iiarg.length();
3900 char *argviic =
new char[
len + 1];
3901 strlcpy(argviic, iiarg.c_str(),
len + 1);
3902 argv[iic] = argviic;
3911 auto &opts = llvm::cl::getRegisteredOptions();
3912 llvm::cl::Option* optHelp = opts[
"help"];
3913 llvm::cl::alias optHelpAlias1(
"h",
3914 llvm::cl::desc(
"Alias for -help"),
3915 llvm::cl::aliasopt(*optHelp));
3916 llvm::cl::alias optHelpAlias2(
"?",
3917 llvm::cl::desc(
"Alias for -help"),
3918 llvm::cl::aliasopt(*optHelp));
3920 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
3923 std::string llvmResourceDir = etcDir ? std::string(etcDir) +
"/cling" :
"";
3926 std::vector<const char *> clingArgsC;
3927 clingArgsC.push_back(executableFileName);
3930 clingArgsC.push_back(
"-I");
3931 clingArgsC.push_back(etcDir);
3938 clingArgsC.push_back(Opt.c_str());
3940 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
3942 llvmResourceDir.c_str());
3945 return interp->getDiagnostics().hasFatalErrorOccurred();
3948 std::string dictname;
3962 llvm::cl::PrintHelpMessage();
3977 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
3978 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4005 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4006 llvm::cl::PrintHelpMessage();
4010 std::vector<std::string> clingArgs;
4011 clingArgs.push_back(executableFileName);
4012 clingArgs.push_back(
"-iquote.");
4018 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4024 if (GetErrorIgnoreLevel() >
kWarning)
4026 GetWarningsAreErrors() =
true;
4040 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4045 clingArgs.push_back(std::string(
"-D") + PPDefine);
4048 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4057 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4065 clingArgs.push_back(
"-isystem");
4066 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4070 for (
const std::string &WDiag :
gOptWDiags) {
4071 const std::string FullWDiag = std::string(
"-W") + WDiag;
4075 clingArgs.push_back(FullWDiag);
4080 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(includeDir));
4083 std::vector<std::string> pcmArgs;
4084 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4085 auto thisArg = clingArgs[parg];
4087 if (thisArg ==
"-c" ||
4093 while (
c ==
' ')
c = thisArg[++
offset];
4097 [&](
const std::string& path){
4098 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4099 if (excludePathsEnd != excludePathPos)
continue;
4101 pcmArgs.push_back(thisArg);
4106 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(etcDir));
4110 clingArgs.push_back(
"-D__ROOTCLING__");
4113 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4114#elif defined(R__WIN32)
4115 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4118 clingArgs.push_back(
"-D_XKEYCHECK_H");
4120 clingArgs.push_back(
"-DNOMINMAX");
4122 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4125 clingArgs.push_back(
"-fsyntax-only");
4127 clingArgs.push_back(
"-fPIC");
4129 clingArgs.push_back(
"-Xclang");
4130 clingArgs.push_back(
"-fmodules-embed-all-files");
4131 clingArgs.push_back(
"-Xclang");
4132 clingArgs.push_back(
"-main-file-name");
4133 clingArgs.push_back(
"-Xclang");
4134 clingArgs.push_back((dictname +
".h").c_str());
4142 std::string outputFile;
4144 llvm::StringRef moduleName;
4149 auto clingArgsInterpreter = clingArgs;
4158 clingArgsInterpreter.push_back(
"-fmodules");
4159 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4162 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4165 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + std::string(includeDir) +
"/ROOT.modulemap");
4168 if (llvm::sys::fs::exists(ModuleMapCWD))
4169 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4177 clingArgsInterpreter.push_back(
"-Xclang");
4178 clingArgsInterpreter.push_back(
"-fmodule-feature");
4179 clingArgsInterpreter.push_back(
"-Xclang");
4182 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4192 if (moduleName ==
"Core") {
4194 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4195 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4196 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4197 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4199 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4200 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4204 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4206 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4208 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4209 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4210 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4211 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4212 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4213 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4214 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4215 }
else if (moduleName ==
"MathCore") {
4216 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4221 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4225 clingArgsInterpreter.push_back(
"-v");
4228 std::vector<const char *> clingArgsC;
4229 for (
auto const &clingArg : clingArgsInterpreter) {
4231 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4232 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4235 clingArgsC.push_back(clingArg.c_str());
4239 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4240 cling::Interpreter* interpPtr =
nullptr;
4242 std::list<std::string> filesIncludedByLinkdef;
4246 clingArgsC.push_back(
"-ffast-math");
4249 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4250 llvmResourceDir.c_str()));
4251 interpPtr = owningInterpPtr.get();
4254 clingArgsC.push_back(
"-resource-dir");
4255 clingArgsC.push_back(llvmResourceDir.c_str());
4256 clingArgsC.push_back(
nullptr);
4258 extraArgs = &clingArgsC[1];
4260 if (!interpPtr->getCI())
4263 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4264 interpPtr->setCallbacks(std::move(callBacks));
4267 cling::Interpreter &interp = *interpPtr;
4268 clang::CompilerInstance *CI = interp.getCI();
4270 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4271 CI->getSourceManager().setAllFilesAreTransient(
true);
4273 clang::Preprocessor &PP = CI->getPreprocessor();
4274 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4275 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4276 auto &diags = interp.getDiagnostics();
4283 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4288 diags.setClient(recordingClient,
true);
4294 interp.DumpIncludePath();
4299 interp.printIncludedFiles(llvm::outs());
4300 llvm::outs() <<
"\n\n";
4301 llvm::outs().flush();
4304 const clang::LangOptions& LangOpts
4305 = interp.getCI()->getASTContext().getLangOpts();
4308 using CK = clang::LangOptions::CompatibilityKind;
4309#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
4310 if constexpr (CK::Compatibility != CK::Benign) \
4311 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4312#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description)
4313#include "clang/Basic/LangOptions.def"
4317 interp.getOptions().ErrorOut =
true;
4318 interp.enableRawInput(
true);
4322 if (DepMod.ends_with(
"_rdict.pcm")) {
4329 cling::Interpreter::PushTransactionRAII RAII(&interp);
4330 if (!interp.loadModule(DepMod.str(),
false)) {
4339 if (interp.declare(
"#include <cassert>\n"
4340 "#include \"Rtypes.h\"\n"
4341 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4349 if (interp.declare(
"#include <string>\n"
4350 "#include <RtypesCore.h>\n"
4351 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4362 clingArgs.push_back(
"-D__CINT__");
4363 clingArgs.push_back(
"-D__MAKECINT__");
4369 std::string interpPragmaSource;
4370 std::string includeForSource;
4371 std::string interpreterDeclarations;
4372 std::string linkdef;
4378 if (isSelectionFile) {
4380 linkdef = optHeaderFileName;
4383 executableFileName, optHeaderFileName.c_str());
4389 std::string fullheader(optHeaderFileName);
4392 if (fullheader[fullheader.length() - 1] ==
'+') {
4393 fullheader.erase(fullheader.length() - 1);
4398 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4399 if (!isSelectionFile) {
4407 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4408 pcmArgs.push_back(header);
4410 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4415 bool hasSelectionFile = !linkdef.empty();
4416 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4427 if (!newName.empty())
4440 string incCurDir =
"-I";
4441 incCurDir += currentDirectory;
4442 pcmArgs.push_back(incCurDir);
4447 std::stringstream res;
4448 const char* delim=
"\n";
4449 std::copy(diagnosticPragmas.begin(),
4450 diagnosticPragmas.end(),
4451 std::ostream_iterator<std::string>(res, delim));
4452 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4458 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4460 IgnoringPragmaHandler(
const char* pragma):
4461 clang::PragmaNamespace(pragma) {}
4462 void HandlePragma(clang::Preprocessor &PP,
4463 clang::PragmaIntroducer Introducer,
4464 clang::Token &tok)
override {
4465 PP.DiscardUntilEndOfDirective();
4471 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4472 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4473 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4474 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4476 if (!interpreterDeclarations.empty() &&
4477 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4489 pcmArgs.push_back(linkdef);
4492 modGen.ParseArgs(pcmArgs);
4496 for (
const std::string & inclPath : modGen.GetIncludePaths()) {
4497 interp.AddIncludePath(inclPath);
4499 std::stringstream definesUndefinesStr;
4500 modGen.WritePPDefines(definesUndefinesStr);
4501 modGen.WritePPUndefines(definesUndefinesStr);
4502 if (!definesUndefinesStr.str().empty()) {
4503 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4504 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4516 std::ofstream fileout;
4523 std::ostream *splitDictStream =
nullptr;
4524 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4543 splitDeleter.reset(splitDictStream);
4545 splitDictStream = &dictStream;
4548 size_t dh = main_dictname.rfind(
'.');
4549 if (dh != std::string::npos) {
4550 main_dictname.erase(dh);
4553 std::string main_dictname_copy(main_dictname);
4575 string linkdefFilename;
4576 if (linkdef.empty()) {
4577 linkdefFilename =
"in memory";
4579 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4587 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4593 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4595 std::string extraIncludes;
4600 const unsigned int selRulesInitialSize = selectionRules.Size();
4604 bool dictSelRulesPresent = selectionRules.Size() > selRulesInitialSize;
4608 int rootclingRetCode(0);
4612 std::ifstream file(linkdefFilename.c_str());
4613 if (file.is_open()) {
4627 if (!ldefr.Parse(selectionRules, interpPragmaSource, clingArgs,
4628 llvmResourceDir.c_str())) {
4630 rootclingRetCode += 1;
4635 if (!ldefr.LoadIncludes(extraIncludes)) {
4640 }
else if (isSelXML) {
4644 std::ifstream file(linkdefFilename.c_str());
4645 if (file.is_open()) {
4649 if (!xmlr.Parse(linkdefFilename.c_str(), selectionRules)) {
4667 selectionRules.FillCache();
4668 selectionRules.Optimize();
4672 ROOT::TMetaUtils::Error(
nullptr,
"No selection rules specified and creation of C++ module not requested: did you forget to specify a selection file or to request the creation of a C++ module?\n");
4677 if (0 != selectionRules.CheckDuplicates()){
4691 dictStream <<
"#include \"TBuffer.h\"\n"
4692 <<
"#include \"TVirtualObject.h\"\n"
4693 <<
"#include <vector>\n"
4694 <<
"#include \"TSchemaHelper.h\"\n\n";
4696 std::list<std::string> includes;
4698 for (
auto & incFile : includes) {
4699 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4701 dictStream << std::endl;
4704 selectionRules.SearchNames(interp);
4706 int scannerVerbLevel = 0;
4709 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4711 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4734 scan.
Scan(CI->getASTContext());
4736 bool has_input_error =
false;
4739 selectionRules.PrintSelectionRules();
4743 !dictSelRulesPresent &&
4744 !selectionRules.AreAllSelectionRulesUsed()) {
4750 if (rootclingRetCode)
return rootclingRetCode;
4757 if (annRcd.RequestNoInputOperator()) {
4769 if (has_input_error) {
4779 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4780 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4806 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4807 constructorTypes.emplace_back(
"__void__", interp);
4808 constructorTypes.emplace_back(
"", interp);
4829 rootclingRetCode +=
GenerateFullDict(*splitDictStream, modGen.GetDictionaryName(), interp, scan, constructorTypes,
4833 if (rootclingRetCode != 0) {
4834 return rootclingRetCode;
4853 std::string detectedUmbrella;
4854 for (
auto & arg : pcmArgs) {
4856 detectedUmbrella = arg;
4862 headersDeclsMap.clear();
4866 std::string headersClassesMapString =
"\"\"";
4867 std::string fwdDeclsString =
"\"\"";
4877 modGen.WriteRegistrationSource(dictStream, fwdDeclnArgsToKeepString, headersClassesMapString, fwdDeclsString,
4883 if (modGen.IsPCH()) {
4886 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
4894 ofstream outputfile(liblist_filename.c_str(), ios::out);
4897 executableFileName, liblist_filename.c_str());
4899 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4900 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4902 outputfile <<
"# Now the list of classes\n";
4907 outputfile << annRcd.GetNormalizedName() << endl;
4913 rootclingRetCode += modGen.GetErrorCount();
4914 if (0 != rootclingRetCode)
return rootclingRetCode;
4920 [](
const std::string &
a,
const std::string &
b) -> std::string {
4921 if (a.empty()) return b;
4922 else return a +
" " + b;
4927 std::list<std::string> classesNames;
4928 std::list<std::string> classesNamesForRootmap;
4929 std::list<std::string> classesDefsList;
4933 classesNamesForRootmap,
4937 std::list<std::string> enumNames;
4942 std::list<std::string> varNames;
4947 if (0 != rootclingRetCode)
return rootclingRetCode;
4950 if (rootMapNeeded) {
4952 std::list<std::string> nsNames;
4961 rootmapLibName.c_str());
4964 std::unordered_set<std::string> headersToIgnore;
4967 headersToIgnore.insert(optHeaderFileName.c_str());
4969 std::list<std::string> typedefsRootmapLines;
4977 classesNamesForRootmap,
4979 typedefsRootmapLines,
4985 if (0 != rootclingRetCode)
return 1;
4995 cling::Interpreter::PushTransactionRAII RAII(&interp);
4996 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5009 if (!
gOptDepFile.empty() && rootclingRetCode == 0 && !dictOutputFileName.empty()) {
5013 "rootcling: failed to open dependency file %s\n",
5015 rootclingRetCode = 1;
5020 auto escapeForDepFile = [](std::string path) {
5021 std::replace(path.begin(), path.end(),
'\\',
'/');
5022 std::string escaped;
5023 escaped.reserve(path.size());
5024 for (
char c : path) {
5025 if (
c ==
' ' ||
c ==
'\t' ||
c ==
'#' ||
c ==
':')
5035 depFile << escapeForDepFile(dictOutputFileName) <<
":";
5039 clang::SourceManager &SM = CI->getSourceManager();
5040 clang::FileManager &FM = SM.getFileManager();
5042 llvm::SmallVector<clang::OptionalFileEntryRef, 64> files;
5043 FM.GetUniqueIDMapping(files);
5045 llvm::SmallString<256> absDictOutput(dictOutputFileName);
5046 llvm::sys::fs::make_absolute(absDictOutput);
5048 llvm::sys::fs::make_absolute(absDictTmp);
5050 std::set<std::string> includedFiles;
5051 for (
const auto &FEOpt : files) {
5054 llvm::StringRef
filename = FEOpt->getName();
5072 llvm::SmallString<256> absPath(
filename);
5073 llvm::sys::fs::make_absolute(absPath);
5074 if (!llvm::sys::fs::exists(absPath))
5076 std::string filenameStr(absPath.str());
5078 if (filenameStr == absDictOutput || filenameStr == absDictTmp)
5080 includedFiles.insert(std::move(filenameStr));
5084 for (
const auto &file : includedFiles)
5085 depFile <<
" \\\n " << escapeForDepFile(file);
5086 if (!includedFiles.empty())
5090 if (!depFile.good()) {
5092 rootclingRetCode = 1;
5099 if(rootclingRetCode == 0) {
5100 rootclingRetCode += tmpCatalog.commit();
5105 return rootclingRetCode;
5116 unsigned int numberOfHeaders = 0;
5117 for (std::vector<std::string>::iterator it = headersNames.begin();
5118 it != headersNames.end(); ++it) {
5119 const std::string headername(*it);
5124 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5125 headername.c_str());
5128 return numberOfHeaders;
5134 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5137 unsigned int argvCounter = 0;
5138 for (
int i = 1; i < argc; ++i) {
5141 args.push_back(argv[i]);
5143 }
else if (argvCounter) {
5144 argv[i - argvCounter] = argv[i];
5151 std::cout <<
"Args: \n";
5152 for (std::vector<std::string>::iterator it = args.begin();
5153 it < args.end(); ++it) {
5154 std::cout << i <<
") " << *it << std::endl;
5168 if (std::string::npos !=
result) {
5180 const unsigned int size(str.size());
5181 char *
a =
new char[
size + 1];
5183 memcpy(
a, str.c_str(),
size);
5199 std::vector<std::string> &ofilesnames)
5201 ofilesnames.reserve(headersNames.size());
5203 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5204 it != headersNames.end(); ++it) {
5205 std::string ofilename(*it);
5207 ofilesnames.push_back(ofilename);
5214 const std::vector<std::string> &argsToBeAdded,
5215 const std::string &optName =
"")
5217 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5218 it != argsToBeAdded.end(); ++it) {
5226 const std::vector<std::string> &argsToBeAdded,
5227 const std::string &optName =
"")
5229 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5230 it != argsToBeAdded.end(); ++it) {
5231 if (optName.length()) {
5241 const std::string &selectionFileName,
5242 const std::string &targetLibName,
5244 const std::vector<std::string> &pcmsNames,
5245 const std::vector<std::string> &includes,
5246 const std::vector<std::string> &preprocDefines,
5247 const std::vector<std::string> &preprocUndefines,
5248 const std::vector<std::string> &warnings,
5249 const std::string &rootmapFileName,
5250 const std::string &rootmapLibName,
5251 bool interpreteronly,
5254 bool writeEmptyRootPCM,
5256 bool noIncludePaths,
5257 bool noGlobalUsingStd,
5258 const std::vector<std::string> &headersNames,
5259 bool failOnWarnings,
5260 bool printRootclingInvocation,
5261 const std::string &ofilename)
5265 std::vector<char *> argvVector;
5276 std::string dictLocation;
5282 std::string newRootmapLibName(rootmapLibName);
5283 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5284 if (headersNames.size() != 1) {
5286 "*** genreflex: No rootmap lib and several header specified!\n");
5289 newRootmapLibName =
"lib";
5290 newRootmapLibName += cleanHeaderName;
5296 std::string newRootmapFileName(rootmapFileName);
5297 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5298 newRootmapFileName = dictLocation + newRootmapFileName;
5303 if (!newRootmapFileName.empty()) {
5309 if (!newRootmapLibName.empty()) {
5319 if (interpreteronly)
5327 if (!targetLibName.empty()) {
5337 if (noGlobalUsingStd)
5347 if (writeEmptyRootPCM)
5370 if (!selectionFileName.empty()) {
5374 const int argc = argvVector.size();
5379 for (
int i = 0; i < argc; i++) {
5380 cmd += argvVector[i];
5385 std::cout << cmd << std::endl;
5386 if (printRootclingInvocation)
return 0;
5389 char **argv = & (argvVector[0]);
5394 for (
int i = 0; i < argc; i++)
5395 delete [] argvVector[i];
5397 return rootclingReturnCode;
5406 const std::string &selectionFileName,
5407 const std::string &targetLibName,
5409 const std::vector<std::string> &pcmsNames,
5410 const std::vector<std::string> &includes,
5411 const std::vector<std::string> &preprocDefines,
5412 const std::vector<std::string> &preprocUndefines,
5413 const std::vector<std::string> &warnings,
5414 const std::string &rootmapFileName,
5415 const std::string &rootmapLibName,
5416 bool interpreteronly,
5419 bool writeEmptyRootPCM,
5421 bool noIncludePaths,
5422 bool noGlobalUsingStd,
5423 const std::vector<std::string> &headersNames,
5424 bool failOnWarnings,
5425 bool printRootclingInvocation,
5426 const std::string &outputDirName_const =
"")
5428 std::string outputDirName(outputDirName_const);
5430 std::vector<std::string> ofilesNames;
5437 std::vector<std::string> namesSingleton(1);
5438 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5439 namesSingleton[0] = headersNames[i];
5440 std::string ofilenameFullPath(ofilesNames[i]);
5441 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5442 ofilenameFullPath = outputDirName + ofilenameFullPath;
5463 printRootclingInvocation,
5465 if (returnCode != 0)
5480 std::vector<std::string> &values)
5483 if (options[oIndex]) {
5484 const int nVals = options[oIndex].count();
5485 values.reserve(nVals);
5486 int optionIndex = 0;
5487 for (ROOT::option::Option *opt = options[oIndex]; opt; opt = opt->next()) {
5489 << optionIndex <<
"/" << nVals <<
" "
5490 << opt->arg << std::endl;
5492 values.push_back(opt->arg);
5503 const char *descriptor)
5505 if (options[optionIndex]) {
5507 "*** genereflex: %s is not supported anymore.\n",
5564 enum optionIndex { UNKNOWN,
5565 PRINTROOTCLINGINVOCATION,
5596 enum optionTypes { NOTYPE, STRING } ;
5599 const char *genreflexUsage =
5600 "********************************************************************************\n"
5601 "* The genreflex utility does not allow to generate C++ modules containing *\n"
5602 "* reflection information required at runtime. Please use rootcling instead *\n"
5603 "* To print the rootcling invocation that corresponds to the current genreflex *\n"
5604 "* invocation please use the --print-rootcling-invocation flag. *\n"
5605 "********************************************************************************\n"
5607 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5608 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5611 const char *printRootclingInvocationUsage =
5612 "--print-rootcling-invocation\n"
5613 " Print to screen the rootcling invocation corresponding to the current \n"
5614 " genreflex invocation.\n";
5616 const char *selectionFilenameUsage =
5617 "-s, --selection_file\tSelection filename\n"
5618 " Class selection file to specify for which classes the dictionary\n"
5619 " will be generated. The final set can be crafted with exclusion and\n"
5620 " exclusion rules.\n"
5621 " Properties can be specified. Some have special meaning:\n"
5622 " - name [string] name of the entity to select with an exact matching\n"
5623 " - pattern [string] name with wildcards (*) to select entities\n"
5624 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5625 " file where the C++ entities reside and not to C++ entities themselves.\n"
5626 " - transient/persistent [string: true/false] The fields to which they are\n"
5627 " applied will not be persistified if requested.\n"
5628 " - comment [string]: what you could write in code after an inline comment\n"
5629 " without \"//\". For example comment=\"!\" or \"||\".\n"
5630 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5631 " Default value is 'false'\n"
5632 " - rntupleStreamerMode [true/false]: enforce streamed or native writing for RNTuple.\n"
5633 " If unset, RNTuple stores classes in split mode or fails if the class cannot be split.\n"
5634 " - rntupleSoARecord [class name]: marks the class as an RNTuple SoA layout for the underlying record\n"
5635 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5636 " to 'true'. Default value is 'false'\n"
5640 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5641 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5642 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5643 " [noInputOperator=\"true/false\"]\n"
5644 " [rntupleStreamerMode=\"true/false\"] />\n"
5645 " [rntupleSoARecord=\"class_name\"] />\n"
5646 " <class name=\"classname\" >\n"
5647 " <field name=\"m_transient\" transient=\"true\"/>\n"
5648 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5649 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5650 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5652 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5653 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5654 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5657 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5658 " <method name=\"unwanted\" />\n"
5663 " If no selection file is specified, the class with the filename without\n"
5664 " extension will be selected, i.e. myClass.h as argument without any\n"
5665 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5667 const char *outputFilenameUsage =
5668 "-o, --output\tOutput filename\n"
5669 " Output file name. If an existing directory is specified instead of a file,\n"
5670 " then a filename will be built using the name of the input file and will\n"
5671 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5672 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5673 " have unique names.\n";
5676 const char *targetLib =
5677 "-l, --library\tTarget library\n"
5678 " The flag -l must be followed by the name of the library that will\n"
5679 " contain the object file corresponding to the dictionary produced by\n"
5680 " this invocation of genreflex.\n"
5681 " The name takes priority over the one specified for the rootmapfile.\n"
5682 " The name influences the name of the created pcm:\n"
5683 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5684 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5685 " Any \"liblib\" occurrence is transformed in the expected \"lib\".\n"
5686 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5687 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5689 const char *rootmapUsage =
5690 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5691 " This file lists the autoload keys. For example classes for which the\n"
5692 " reflection information is provided.\n"
5693 " The format of the rootmap is the following:\n"
5694 " - Forward declarations section\n"
5695 " - Libraries sections\n"
5696 " Rootmaps can be concatenated together, for example with the cat util.\n"
5697 " In order for ROOT to pick up the information in the rootmaps, they\n"
5698 " have to be located in the library path and have the .rootmap extension.\n"
5699 " An example rootmap file could be:\n"
5701 " template <class T> class A;\n"
5702 " [ libMyLib.so ]\n"
5703 " class A<double>\n"
5708 const char *rootmapLibUsage =
5709 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5712 const ROOT::option::Descriptor genreflexUsageDescriptor[] = {
5718 ROOT::option::Arg::None,
5723 PRINTROOTCLINGINVOCATION,
5725 "",
"print-rootcling-invocation",
5726 ROOT::option::Arg::None,
5727 printRootclingInvocationUsage
5734 ROOT::option::FullArg::Required,
5742 ROOT::option::FullArg::Required,
5750 ROOT::option::FullArg::None,
5751 "--multiDict\tSupport for many dictionaries in one library\n"
5752 " Form correct pcm names if multiple dictionaries will be in the same\n"
5753 " library (needs target library switch. See its documentation).\n"
5760 "" ,
"noGlobalUsingStd" ,
5761 ROOT::option::FullArg::None,
5762 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5763 " All header files must have sumbols from std:: namespace fully qualified\n"
5769 "s" ,
"selection_file" ,
5770 ROOT::option::FullArg::Required,
5771 selectionFilenameUsage
5778 ROOT::option::FullArg::Required,
5785 "" ,
"rootmap-lib" ,
5786 ROOT::option::FullArg::Required,
5793 "" ,
"interpreteronly",
5794 ROOT::option::Arg::None,
5795 "--interpreteronly\tDo not generate I/O related information.\n"
5796 " Generate minimal dictionary required for interactivity.\n"
5803 ROOT::option::Arg::None,
5804 "--split\tSplit the dictionary\n"
5805 " Split in two the dictionary, isolating the part with\n"
5806 " ClassDef related functions in a separate file.\n"
5813 ROOT::option::FullArg::Required,
5814 "-m \tPcm file loaded before any header (option can be repeated).\n"
5821 ROOT::option::Arg::None,
5822 "-v, --verbose\tPrint some debug information.\n"
5829 ROOT::option::Arg::None,
5830 "--debug\tPrint all debug information.\n"
5837 ROOT::option::Arg::None,
5838 "--quiet\tPrint only warnings and errors (default).\n"
5845 ROOT::option::Arg::None,
5846 "--silent\tPrint no information at all.\n"
5852 "" ,
"writeEmptyPCM",
5853 ROOT::option::Arg::None,
5854 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5861 ROOT::option::Arg::None,
5862 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5870 ROOT::option::Arg::None,
5871 "--help\tPrint usage and exit.\n"
5877 "",
"fail_on_warnings",
5878 ROOT::option::Arg::None,
5879 "--fail_on_warnings\tFail on warnings and errors.\n"
5885 "",
"selSyntaxOnly",
5886 ROOT::option::Arg::None,
5887 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5893 "" ,
"noIncludePaths",
5894 ROOT::option::Arg::None,
5895 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5903 ROOT::option::FullArg::Required,
5911 ROOT::option::FullArg::Required,
5919 ROOT::option::FullArg::Required,
5927 ROOT::option::FullArg::Required,
5934 "" ,
"no_membertypedefs" ,
5935 ROOT::option::FullArg::None,
5942 "" ,
"no_templatetypedefs" ,
5943 ROOT::option::FullArg::None,
5947 {0, 0,
nullptr,
nullptr,
nullptr,
nullptr}
5950 std::vector<std::string> headersNames;
5951 const int originalArgc = argc;
5953 const int extractedArgs = extractArgs(argc, argv, headersNames);
5956 argc -=
offset + extractedArgs;
5960 ROOT::option::Stats stats(genreflexUsageDescriptor, argc, argv);
5961 std::vector<ROOT::option::Option> options(stats.options_max);
5962 std::vector<ROOT::option::Option> buffer(stats.buffer_max);
5966 ROOT::option::Parser parse(genreflexUsageDescriptor, argc, argv, &options[0], &buffer[0], 5);
5968 if (parse.error()) {
5974 if (options[HELP] || originalArgc == 1) {
5975 ROOT::option::printUsage(std::cout, genreflexUsageDescriptor);
5979 int numberOfHeaders = checkHeadersNames(headersNames);
5980 if (0 == numberOfHeaders) {
5991 std::string verbosityOption(
"-v2");
5992 if (options[SILENT]) verbosityOption =
"-v0";
5993 if (options[VERBOSE] || std::getenv (
"VERBOSE")) verbosityOption =
"-v3";
5994 if (options[
DEBUG]) verbosityOption =
"-v4";
5999 std::string selectionFileName;
6000 if (options[SELECTIONFILENAME]) {
6001 selectionFileName = options[SELECTIONFILENAME].arg;
6004 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
6005 selectionFileName.c_str());
6020 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
6021 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
6024 std::string targetLibName;
6025 if (options[TARGETLIB]) {
6026 targetLibName = options[TARGETLIB].arg;
6029 "Invalid target library extension: filename is %s and extension %s is expected!\n",
6030 targetLibName.c_str(),
6034 if (options[ROOTMAP]) {
6039 bool isCxxmodule = options[CXXMODULE];
6041 bool multidict =
false;
6042 if (options[MULTIDICT]) multidict =
true;
6044 bool noGlobalUsingStd =
false;
6045 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
6047 if (multidict && targetLibName.empty()) {
6049 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
6053 bool printRootclingInvocation =
false;
6054 if (options[PRINTROOTCLINGINVOCATION])
6055 printRootclingInvocation =
true;
6057 bool interpreteronly =
false;
6058 if (options[INTERPRETERONLY])
6059 interpreteronly =
true;
6061 bool doSplit =
false;
6065 bool writeEmptyRootPCM =
false;
6066 if (options[WRITEEMPTYROOTPCM])
6067 writeEmptyRootPCM =
true;
6069 bool selSyntaxOnly =
false;
6070 if (options[SELSYNTAXONLY]) {
6071 selSyntaxOnly =
true;
6074 bool noIncludePaths =
false;
6075 if (options[NOINCLUDEPATHS]) {
6076 noIncludePaths =
true;
6079 bool failOnWarnings =
false;
6080 if (options[FAILONWARNINGS]) {
6081 failOnWarnings =
true;
6090 std::vector<std::string> pcmsNames;
6094 std::vector<std::string> preprocDefines;
6098 std::vector<std::string> preprocUndefines;
6102 std::vector<std::string> includes;
6106 std::vector<std::string> warnings;
6117 int returnValue = 0;
6118 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6122 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6123 returnValue = invokeRootCling(verbosityOption,
6143 printRootclingInvocation,
6147 returnValue = invokeManyRootCling(verbosityOption,
6167 printRootclingInvocation,
6181 assert(!
gDriverConfig &&
"Driver configuration already set!");
6201 if (std::string::npos != exeName.find(
"genreflex"))
6209 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...
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Basic types used by ROOT and required by TInterpreter.
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
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.
void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
~CheckModuleBuildClient() override
CheckModuleBuildClient(clang::DiagnosticConsumer *Child, bool OwnsChild, clang::ModuleMap &Map)
clang::DiagnosticConsumer * fChild
bool IncludeInDiagnosticCounts() const override
void EndSourceFile() override
void BeginSourceFile(const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) override
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.
~TRootClingCallbacks() override
void InclusionDirective(clang::SourceLocation, const clang::Token &, llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange, clang::OptionalFileEntryRef, llvm::StringRef, llvm::StringRef, const clang::Module *, bool, 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)
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)
@ kInfo
Informational messages; used for instance for tracing.
@ kWarning
Warnings about likely unexpected behavior.
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 ...
int GenerateFullDict(std::ostream &dictStream, std::string dictName, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool isSelXML, bool writeEmptyRootPCM)
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)
int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
#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))
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))
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.
static llvm::cl::opt< std::string > gOptDepFile("MF", llvm::cl::desc("Write dependency output to the specified file."), llvm::cl::cat(gRootclingOptions))
bool IsSupportedClassName(const char *name)
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)
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)
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.
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)()