12#include "rootclingCommandLineOptionsHelp.h"
14#include "RConfigure.h"
33#include <unordered_map>
34#include <unordered_set>
46#define PATH_MAX _MAX_PATH
54#include <mach-o/dyld.h>
62#include <libprocstat.h>
71#include "cling/Interpreter/Interpreter.h"
72#include "cling/Interpreter/InterpreterCallbacks.h"
73#include "cling/Interpreter/LookupHelper.h"
74#include "cling/Interpreter/Value.h"
75#include "clang/AST/CXXInheritance.h"
76#include "clang/Basic/Diagnostic.h"
77#include "clang/Frontend/CompilerInstance.h"
78#include "clang/Frontend/FrontendActions.h"
79#include "clang/Frontend/FrontendDiagnostic.h"
80#include "clang/Lex/HeaderSearch.h"
81#include "clang/Lex/Preprocessor.h"
82#include "clang/Lex/ModuleMap.h"
83#include "clang/Lex/Pragma.h"
84#include "clang/Sema/Sema.h"
85#include "clang/Serialization/ASTWriter.h"
86#include "cling/Utils/AST.h"
88#include "llvm/ADT/StringRef.h"
90#include "llvm/Support/CommandLine.h"
91#include "llvm/Support/Path.h"
92#include "llvm/Support/PrettyStackTrace.h"
93#include "llvm/Support/Signals.h"
117#include <mach-o/dyld.h>
122#define strcasecmp _stricmp
123#define strncasecmp _strnicmp
131#define rootclingStringify(s) rootclingStringifyx(s)
132#define rootclingStringifyx(s) #s
139using std::string, std::map, std::ifstream, std::ofstream, std::endl, std::ios, std::vector;
150static llvm::cl::opt<bool>
152 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
153When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
173static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
177 for (
const auto td : tdvec)
180static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
184 for (
const auto en : enumvec) {
186 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
187 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
188 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
198 static std::string exepath;
201 exepath = _dyld_get_image_name(0);
203#if defined(__linux) || defined(__linux__)
204 char linkname[PATH_MAX];
210 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
211 int ret = readlink(linkname, buf, 1024);
212 if (ret > 0 && ret < 1024) {
218 procstat* ps = procstat_open_sysctl();
219 kinfo_proc* kp = kinfo_getproc(getpid());
222 char path_str[PATH_MAX] =
"";
223 procstat_getpathname(ps, kp, path_str,
sizeof(path_str));
231 char *buf =
new char[MAX_MODULE_NAME32 + 1];
232 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
234 while ((
p = strchr(
p,
'\\')))
240 return exepath.c_str();
246 const cling::Interpreter &interp)
254 const std::list<VariableSelectionRule> &fieldSelRules)
262 if (fieldSelRules.empty())
return;
264 clang::ASTContext &C = decl.getASTContext();
266 const std::string declName(decl.getNameAsString());
268 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
269 it != fieldSelRules.end(); ++it) {
270 if (! it->GetAttributeValue(propNames::name, varName))
continue;
271 if (declName == varName) {
274 BaseSelectionRule::AttributesMap_t::iterator iter;
275 std::string userDefinedProperty;
276 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
277 const std::string &
name = iter->first;
278 const std::string &
value = iter->second;
280 if (
name == propNames::name)
continue;
285 if (
name == propNames::iotype &&
286 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
287 const char *msg =
"Data member \"%s\" is an array or a pointer. "
288 "It is not possible to assign to it the iotype \"%s\". "
289 "This transformation is possible only with data members "
290 "which are not pointers or arrays.\n";
292 msg, varName.c_str(),
value.c_str());
300 if (
name == propNames::comment) {
301 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
value));
305 if ((
name == propNames::transient &&
value ==
"true") ||
306 (
name == propNames::persistent &&
value ==
"false")) {
307 userDefinedProperty = propNames::comment + propNames::separator +
"!";
311 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
"!"));
316 userDefinedProperty =
name + propNames::separator +
value;
319 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty));
330 cling::Interpreter &interpreter,
338 using namespace clang;
339 SourceLocation commentSLoc;
340 llvm::StringRef comment;
342 ASTContext &C = CXXRD.getASTContext();
345 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
346 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
347 if (declSelRulePair == declSelRulesMap.end()){
348 const std::string thisClassName(CXXRD.getName());
349 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
354 if (thisClassBaseSelectionRule) {
357 BaseSelectionRule::AttributesMap_t::iterator iter;
358 std::string userDefinedProperty;
360 const std::string &
name =
attr.first;
365 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty));
372 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
373 E = CXXRD.decls_end();
I != E; ++
I) {
377 if (!(*I)->isImplicit()
378 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
382 if (isClassDefMacro) {
383 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
389 if (comment.size()) {
391 if (isClassDefMacro) {
392 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str()));
393 }
else if (!isGenreflex) {
399 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str()));
404 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
408 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
422 llvm::APInt
len = arrayType->getSize();
423 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
424 len *= subArrayType->getSize();
425 arrayType = subArrayType;
427 return len.getLimitedValue();
433 const cling::Interpreter &interp)
435 static const clang::CXXRecordDecl *TObject_decl
438 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
445 const cling::Interpreter &interp)
447 static const clang::CXXRecordDecl *TObject_decl
460 return (0 == strcasecmp(
filename + (
len - xmllen),
".xml"));
486 if (exepath && *exepath) {
488 char *ep =
new char[PATH_MAX];
489 if (!realpath(exepath, ep)) {
490 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
491 strlcpy(ep, exepath, PATH_MAX);
494 int nche = strlen(exepath) + 1;
495 char *ep =
new char[nche];
496 strlcpy(ep, exepath, nche);
500 if ((s = strrchr(ep,
'/'))) {
502 int removesubdirs = 2;
503 if (!strncmp(s + 1,
"rootcling_stage1.exe", 20)) {
507 }
else if (!strncmp(s + 1,
"rootcling_stage1", 16)) {
512 for (
int i = 1; s && i < removesubdirs; ++i) {
514 s = strrchr(ep,
'/');
528 int ncha = strlen(ep) + 10;
529 char *env =
new char[ncha];
530 snprintf(env, ncha,
"ROOTSYS=%s", ep);
551 const char *expectedTokens[],
552 size_t *end =
nullptr)
555 if (
line[0] !=
'#')
return false;
557 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
558 while (isspace(
line[pos])) ++pos;
559 size_t lenToken = strlen(*iToken);
560 if (
line.compare(pos, lenToken, *iToken)) {
579 if (recordDecl->hasOwningModule()) {
580 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
583 std::string qual_name;
589 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
598 if (classname.find(
':') == std::string::npos)
return;
601 int slen = classname.size();
602 for (
int k = 0; k < slen; ++k) {
603 if (classname[k] ==
':') {
604 if (k + 1 >= slen || classname[k + 1] !=
':') {
609 string base = classname.substr(0, k);
614 autoloads[base] =
"";
618 }
else if (classname[k] ==
'<') {
630 std::string classname;
632 while (file >>
line) {
634 if (
line.find(
"Library.") != 0)
continue;
636 int pos =
line.find(
":", 8);
637 classname =
line.substr(8, pos - 8);
642 getline(file,
line,
'\n');
643 while (
line[0] ==
' ')
line.replace(0, 1,
"");
647 if (classname ==
"ROOT::TImpProxy") {
651 autoloads[classname] =
line;
666 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
668 while (getline(file,
line,
'\n')) {
669 if (
line ==
"{ decls }") {
670 while (getline(file,
line,
'\n')) {
671 if (
line[0] ==
'[')
break;
674 const char firstChar =
line[0];
675 if (firstChar ==
'[') {
677 libs =
line.substr(1,
line.find(
']') - 1);
678 while (libs[0] ==
' ') libs.replace(0, 1,
"");
679 }
else if (0 != keyLenMap.count(firstChar)) {
680 unsigned int keyLen = keyLenMap.at(firstChar);
681 keyname =
line.substr(keyLen,
line.length() - keyLen);
683 autoloads[keyname] = libs;
693void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
695 std::ifstream filelist(fileListName.c_str());
702 if (llvm::sys::fs::is_directory(
filename))
continue;
708 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
710 file.seekg(0, std::ios::beg);
731 const string &fullname,
732 const clang::RecordDecl *cl,
733 cling::Interpreter &interp)
736 const clang::FunctionDecl *method
741 clang::TranslationUnitDecl *TU =
742 cl->getASTContext().getTranslationUnitDecl();
746 bool has_input_error =
false;
747 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
749 if (strstr(
filename.c_str(),
"TBuffer.h") !=
nullptr ||
750 strstr(
filename.c_str(),
"Rtypes.h") !=
nullptr) {
752 has_input_error =
true;
755 has_input_error =
true;
757 if (has_input_error) {
759 const char *maybeconst =
"";
760 const char *mayberef =
"&";
761 if (
what[strlen(
what) - 1] ==
'<') {
762 maybeconst =
"const ";
766 "in this version of ROOT, the option '!' used in a linkdef file\n"
767 " implies the actual existence of customized operators.\n"
768 " The following declaration is now required:\n"
769 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
771 return has_input_error;
783 int ncha = fullname.length() + 13;
784 char *
proto =
new char[ncha];
796 return has_input_error;
802bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
808 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
812 bool isAbstract = clxx->isAbstract();
815 std::string qualName;
817 const char *qualName_c = qualName.c_str();
819 "because it inherits from TObject but does not "
820 "have its own ClassDef.\n",
833 if (
m.getType().isConstQualified()) {
834 string ret =
"const_cast< ";
837 if (type_name.substr(0,6)==
"const ") {
838 ret += type_name.c_str()+6;
844 ret +=
m.getName().str();
848 return prefix +
m.getName().str();
858 const cling::Interpreter &interp,
860 std::ostream &dictStream)
863 std::string mTypename;
876 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
878 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
879 if (!tmplt_specialization)
return 0;
885 string fulName1, fulName2;
886 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
887 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
888 clang::QualType ti = arg0.getAsType();
892 fulName1 = ti.getAsString();
895 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
896 clang::QualType tmplti = arg1.getAsType();
899 fulName2 = tmplti.getAsString();
906 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
912 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
916 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
918 }
else if (
m.getType()->isPointerType()) {
923 dictStream <<
" {" << std::endl;
925 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
930 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
933 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
936 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
937 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
938 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
941 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
942 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
943 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
947 dictStream <<
" R__stl.clear();" << std::endl;
950 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
951 <<
" if (R__tcl1==0) {" << std::endl
952 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
953 << fulName1.c_str() <<
"!\");" << std::endl
954 <<
" return;" << std::endl
955 <<
" }" << std::endl;
958 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
959 <<
" if (R__tcl2==0) {" << std::endl
960 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
961 << fulName2.c_str() <<
"!\");" << std::endl
962 <<
" return;" << std::endl
963 <<
" }" << std::endl;
966 dictStream <<
" int R__i, R__n;" << std::endl
967 <<
" R__b >> R__n;" << std::endl;
970 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
972 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
976 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
996 std::string keyName(ti.getAsString());
997 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
998 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
999 <<
" R__stl.insert(R__t3);" << std::endl;
1007 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1012 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1015 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1020 dictStream <<
" }" << std::endl
1021 <<
" }" << std::endl;
1022 if (isArr) dictStream <<
" }" << std::endl;
1028 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
1030 dictStream <<
" {" << std::endl;
1033 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1036 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1039 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1042 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1046 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1047 <<
" R__b << R__n;" << std::endl
1048 <<
" if(R__n) {" << std::endl;
1051 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1052 <<
" if (R__tcl1==0) {" << std::endl
1053 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1054 << fulName1.c_str() <<
"!\");" << std::endl
1055 <<
" return;" << std::endl
1056 <<
" }" << std::endl;
1059 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1060 <<
" if (R__tcl2==0) {" << std::endl
1061 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1062 <<
" return;" << std::endl
1063 <<
" }" << std::endl;
1066 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1067 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1069 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1070 clang::QualType tmplti = arg1.getAsType();
1077 dictStream <<
" }" << std::endl
1078 <<
" }" << std::endl
1079 <<
" }" << std::endl;
1080 if (isArr) dictStream <<
" }" << std::endl;
1092 std::string mTypenameStr;
1096 if (!strcmp(mTypeName,
"string")) {
1098 std::string fieldname =
m.getName().str();
1101 if (
m.getType()->isConstantArrayType()) {
1102 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1103 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1105 std::stringstream fullIdx;
1106 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1109 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1110 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1111 fullIdx <<
"[R__i" << dim <<
"]";
1112 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1115 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1116 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1119 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1120 if (
m.getType()->isPointerType())
1121 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1122 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1124 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1128 if (
m.getType()->isPointerType())
1129 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1130 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1131 else if (
m.getType()->isConstantArrayType()) {
1132 std::stringstream fullIdx;
1133 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1136 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1137 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1138 fullIdx <<
"[R__i" << dim <<
"]";
1139 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1142 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1144 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1155 if (
m.getType()->isPointerType()) {
1156 if (
m.getType()->getPointeeType()->isPointerType()) {
1168 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1170 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1172 dictStream <<
"[0]";
1173 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1188 int enclSpaceNesting = 0;
1195 dictStream <<
"#include \"TInterpreter.h\"\n";
1197 dictStream <<
"//_______________________________________"
1198 <<
"_______________________________________" << std::endl;
1199 if (add_template_keyword) dictStream <<
"template <> ";
1200 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1203 <<
"//_______________________________________"
1204 <<
"_______________________________________" << std::endl;
1205 if (add_template_keyword) dictStream <<
"template <> ";
1206 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1207 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1209 dictStream <<
"//_______________________________________"
1210 <<
"_______________________________________" << std::endl;
1211 if (add_template_keyword) dictStream <<
"template <> ";
1212 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1213 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1214 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1216 <<
"//_______________________________________"
1217 <<
"_______________________________________" << std::endl;
1218 if (add_template_keyword) dictStream <<
"template <> ";
1219 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1220 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1221 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1223 <<
"//_______________________________________"
1224 <<
"_______________________________________" << std::endl;
1225 if (add_template_keyword) dictStream <<
"template <> ";
1226 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1230 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1231 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1232 <<
"*)nullptr)->GetClass();" << std::endl
1233 <<
" return fgIsA;\n"
1234 <<
"}" << std::endl << std::endl
1236 <<
"//_______________________________________"
1237 <<
"_______________________________________" << std::endl;
1238 if (add_template_keyword) dictStream <<
"template <> ";
1239 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1241 dictStream <<
" Dictionary();\n";
1243 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1244 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1246 dictStream <<
" return fgIsA;" << std::endl
1247 <<
"}" << std::endl << std::endl;
1249 while (enclSpaceNesting) {
1250 dictStream <<
"} // namespace " << nsname << std::endl;
1259 cling::Interpreter &interp,
1260 std::ostream &dictStream)
1262 if (cl->isAnonymousNamespace()) {
1274 if (classname !=
"ROOT") {
1278 dictStream <<
" namespace ROOTDict {" << std::endl;
1281 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1285 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1286 dictStream << std::endl
1288 <<
" // Function generating the singleton type initializer" << std::endl
1291 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1292 <<
" {" << std::endl
1294 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1295 <<
" {" << std::endl
1298 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1300 <<
" instance(\"" << classname.c_str() <<
"\", ";
1303 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1305 dictStream <<
"0 /*version*/, ";
1309 for (
unsigned int i = 0; i <
filename.length(); i++) {
1313 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1317 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1319 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1322 dictStream << 0 <<
");" << std::endl
1324 <<
" return &instance;" << std::endl
1325 <<
" }" << std::endl
1326 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1327 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1328 <<
" // Static variable to force the class initialization" << std::endl
1330 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1331 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1334 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1335 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1336 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1337 <<
" }" << std::endl << std::endl;
1340 dictStream <<
" }" << std::endl;
1342 dictStream <<
"}" << std::endl;
1344 dictStream << std::endl;
1353llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1356 llvm::StringRef where;
1359 if (
index.size() == 0 && printError) {
1360 const char *errorstring;
1363 errorstring =
"is not an integer";
1366 errorstring =
"has not been defined before the array";
1369 errorstring =
"is a private member of a parent class";
1372 errorstring =
"is not known";
1375 errorstring =
"UNKNOWN ERROR!!!!";
1378 if (where.size() == 0) {
1380 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1383 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1392 const cling::Interpreter &interp,
1394 std::ostream &dictStream)
1396 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1397 if (clxx ==
nullptr)
return;
1404 int enclSpaceNesting = 0;
1410 dictStream <<
"//_______________________________________"
1411 <<
"_______________________________________" << std::endl;
1412 if (add_template_keyword) dictStream <<
"template <> ";
1413 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1414 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1422 int basestreamer = 0;
1423 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1427 string base_fullname;
1430 if (strstr(base_fullname.c_str(),
"::")) {
1432 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1433 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1434 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1436 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1441 if (!basestreamer) {
1442 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1443 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1445 dictStream <<
"}" << std::endl << std::endl;
1446 while (enclSpaceNesting) {
1447 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1454 string classname = fullname;
1455 if (strstr(fullname.c_str(),
"::")) {
1457 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1458 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1459 classname =
"thisClass";
1461 for (
int i = 0; i < 2; i++) {
1466 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1467 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1468 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1470 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1471 dictStream <<
" } else {" << std::endl;
1472 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1477 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1481 string base_fullname;
1484 if (strstr(base_fullname.c_str(),
"::")) {
1486 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1487 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1488 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1491 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1497 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1502 clang::QualType
type = field_iter->getType();
1503 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1513 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1517 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1520 if (strncmp(comment,
"!", 1)) {
1523 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1524 if (
type.getTypePtr()->isConstantArrayType() &&
1525 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1526 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1530 dictStream <<
" int R__i;" << std::endl;
1533 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1535 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: array of pointers to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1536 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1538 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1540 }
else if (
type.getTypePtr()->isPointerType()) {
1541 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1542 if (indexvar.size() == 0) {
1544 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1545 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1547 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1551 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1556 <<
"," << indexvar.str() <<
");" << std::endl;
1557 }
else if (isDouble32) {
1559 <<
"," << indexvar.str() <<
");" << std::endl;
1562 <<
"," << indexvar.str() <<
");" << std::endl;
1566 dictStream <<
" R__b.WriteFastArrayFloat16("
1567 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1568 }
else if (isDouble32) {
1569 dictStream <<
" R__b.WriteFastArrayDouble32("
1570 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1572 dictStream <<
" R__b.WriteFastArray("
1573 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1577 }
else if (
type.getTypePtr()->isArrayType()) {
1579 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1580 if (underling_type->isEnumeralType())
1581 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1585 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1586 }
else if (isDouble32) {
1588 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1591 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1595 if (underling_type->isEnumeralType()) {
1596 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1599 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1600 }
else if (isDouble32) {
1601 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1604 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1609 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1612 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1613 if (underling_type->isEnumeralType())
1614 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1615 << s <<
");" << std::endl;
1616 else if (isFloat16) {
1618 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1619 }
else if (isDouble32) {
1621 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1624 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1627 if (underling_type->isEnumeralType())
1628 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1629 else if (isFloat16) {
1630 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1631 }
else if (isDouble32) {
1632 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1634 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1638 }
else if (underling_type->isEnumeralType()) {
1640 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1641 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1643 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1648 <<
"=Float16_t(R_Dummy);}" << std::endl;
1651 }
else if (isDouble32) {
1654 <<
"=Double32_t(R_Dummy);}" << std::endl;
1676 if (
type.getTypePtr()->isConstantArrayType() &&
1677 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1678 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1682 dictStream <<
" int R__i;" << std::endl;
1685 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1690 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1695 dictStream <<
"[R__i];" << std::endl;
1696 }
else if (
type.getTypePtr()->isPointerType()) {
1704 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1705 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1707 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1711 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1725 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1731 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1735 dictStream <<
" int R__i;" << std::endl;
1738 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1739 std::string mTypeNameStr;
1741 const char *mTypeName = mTypeNameStr.c_str();
1742 const char *constwd =
"const ";
1743 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1744 mTypeName += strlen(constwd);
1745 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1747 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1751 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1757 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1758 << field_iter->getName().str() <<
"));" << std::endl;
1769 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1770 <<
" }" << std::endl
1771 <<
"}" << std::endl << std::endl;
1773 while (enclSpaceNesting) {
1774 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1782 const cling::Interpreter &interp,
1784 std::ostream &dictStream)
1788 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1789 if (clxx ==
nullptr)
return;
1794 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1806 int enclSpaceNesting = 0;
1812 dictStream <<
"//_______________________________________"
1813 <<
"_______________________________________" << std::endl;
1814 if (add_template_keyword) dictStream <<
"template <> ";
1815 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1817 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1818 <<
" if (R__b.IsReading()) {" << std::endl
1819 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1820 <<
" } else {" << std::endl
1821 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1822 <<
" }" << std::endl
1823 <<
"}" << std::endl << std::endl;
1825 while (enclSpaceNesting) {
1826 dictStream <<
"} // namespace " << nsname << std::endl;
1834 const cling::Interpreter &interp,
1836 std::ostream &dictStream,
1837 bool isAutoStreamer)
1839 if (isAutoStreamer) {
1849 std::string &code_for_parser)
1851 code_for_parser +=
"#ifdef __CINT__\n\n";
1852 code_for_parser +=
"#pragma link off all globals;\n";
1853 code_for_parser +=
"#pragma link off all classes;\n";
1854 code_for_parser +=
"#pragma link off all functions;\n\n";
1856 for (std::string& arg : InputFiles) {
1858 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1859 for (
int j = 0; j < 3; j++) {
1860 if (arg[
l] ==
'-') {
1865 if (arg[
l] ==
'!') {
1870 if (arg[
l] ==
'+') {
1876 if (nostr || noinp) {
1878 if (nostr) strlcat(trail,
"-", 3);
1879 if (noinp) strlcat(trail,
"!", 3);
1882 strlcpy(trail,
"+", 3);
1886 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1887 llvm::sys::path::replace_extension(filestem,
"");
1889 code_for_parser +=
"#pragma link C++ class ";
1890 code_for_parser += filestem.str().str();
1891 if (nostr || noinp || bcnt)
1892 code_for_parser += trail;
1893 code_for_parser +=
";\n";
1896 code_for_parser +=
"\n#endif\n";
1904bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1909 static const char *fopenopts =
"rb";
1911 static const char *fopenopts =
"r";
1915 fp = fopen(pname.c_str(), fopenopts);
1921 llvm::SmallVector<std::string, 10> includePaths;
1923 interp.GetIncludePaths(includePaths,
false,
false);
1925 const size_t nPaths = includePaths.size();
1926 for (
size_t i = 0; i < nPaths; i += 1 ) {
1930 fp = fopen(pname.c_str(), fopenopts);
1952 const char *inc = strstr(original,
"\\inc\\");
1954 inc = strstr(original,
"/inc/");
1955 if (inc && strlen(inc) > 5)
1975 cling::Interpreter &interp,
1978 std::ostringstream out;
1983 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1984 const std::string &hdrName
2002static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
2003 llvm::StringRef iSysRoot,
2004 clang::Module *module =
nullptr)
2007 llvm::SmallVector<char, 128> buffer;
2008 llvm::BitstreamWriter stream(buffer);
2009 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
2010 std::unique_ptr<llvm::raw_ostream> out =
2011 compilerInstance->createOutputFile(fileName,
true,
2020 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2022 writer.WriteAST(compilerInstance->getSema(), fileName.str(), module, iSysRoot);
2025 out->write(&buffer.front(), buffer.size());
2037 const std::string ¤tDirectory)
2039 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2041 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2049static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2052 if (headers.empty())
2056 std::stringstream includes;
2057 for (
const std::string &header : headers) {
2058 includes <<
"#include \"" << header <<
"\"\n";
2060 std::string includeListStr = includes.str();
2061 auto result = interpreter.declare(includeListStr);
2062 return result == cling::Interpreter::CompilationResult::kSuccess;
2070 char platformDefines[64] = {0};
2071#ifdef __INTEL_COMPILER
2072 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2073 clingArgs.push_back(platformDefines);
2076 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2077 clingArgs.push_back(platformDefines);
2080 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2081 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2082 clingArgs.push_back(platformDefines);
2084#ifdef __GNUC_MINOR__
2085 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2086 clingArgs.push_back(platformDefines);
2089 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2090 clingArgs.push_back(platformDefines);
2093 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2094 clingArgs.push_back(platformDefines);
2097 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2098 clingArgs.push_back(platformDefines);
2100#ifdef _STLPORT_VERSION
2102 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2103 clingArgs.push_back(platformDefines);
2106 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2107 clingArgs.push_back(platformDefines);
2110 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2111 clingArgs.push_back(platformDefines);
2114 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2115 clingArgs.push_back(platformDefines);
2118 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2119 clingArgs.push_back(platformDefines);
2122 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2123 clingArgs.push_back(platformDefines);
2126 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2127 clingArgs.push_back(platformDefines);
2131 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
2132 clingArgs.push_back(platformDefines);
2135 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2136 clingArgs.push_back(platformDefines);
2137 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2138 clingArgs.push_back(platformDefines);
2147 return llvm::sys::path::filename(path).str();
2157 if (std::string::npos != pos) {
2158 dirname.assign(path.begin(), path.begin() + pos + 1);
2169 std::string dictLocation;
2171 return !dictLocation.empty();
2177 std::string &rootmapLibName)
2181 if (rootmapFileName.empty()) {
2183 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2184 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2185 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2187 rootmapLibName.c_str(),
2188 rootmapFileName.c_str());
2197 std::string &ctxtName,
2198 const cling::Interpreter &interpreter,
2199 bool treatParent =
true)
2201 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2203 if (!outerCtxt)
return;
2205 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2215 std::string &ctxtName,
2216 const cling::Interpreter &interpreter)
2218 const clang::DeclContext *theContext = theDecl.getDeclContext();
2226 const cling::Interpreter &interp)
2228 if (!decls.empty()) {
2229 std::string autoLoadKey;
2230 for (
auto &
d : decls) {
2234 if (autoLoadKey.empty()) {
2235 names.push_back(
d->getQualifiedNameAsString());
2253 const std::string &rootmapLibName,
2254 const std::list<std::string> &classesDefsList,
2255 const std::list<std::string> &classesNames,
2256 const std::list<std::string> &nsNames,
2257 const std::list<std::string> &tdNames,
2258 const std::list<std::string> &enNames,
2259 const std::list<std::string> &varNames,
2261 const std::unordered_set<std::string> headersToIgnore)
2264 std::ofstream rootmapFile(rootmapFileName.c_str());
2272 std::unordered_set<std::string> classesKeys;
2276 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2277 !enNames.empty() || !varNames.empty()) {
2280 if (!classesDefsList.empty()) {
2281 rootmapFile <<
"{ decls }\n";
2282 for (
auto & classDef : classesDefsList) {
2283 rootmapFile << classDef << std::endl;
2285 rootmapFile <<
"\n";
2287 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2290 if (!classesNames.empty()) {
2291 rootmapFile <<
"# List of selected classes\n";
2292 for (
auto & className : classesNames) {
2293 rootmapFile <<
"class " << className << std::endl;
2294 classesKeys.insert(className);
2297 std::unordered_set<std::string> treatedHeaders;
2298 for (
auto & className : classesNames) {
2300 if (className.find(
"<") != std::string::npos)
continue;
2301 if (headersClassesMap.count(className)) {
2302 auto &headers = headersClassesMap.at(className);
2303 if (!headers.empty()){
2304 auto &header = headers.front();
2305 if (treatedHeaders.insert(header).second &&
2306 headersToIgnore.find(header) == headersToIgnore.end() &&
2308 rootmapFile <<
"header " << header << std::endl;
2316 if (!nsNames.empty()) {
2317 rootmapFile <<
"# List of selected namespaces\n";
2318 for (
auto & nsName : nsNames) {
2319 rootmapFile <<
"namespace " << nsName << std::endl;
2324 if (!tdNames.empty()) {
2325 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2326 for (
const auto & autoloadKey : tdNames)
2327 if (classesKeys.insert(autoloadKey).second)
2328 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2333 if (!enNames.empty()){
2334 rootmapFile <<
"# List of selected enums and outer classes\n";
2335 for (
const auto & autoloadKey : enNames)
2336 if (classesKeys.insert(autoloadKey).second)
2337 rootmapFile <<
"enum " << autoloadKey << std::endl;
2341 if (!varNames.empty()){
2342 rootmapFile <<
"# List of selected vars\n";
2343 for (
const auto & autoloadKey : varNames)
2344 if (classesKeys.insert(autoloadKey).second)
2345 rootmapFile <<
"var " << autoloadKey << std::endl;
2359 auto nsPattern =
'{';
auto nsPatternLength = 1;
2360 auto foundNsPos =
line.find_last_of(nsPattern);
2361 if (foundNsPos == std::string::npos)
return {
"",
""};
2362 foundNsPos+=nsPatternLength;
2363 auto extNs =
line.substr(0,foundNsPos);
2365 auto nsEndPattern =
'}';
2366 auto foundEndNsPos =
line.find(nsEndPattern);
2367 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2369 return {extNs, contained};
2385 std::map<std::string, std::string> nsEntitiesMap;
2386 std::list<std::string> optFwdDeclList;
2387 for (
auto const & fwdDecl : fwdDeclarationsList){
2390 if (extNsAndEntities.first.empty()) {
2392 optFwdDeclList.push_front(fwdDecl);
2394 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2395 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2399 std::string optFwdDecl;
2400 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2401 optFwdDecl = extNsAndEntities.first;
2402 optFwdDecl += extNsAndEntities.second;
2403 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2406 optFwdDeclList.push_front(optFwdDecl);
2409 return optFwdDeclList;
2417 std::list<std::string> &el_list,
2418 std::unordered_set<std::string> &el_set)
2420 std::stringstream elStream(el);
2423 while (getline(elStream, tmp,
'\n')) {
2425 if (el_set.insert(tmp).second && !tmp.empty()) {
2426 el_list.push_back(tmp);
2437 std::list<std::string> &classesList,
2438 std::list<std::string> &classesListForRootmap,
2439 std::list<std::string> &fwdDeclarationsList,
2440 const cling::Interpreter &interpreter)
2448 std::unordered_set<std::string> classesSet;
2449 std::unordered_set<std::string> outerMostClassesSet;
2451 std::string attrName, attrValue;
2452 bool isClassSelected;
2453 std::unordered_set<std::string> availableFwdDecls;
2454 std::string fwdDeclaration;
2456 fwdDeclaration =
"";
2462 fwdDeclaration =
"";
2469 isClassSelected =
true;
2470 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2471 std::string normalizedName;
2472 normalizedName = selClass.GetNormalizedName();
2473 if (!normalizedName.empty() &&
2474 !classesSet.insert(normalizedName).second &&
2475 outerMostClassesSet.count(normalizedName) == 0) {
2476 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2477 <<
" was already selected. This means that two different instances of"
2478 <<
" clang::RecordDecl had the same name, which is not possible."
2479 <<
" This can be a hint of a serious problem in the class selection."
2480 <<
" In addition, the generated dictionary would not even compile.\n";
2483 classesList.push_back(normalizedName);
2486 const char *reqName(selClass.GetRequestedName());
2489 fwdDeclaration =
"";
2494 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2495 fwdDeclaration =
"";
2498 std::string fwdDeclarationTemplateSpec;
2500 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2508 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2510 attrName ==
"rootmap" &&
2511 attrValue ==
"false") {
2512 attrName = attrValue =
"";
2513 isClassSelected =
false;
2517 if (isClassSelected) {
2533 std::string outerMostClassName;
2535 if (!outerMostClassName.empty() &&
2536 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2537 classesSet.insert(outerMostClassName).second &&
2538 outerMostClassesSet.insert(outerMostClassName).second) {
2539 classesListForRootmap.push_back(outerMostClassName);
2541 classesListForRootmap.push_back(normalizedName);
2542 if (reqName && reqName[0] && reqName != normalizedName) {
2543 classesListForRootmap.push_back(reqName);
2548 std::string demangledName = selClass.GetDemangledTypeInfo();
2549 if (!demangledName.empty()) {
2554 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2556 classesListForRootmap.push_back(demangledName);
2562 classesListForRootmap.sort();
2575 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2590 if (clang::CXXRecordDecl *CXXRD =
2591 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2603 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2606 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2609 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2625 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2626 "#include \"TFile.h\"\n"
2627 "#include \"TObjArray.h\"\n"
2628 "#include \"TVirtualArray.h\"\n"
2629 "#include \"TStreamerElement.h\"\n"
2630 "#include \"TProtoClass.h\"\n"
2631 "#include \"TBaseClass.h\"\n"
2632 "#include \"TListOfDataMembers.h\"\n"
2633 "#include \"TListOfEnums.h\"\n"
2634 "#include \"TListOfEnumsWithLock.h\"\n"
2635 "#include \"TDataMember.h\"\n"
2636 "#include \"TEnum.h\"\n"
2637 "#include \"TEnumConstant.h\"\n"
2638 "#include \"TDictAttributeMap.h\"\n"
2639 "#include \"TMessageHandler.h\"\n"
2640 "#include \"TArray.h\"\n"
2641 "#include \"TRefArray.h\"\n"
2642 "#include \"root_std_complex.h\"\n")
2643 != cling::Interpreter::kSuccess)
2654 cling::Interpreter &interp,
2660 bool writeEmptyRootPCM)
2664 bool needsCollectionProxy =
false;
2686 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2687 if (nsName.find(
"(anonymous)") == std::string::npos)
2692 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2696 if (selClass.RequestOnlyTClass()) {
2704 if (clang::CXXRecordDecl *CXXRD =
2705 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2709 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2717 }
else if (CRD->getName() ==
"RVec") {
2718 static const clang::DeclContext *vecOpsDC =
nullptr;
2720 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2721 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2722 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2730 needsCollectionProxy);
2745 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2749 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2761 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2765 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2770 needsCollectionProxy);
2805 if (finRetCode != 0)
return finRetCode;
2815 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2816 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2819 <<
"#define R__NO_DEPRECATION" << std::endl
2824 <<
"\n/*******************************************************************/\n"
2825 <<
"#include <stddef.h>\n"
2826 <<
"#include <stdio.h>\n"
2827 <<
"#include <stdlib.h>\n"
2828 <<
"#include <string.h>\n"
2829 <<
"#include <assert.h>\n"
2830 <<
"#define G__DICTIONARY\n"
2831 <<
"#include \"ROOT/RConfig.hxx\"\n"
2832 <<
"#include \"TClass.h\"\n"
2833 <<
"#include \"TDictAttributeMap.h\"\n"
2834 <<
"#include \"TInterpreter.h\"\n"
2835 <<
"#include \"TROOT.h\"\n"
2836 <<
"#include \"TBuffer.h\"\n"
2837 <<
"#include \"TMemberInspector.h\"\n"
2838 <<
"#include \"TInterpreter.h\"\n"
2839 <<
"#include \"TVirtualMutex.h\"\n"
2840 <<
"#include \"TError.h\"\n\n"
2841 <<
"#ifndef G__ROOT\n"
2842 <<
"#define G__ROOT\n"
2844 <<
"#include \"RtypesImp.h\"\n"
2845 <<
"#include \"TIsAProxy.h\"\n"
2846 <<
"#include \"TFileMergeInfo.h\"\n"
2847 <<
"#include <algorithm>\n"
2848 <<
"#include \"TCollectionProxyInfo.h\"\n"
2849 <<
"/*******************************************************************/\n\n"
2850 <<
"#include \"TDataMember.h\"\n\n";
2857 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2858 <<
"namespace std {} using namespace std;\n\n";
2864 const std::string &includeForSource,
2865 const std::string &extraIncludes)
2867 dictStream <<
"// Header files passed as explicit arguments\n"
2868 << includeForSource << std::endl
2869 <<
"// Header files passed via #pragma extra_include\n"
2870 << extraIncludes << std::endl;
2876#if defined(R__IOSSIM) || defined(R__IOS)
2901 return filename +
"_tmp_" + std::to_string(getpid());
2908 if (nameStr.empty())
return;
2910 std::string tmpNameStr(getTmpFileName(nameStr));
2913 const char *
name(nameStr.c_str());
2914 const char *tmpName(tmpNameStr.c_str());
2916 m_names.push_back(nameStr);
2917 m_tempNames.push_back(tmpNameStr);
2921 if (0 == std::rename(
name , tmpName)) {
2926 nameStr = tmpNameStr;
2937 for (
unsigned int i = 0; i < m_size; ++i) {
2938 const char *tmpName = m_tempNames[i].c_str();
2940 std::ifstream ifile(tmpName);
2945 if (ifile.is_open())
2947 if (0 != std::remove(tmpName)) {
2960 for (
unsigned int i = 0; i < m_size; ++i) {
2961 const char *tmpName = m_tempNames[i].c_str();
2962 const char *
name = m_names[i].c_str();
2964 std::ifstream ifile(tmpName);
2969 if (ifile.is_open())
2975 if (0 != std::rename(tmpName ,
name)) {
2976 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2977 llvm::sys::fs::remove(tmpName);
2981 if (0 != std::rename(tmpName ,
name)) {
2993 size_t i = std::distance(m_tempNames.begin(),
2994 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2995 if (i == m_tempNames.size())
return m_emptyString;
3002 std::cout <<
"Restoring files in temporary file catalog:\n";
3003 for (
unsigned int i = 0; i < m_size; ++i) {
3004 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3021 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
3022 const size_t dotPos = splitDictName.find_last_of(
".");
3023 splitDictName.insert(dotPos,
"_classdef");
3025 return new std::ofstream(splitDictName.c_str());
3034 std::list<std::string> &diagnosticPragmas)
3036 static const std::string pattern(
"-Wno-");
3038 if (arg.find(pattern) != 0)
3043 diagnosticPragmas.push_back(arg);
3049 cling::Interpreter &interp)
3052 std::string fwdDecl;
3053 std::string initStr(
"{");
3055 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3056 auto &clTemplDecl = *strigNargsToKeepPair.first;
3057 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3060 + std::to_string(strigNargsToKeepPair.second)
3063 if (!fwdDeclnArgsToSkipColl.empty())
3074 if (qt.isNull())
return qt;
3075 clang::QualType thisQt(qt);
3076 while (thisQt->isPointerType() ||
3077 thisQt->isReferenceType()) {
3078 thisQt = thisQt->getPointeeType();
3088 const cling::Interpreter &interp,
3089 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3091 std::list<std::string> headers;
3094 cling::Interpreter::PushTransactionRAII RAII(&interp);
3097 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3101 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3104 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3105 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3107 if (tArgQualType.isNull())
continue;
3108 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3109 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3116 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3118 if (baseQualType.isNull())
continue;
3119 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3120 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3125 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3126 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3128 if (fieldQualType.isNull()) continue ;
3129 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3130 if (fieldCxxRcd->hasDefinition())
3131 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3137 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3139 for (
auto & fPar : methodIt->parameters()) {
3141 if (fParQualType.isNull())
continue;
3142 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3143 if (fParCxxRcd->hasDefinition())
3144 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3149 if (retQualType.isNull())
continue;
3150 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3151 if (retCxxRcd->hasDefinition())
3160 headers.emplace_back(header);
3173 if (
auto dclCtxt= rcd.getDeclContext()){
3174 if (! dclCtxt->isStdNamespace()){
3183 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3184 if (!clAsTmplSpecDecl)
return false;
3189 auto& astCtxt = rcd.getASTContext();
3190 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3191 for (
auto&& arg : templInstArgs.asArray()){
3193 auto argKind = arg.getKind();
3194 if (argKind != clang::TemplateArgument::Type){
3195 if (argKind == clang::TemplateArgument::Integral)
continue;
3199 auto argQualType = arg.getAsType();
3200 auto isPOD = argQualType.isPODType(astCtxt);
3202 if (isPOD)
continue;
3204 auto argType = argQualType.getTypePtr();
3205 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3208 if (isArgGoodForAutoParseMap)
continue;
3227 const cling::Interpreter &interp)
3229 std::set<const clang::CXXRecordDecl *> visitedDecls;
3230 std::unordered_set<std::string> buffer;
3231 std::string autoParseKey;
3234 for (
auto & annotatedRcd : annotatedRcds) {
3235 if (
const clang::CXXRecordDecl *cxxRcd =
3236 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3238 visitedDecls.clear();
3242 headers.remove_if([&buffer](
const std::string & s) {
3243 return !buffer.insert(s).second;
3246 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3248 headersDeclsMap[autoParseKey] = headers;
3249 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3251 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3256 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3257 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3258 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3264 for (
auto & tDef : tDefDecls) {
3265 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3267 visitedDecls.clear();
3272 headers.remove_if([&buffer](
const std::string & s) {
3273 return !buffer.insert(s).second;
3276 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3277 headersDeclsMap[autoParseKey] = headers;
3282 for (
auto & func : funcDecls) {
3288 for (
auto & var : varDecls) {
3294 for (
auto & en : enumDecls) {
3304 const cling::Interpreter &interp)
3306 std::string newFwdDeclString;
3310 std::string fwdDeclString;
3312 std::unordered_set<std::string> fwdDecls;
3333 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3338 selectedDecls.begin(),
3342 selectedDecls.push_back(TD);
3347 std::string fwdDeclLogs;
3355 std::cout <<
"Logs from forward decl printer: \n"
3372 if (fwdDeclString.empty()) fwdDeclString =
"";
3373 return fwdDeclString;
3380 const std::string &detectedUmbrella,
3381 bool payLoadOnly =
false)
3383 std::string headerName;
3386 std::cout <<
"Class-headers Mapping:\n";
3387 std::string headersClassesMapString =
"";
3388 for (
auto const & classHeaders : headersClassesMap) {
3390 std::cout <<
" o " << classHeaders.first <<
" --> ";
3391 headersClassesMapString +=
"\"";
3392 headersClassesMapString += classHeaders.first +
"\"";
3393 for (
auto const & header : classHeaders.second) {
3394 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3395 headersClassesMapString +=
", " + headerName;
3397 std::cout <<
", " << headerName;
3402 std::cout << std::endl;
3403 headersClassesMapString +=
", \"@\",\n";
3405 headersClassesMapString +=
"nullptr";
3406 return headersClassesMapString;
3429 static const std::vector<std::string> namePrfxes {
3432 auto pos = find_if(namePrfxes.begin(),
3434 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3435 return namePrfxes.end() == pos;
3442 static const std::vector<std::string> uclNamePrfxes {
3446 static const std::set<std::string> unsupportedClassesNormNames{
3449 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3450 auto pos = find_if(uclNamePrfxes.begin(),
3451 uclNamePrfxes.end(),
3452 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3453 return uclNamePrfxes.end() == pos;
3463 for (
auto&& aRcd : annotatedRcds){
3464 auto clName = aRcd.GetNormalizedName();
3466 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3467 <<
"currently the support for its I/O is not yet available. Note that "
3468 << clName <<
", even if not selected, will be available for "
3469 <<
"interpreted code.\n";
3473 std::cerr <<
"Error: It is not necessary to explicitly select class "
3474 << clName <<
". I/O is supported for it transparently.\n";
3486 bool isLocked =
false;
3489 InterpreterCallbacks(interp),
3490 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3495 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3496 clang::OptionalFileEntryRef , llvm::StringRef ,
3497 llvm::StringRef ,
const clang::Module * ,
3498 clang::SrcMgr::CharacteristicKind )
override
3500 if (isLocked)
return;
3501 if (IsAngled)
return;
3502 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3503 auto curLexer = PP.getCurrentFileLexer();
3504 if (!curLexer)
return;
3505 auto fileEntry = curLexer->getFileEntry();
3506 if (!fileEntry)
return;
3507 auto thisFileName = fileEntry->getName();
3508 auto fileNameAsString = FileName.str();
3510 if (isThisLinkdef) {
3512 if (isTheIncludedLinkdef) {
3513 fFilesIncludedByLinkdef.clear();
3516 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3530 clang::SourceLocation ImportLoc,
3531 bool ForPragma)
override {
3533 using namespace clang;
3534 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3535 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3536 HeaderSearch& HS = PP.getHeaderSearchInfo();
3538 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3540 assert(M &&
"Must have module Core");
3541 PP.makeModuleVisible(CoreModule, ImportLoc);
3546static llvm::cl::list<std::string>
3549 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3552static llvm::cl::opt<std::string>
3554 llvm::cl::desc(
"<output dictionary file>"),
3574 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3586 using namespace clang::diag;
3592 std::string moduleName;
3593 const clang::Module *module =
nullptr;
3596 const auto &ID =
Info.getID();
3597 if (ID == remark_module_build || ID == remark_module_build_done) {
3598 moduleName =
Info.getArgStdStr(0);
3599 module = fMap.findModule(moduleName);
3605 "Couldn't find module %s in the available modulemaps. This"
3606 "prevents us from correctly diagnosing wrongly built modules.\n",
3607 moduleName.c_str());
3620 bool isByproductModule
3622 if (!isByproductModule)
3623 fChild->HandleDiagnostic(DiagLevel,
Info);
3625 if (ID == remark_module_build && !isByproductModule) {
3627 "Building module '%s' implicitly. If '%s' requires a \n"
3628 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3629 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3631 moduleName.c_str(), moduleName.c_str());
3639 DiagnosticConsumer::clear();
3642 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3644 fChild->BeginSourceFile(LangOpts, PP);
3645 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3650 fChild->EndSourceFile();
3651 DiagnosticConsumer::EndSourceFile();
3657 DiagnosticConsumer::finish();
3664#if defined(_WIN32) && defined(_MSC_VER)
3668 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3669 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3670 ::_set_error_mode(_OUT_TO_STDERR);
3671 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3672 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3673 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3674 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3675 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3676 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3681static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3683static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3694static llvm::cl::opt<VerboseLevel>
3696 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3697 clEnumVal(
v0,
"Show only fatal errors."),
3698 clEnumVal(
v1,
"Show errors (the same as -v)."),
3699 clEnumVal(
v2,
"Show warnings (default)."),
3700 clEnumVal(
v3,
"Show notes."),
3701 clEnumVal(
v4,
"Show information.")),
3705static llvm::cl::opt<bool>
3706gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3709static llvm::cl::opt<bool>
3710gOptReflex(
"reflex", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3713static llvm::cl::opt<bool>
3714gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3717static llvm::cl::opt<std::string>
3719 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3722static llvm::cl::opt<bool>
3724 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3727static llvm::cl::opt<bool>
3728gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3730static llvm::cl::opt<bool>
3731gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3733static llvm::cl::list<std::string>
3735 llvm::cl::desc(
"Generate rootmap file."),
3737static llvm::cl::opt<std::string>
3739 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3741static llvm::cl::opt<bool>
3743 llvm::cl::desc(
"Generate a C++ module."),
3745static llvm::cl::list<std::string>
3747 llvm::cl::desc(
"Specify a C++ modulemap file."),
3750static llvm::cl::opt<bool>
3752 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3754static llvm::cl::opt<bool>
3756 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3758static llvm::cl::opt<bool>
3760 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3762static llvm::cl::opt<bool>
3764 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3766static llvm::cl::opt<bool>
3768 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3769information and another the interactivity support."),
3771static llvm::cl::opt<bool>
3774 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3776static llvm::cl::opt<std::string>
3778 llvm::cl::desc(
"The path to the library of the built dictionary."),
3780static llvm::cl::list<std::string>
3782 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3784static llvm::cl::list<std::string>
3786 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3790static llvm::cl::opt<bool>
3792 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3800static llvm::cl::opt<bool>
3803 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3805static llvm::cl::opt<bool>
3807 llvm::cl::desc(
"Check the selection syntax only."),
3809static llvm::cl::opt<bool>
3811 llvm::cl::desc(
"Fail if there are warnings."),
3813static llvm::cl::opt<bool>
3815 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3817static llvm::cl::opt<std::string>
3819 llvm::cl::desc(
"Specify an isysroot."),
3821 llvm::cl::init(
"-"));
3822static llvm::cl::list<std::string>
3824 llvm::cl::desc(
"Specify an include path."),
3826static llvm::cl::list<std::string>
3828 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3830static llvm::cl::list<std::string>
3832 llvm::cl::desc(
"Specify a system include path."),
3834static llvm::cl::list<std::string>
3836 llvm::cl::desc(
"Specify defined macros."),
3838static llvm::cl::list<std::string>
3840 llvm::cl::desc(
"Specify undefined macros."),
3842static llvm::cl::list<std::string>
3844 llvm::cl::desc(
"Specify compiler diagnostics options."),
3847static llvm::cl::list<std::string>
3849 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file>"),
3851static llvm::cl::list<std::string>
3853 llvm::cl::desc(
"Consumes all unrecognized options."),
3856static llvm::cl::SubCommand
3859static llvm::cl::list<std::string>
3861 llvm::cl::desc(
"Consumes options and sends them to cling."),
3871 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3874 std::vector<clang::Module::Header> moduleHeaders;
3876 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3878 bool foundAllHeaders =
true;
3880 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3881 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3882 if (header == moduleHeader.NameAsWritten)
3890 for (
const std::string &header : modGen.
GetHeaders()) {
3891 if (isHeaderInModule(header))
3894 clang::ModuleMap::KnownHeader SuggestedModule;
3895 clang::ConstSearchDirIterator *CurDir =
nullptr;
3896 if (
auto FE = headerSearch.LookupFile(
3897 header, clang::SourceLocation(),
3900 clang::ArrayRef<std::pair<const clang::FileEntry *, const clang::DirectoryEntry *>>(),
3903 0, &SuggestedModule,
3910 if (
auto OtherModule = SuggestedModule.getModule()) {
3911 std::string OtherModuleName;
3912 auto TLM = OtherModule->getTopLevelModuleName();
3914 OtherModuleName = TLM.str();
3916 OtherModuleName = OtherModule->Name;
3923 missingHeaders.push_back({header, OtherModuleName});
3926 missingHeaders.push_back({header, {}});
3928 foundAllHeaders =
false;
3930 return foundAllHeaders;
3936 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3938 clang::CompilerInstance *CI = interpreter.getCI();
3939 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3940 headerSearch.loadTopLevelSystemModules();
3943 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3948 moduleName.c_str());
3955 std::vector<std::array<std::string, 2>> missingHdrMod;
3958 std::stringstream msgStream;
3959 msgStream <<
"after creating module \"" << module->Name <<
"\" ";
3960 if (!module->PresumedModuleMapFile.empty())
3961 msgStream <<
"using modulemap \"" << module->PresumedModuleMapFile <<
"\" ";
3962 msgStream <<
"the following headers are not part of that module:\n";
3963 for (
auto &
H : missingHdrMod) {
3964 msgStream <<
" " <<
H[0];
3966 msgStream <<
" (already part of module \"" <<
H[1] <<
"\")";
3969 std::string warningMessage = msgStream.str();
3971 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3982 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3983 warningMessage.c_str(),
3990 std::vector<std::string> missingHeaders;
3991 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
3992 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
3995 module->Name.c_str());
4005 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
4006 moduleName.consume_front(
"lib");
4007 moduleName.consume_back(
".pcm");
4008 moduleName.consume_back(
"_rdict");
4016 bool isGenreflex =
false)
4027 const char *executableFileName = argv[0];
4029 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
4030 llvm::PrettyStackTraceProgram
X(argc, argv);
4033#if defined(R__WIN32) && !defined(R__WINGCC)
4038 for (
int iic = 1 ; iic < argc; ++iic) {
4039 std::string iiarg(argv[iic]);
4041 size_t len = iiarg.length();
4043 char *argviic =
new char[
len + 1];
4044 strlcpy(argviic, iiarg.c_str(),
len + 1);
4045 argv[iic] = argviic;
4054 auto &opts = llvm::cl::getRegisteredOptions();
4055 llvm::cl::Option* optHelp = opts[
"help"];
4056 llvm::cl::alias optHelpAlias1(
"h",
4057 llvm::cl::desc(
"Alias for -help"),
4058 llvm::cl::aliasopt(*optHelp));
4059 llvm::cl::alias optHelpAlias2(
"?",
4060 llvm::cl::desc(
"Alias for -help"),
4061 llvm::cl::aliasopt(*optHelp));
4063 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
4067 std::vector<const char *> clingArgsC;
4068 clingArgsC.push_back(executableFileName);
4070 clingArgsC.push_back(
"-I");
4077 clingArgsC.push_back(Opt.c_str());
4079 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
4081 llvmResourceDir.c_str());
4084 return interp->getDiagnostics().hasFatalErrorOccurred();
4087 std::string dictname;
4101 llvm::cl::PrintHelpMessage();
4116 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
4117 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4144 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4145 llvm::cl::PrintHelpMessage();
4149 std::vector<std::string> clingArgs;
4150 clingArgs.push_back(executableFileName);
4151 clingArgs.push_back(
"-iquote.");
4157 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4163 if (GetErrorIgnoreLevel() >
kWarning)
4165 GetWarningsAreErrors() =
true;
4179 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4184 clingArgs.push_back(std::string(
"-D") + PPDefine);
4187 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4190 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4197 clingArgs.push_back(
"-isystem");
4198 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4202 for (
const std::string &WDiag :
gOptWDiags) {
4203 const std::string FullWDiag = std::string(
"-W") + WDiag;
4207 clingArgs.push_back(FullWDiag);
4211 clingArgs.push_back(std::string(
"-I") + includeDir);
4213 std::vector<std::string> pcmArgs;
4214 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4215 auto thisArg = clingArgs[parg];
4217 if (thisArg ==
"-c" ||
4223 while (
c ==
' ')
c = thisArg[++
offset];
4227 [&](
const std::string& path){
4228 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4229 if (excludePathsEnd != excludePathPos)
continue;
4231 pcmArgs.push_back(thisArg);
4238 clingArgs.push_back(
"-D__ROOTCLING__");
4241 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4242#elif defined(R__WIN32)
4243 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4246 clingArgs.push_back(
"-D_XKEYCHECK_H");
4248 clingArgs.push_back(
"-DNOMINMAX");
4250 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4253 clingArgs.push_back(
"-fsyntax-only");
4255 clingArgs.push_back(
"-fPIC");
4257 clingArgs.push_back(
"-Xclang");
4258 clingArgs.push_back(
"-fmodules-embed-all-files");
4259 clingArgs.push_back(
"-Xclang");
4260 clingArgs.push_back(
"-main-file-name");
4261 clingArgs.push_back(
"-Xclang");
4262 clingArgs.push_back((dictname +
".h").c_str());
4270 std::string outputFile;
4272 llvm::StringRef moduleName;
4277 auto clingArgsInterpreter = clingArgs;
4286 clingArgsInterpreter.push_back(
"-fmodules");
4287 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4290 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4292 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4296 if (llvm::sys::fs::exists(ModuleMapCWD))
4297 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4305 clingArgsInterpreter.push_back(
"-Xclang");
4306 clingArgsInterpreter.push_back(
"-fmodule-feature");
4307 clingArgsInterpreter.push_back(
"-Xclang");
4310 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4320 if (moduleName ==
"Core") {
4322 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4323 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4324 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4325 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4327 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4328 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4332 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4334 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4336 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4337 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4338 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4339 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4340 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4341 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4342 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4343 }
else if (moduleName ==
"MathCore") {
4344 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4349 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4353 clingArgsInterpreter.push_back(
"-v");
4356 std::vector<const char *> clingArgsC;
4357 for (
auto const &clingArg : clingArgsInterpreter) {
4359 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4360 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4363 clingArgsC.push_back(clingArg.c_str());
4367 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4368 cling::Interpreter* interpPtr =
nullptr;
4370 std::list<std::string> filesIncludedByLinkdef;
4374 clingArgsC.push_back(
"-ffast-math");
4377 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4378 llvmResourceDir.c_str()));
4379 interpPtr = owningInterpPtr.get();
4382 clingArgsC.push_back(
"-resource-dir");
4383 clingArgsC.push_back(llvmResourceDir.c_str());
4384 clingArgsC.push_back(
nullptr);
4386 extraArgs = &clingArgsC[1];
4389 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4390 interpPtr->setCallbacks(std::move(callBacks));
4393 cling::Interpreter &interp = *interpPtr;
4394 clang::CompilerInstance *CI = interp.getCI();
4396 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4397 CI->getSourceManager().setAllFilesAreTransient(
true);
4399 clang::Preprocessor &PP = CI->getPreprocessor();
4400 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4401 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4402 auto &diags = interp.getDiagnostics();
4409 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4414 diags.setClient(recordingClient,
true);
4420 interp.DumpIncludePath();
4425 interp.printIncludedFiles(llvm::outs());
4426 llvm::outs() <<
"\n\n";
4427 llvm::outs().flush();
4430 const clang::LangOptions& LangOpts
4431 = interp.getCI()->getASTContext().getLangOpts();
4432#define LANGOPT(Name, Bits, Default, Description) \
4433 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4434#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4435#include "clang/Basic/LangOptions.def"
4439 interp.getOptions().ErrorOut =
true;
4440 interp.enableRawInput(
true);
4444 if (DepMod.endswith(
"_rdict.pcm")) {
4451 cling::Interpreter::PushTransactionRAII RAII(&interp);
4452 if (!interp.loadModule(DepMod.str(),
false)) {
4461 if (interp.declare(
"#include <assert.h>\n"
4462 "#include \"Rtypes.h\"\n"
4463 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4471 if (interp.declare(
"#include <string>\n"
4472 "#include <RtypesCore.h>\n"
4473 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4484 clingArgs.push_back(
"-D__CINT__");
4485 clingArgs.push_back(
"-D__MAKECINT__");
4491 std::string interpPragmaSource;
4492 std::string includeForSource;
4493 std::string interpreterDeclarations;
4494 std::string linkdef;
4500 if (isSelectionFile) {
4502 linkdef = optHeaderFileName;
4505 executableFileName, optHeaderFileName.c_str());
4511 std::string fullheader(optHeaderFileName);
4514 if (fullheader[fullheader.length() - 1] ==
'+') {
4515 fullheader.erase(fullheader.length() - 1);
4520 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4521 if (!isSelectionFile) {
4529 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4530 pcmArgs.push_back(header);
4532 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4537 bool hasSelectionFile = !linkdef.empty();
4538 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4549 if (!newName.empty())
4562 string incCurDir =
"-I";
4563 incCurDir += currentDirectory;
4564 pcmArgs.push_back(incCurDir);
4569 std::stringstream res;
4570 const char* delim=
"\n";
4571 std::copy(diagnosticPragmas.begin(),
4572 diagnosticPragmas.end(),
4573 std::ostream_iterator<std::string>(res, delim));
4574 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4580 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4582 IgnoringPragmaHandler(
const char* pragma):
4583 clang::PragmaNamespace(pragma) {}
4584 void HandlePragma(clang::Preprocessor &PP,
4585 clang::PragmaIntroducer Introducer,
4586 clang::Token &tok)
override {
4587 PP.DiscardUntilEndOfDirective();
4593 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4594 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4595 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4596 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4598 if (!interpreterDeclarations.empty() &&
4599 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4611 pcmArgs.push_back(linkdef);
4619 interp.AddIncludePath(inclPath);
4621 std::stringstream definesUndefinesStr;
4624 if (!definesUndefinesStr.str().empty()) {
4625 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4626 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4637 if (linkdef.empty()) {
4643 std::ofstream fileout;
4645 std::ostream *splitDictStream =
nullptr;
4646 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4668 splitDeleter.reset(splitDictStream);
4670 splitDictStream = &dictStream;
4673 size_t dh = main_dictname.rfind(
'.');
4674 if (dh != std::string::npos) {
4675 main_dictname.erase(dh);
4678 std::string main_dictname_copy(main_dictname);
4700 string linkdefFilename;
4701 if (linkdef.empty()) {
4702 linkdefFilename =
"in memory";
4704 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4712 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4718 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4720 std::string extraIncludes;
4725 const unsigned int selRulesInitialSize = selectionRules.
Size();
4729 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4733 int rootclingRetCode(0);
4737 std::ifstream file(linkdefFilename.c_str());
4738 if (file.is_open()) {
4751 clingArgs.push_back(
"-Ietc/cling/cint");
4753 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4754 llvmResourceDir.c_str())) {
4756 rootclingRetCode += 1;
4766 }
else if (isSelXML) {
4770 std::ifstream file(linkdefFilename.c_str());
4771 if (file.is_open()) {
4775 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4811 dictStream <<
"#include \"TBuffer.h\"\n"
4812 <<
"#include \"TVirtualObject.h\"\n"
4813 <<
"#include <vector>\n"
4814 <<
"#include \"TSchemaHelper.h\"\n\n";
4816 std::list<std::string> includes;
4818 for (
auto & incFile : includes) {
4819 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4821 dictStream << std::endl;
4826 int scannerVerbLevel = 0;
4829 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4831 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4854 scan.
Scan(CI->getASTContext());
4856 bool has_input_error =
false;
4863 !dictSelRulesPresent &&
4870 if (rootclingRetCode)
return rootclingRetCode;
4877 if (annRcd.RequestNoInputOperator()) {
4889 if (has_input_error) {
4899 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4900 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4928 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4929 constructorTypes.emplace_back(
"__void__", interp);
4930 constructorTypes.emplace_back(
"", interp);
4961 if (rootclingRetCode != 0) {
4962 return rootclingRetCode;
4981 std::string detectedUmbrella;
4982 for (
auto & arg : pcmArgs) {
4984 detectedUmbrella = arg;
4990 headersDeclsMap.clear();
4994 std::string headersClassesMapString =
"\"\"";
4995 std::string fwdDeclsString =
"\"\"";
5011 if (modGen.
IsPCH()) {
5014 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
5024 ofstream outputfile(liblist_filename.c_str(), ios::out);
5027 executableFileName, liblist_filename.c_str());
5029 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
5030 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
5032 outputfile <<
"# Now the list of classes\n";
5037 outputfile << annRcd.GetNormalizedName() << endl;
5044 if (0 != rootclingRetCode)
return rootclingRetCode;
5050 [](
const std::string &
a,
const std::string &
b) -> std::string {
5051 if (a.empty()) return b;
5052 else return a +
" " + b;
5057 std::list<std::string> classesNames;
5058 std::list<std::string> classesNamesForRootmap;
5059 std::list<std::string> classesDefsList;
5063 classesNamesForRootmap,
5067 std::list<std::string> enumNames;
5072 std::list<std::string> varNames;
5077 if (0 != rootclingRetCode)
return rootclingRetCode;
5080 if (rootMapNeeded) {
5082 std::list<std::string> nsNames;
5091 rootmapLibName.c_str());
5094 std::unordered_set<std::string> headersToIgnore;
5097 headersToIgnore.insert(optHeaderFileName.c_str());
5099 std::list<std::string> typedefsRootmapLines;
5107 classesNamesForRootmap,
5109 typedefsRootmapLines,
5115 if (0 != rootclingRetCode)
return 1;
5125 cling::Interpreter::PushTransactionRAII RAII(&interp);
5126 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5137 if(rootclingRetCode == 0) {
5138 rootclingRetCode += tmpCatalog.
commit();
5143 return rootclingRetCode;
5154 unsigned int numberOfHeaders = 0;
5155 for (std::vector<std::string>::iterator it = headersNames.begin();
5156 it != headersNames.end(); ++it) {
5157 const std::string headername(*it);
5162 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5163 headername.c_str());
5166 return numberOfHeaders;
5172 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5175 unsigned int argvCounter = 0;
5176 for (
int i = 1; i < argc; ++i) {
5179 args.push_back(argv[i]);
5181 }
else if (argvCounter) {
5182 argv[i - argvCounter] = argv[i];
5189 std::cout <<
"Args: \n";
5190 for (std::vector<std::string>::iterator it = args.begin();
5191 it < args.end(); ++it) {
5192 std::cout << i <<
") " << *it << std::endl;
5206 if (std::string::npos !=
result) {
5218 const unsigned int size(str.size());
5219 char *
a =
new char[
size + 1];
5221 memcpy(
a, str.c_str(),
size);
5237 std::vector<std::string> &ofilesnames)
5239 ofilesnames.reserve(headersNames.size());
5241 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5242 it != headersNames.end(); ++it) {
5243 std::string ofilename(*it);
5245 ofilesnames.push_back(ofilename);
5252 const std::vector<std::string> &argsToBeAdded,
5253 const std::string &optName =
"")
5255 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5256 it != argsToBeAdded.end(); ++it) {
5264 const std::vector<std::string> &argsToBeAdded,
5265 const std::string &optName =
"")
5267 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5268 it != argsToBeAdded.end(); ++it) {
5269 if (optName.length()) {
5279 const std::string &selectionFileName,
5280 const std::string &targetLibName,
5282 const std::vector<std::string> &pcmsNames,
5283 const std::vector<std::string> &includes,
5284 const std::vector<std::string> &preprocDefines,
5285 const std::vector<std::string> &preprocUndefines,
5286 const std::vector<std::string> &warnings,
5287 const std::string &rootmapFileName,
5288 const std::string &rootmapLibName,
5289 bool interpreteronly,
5292 bool writeEmptyRootPCM,
5294 bool noIncludePaths,
5295 bool noGlobalUsingStd,
5296 const std::vector<std::string> &headersNames,
5297 bool failOnWarnings,
5298 const std::string &ofilename)
5302 std::vector<char *> argvVector;
5313 std::string dictLocation;
5319 std::string newRootmapLibName(rootmapLibName);
5320 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5321 if (headersNames.size() != 1) {
5323 "*** genreflex: No rootmap lib and several header specified!\n");
5326 newRootmapLibName =
"lib";
5327 newRootmapLibName += cleanHeaderName;
5333 std::string newRootmapFileName(rootmapFileName);
5334 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5335 newRootmapFileName = dictLocation + newRootmapFileName;
5340 if (!newRootmapFileName.empty()) {
5346 if (!newRootmapLibName.empty()) {
5352 if (interpreteronly)
5360 if (!targetLibName.empty()) {
5370 if (noGlobalUsingStd)
5380 if (writeEmptyRootPCM)
5403 if (!selectionFileName.empty()) {
5407 const int argc = argvVector.size();
5411 std::cout <<
"Rootcling commandline:\n";
5412 for (
int i = 0; i < argc; i++)
5413 std::cout << i <<
") " << argvVector[i] << std::endl;
5416 char **argv = & (argvVector[0]);
5421 for (
int i = 0; i < argc; i++)
5422 delete [] argvVector[i];
5424 return rootclingReturnCode;
5433 const std::string &selectionFileName,
5434 const std::string &targetLibName,
5436 const std::vector<std::string> &pcmsNames,
5437 const std::vector<std::string> &includes,
5438 const std::vector<std::string> &preprocDefines,
5439 const std::vector<std::string> &preprocUndefines,
5440 const std::vector<std::string> &warnings,
5441 const std::string &rootmapFileName,
5442 const std::string &rootmapLibName,
5443 bool interpreteronly,
5446 bool writeEmptyRootPCM,
5448 bool noIncludePaths,
5449 bool noGlobalUsingStd,
5450 const std::vector<std::string> &headersNames,
5451 bool failOnWarnings,
5452 const std::string &outputDirName_const =
"")
5454 std::string outputDirName(outputDirName_const);
5456 std::vector<std::string> ofilesNames;
5463 std::vector<std::string> namesSingleton(1);
5464 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5465 namesSingleton[0] = headersNames[i];
5466 std::string ofilenameFullPath(ofilesNames[i]);
5467 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5468 ofilenameFullPath = outputDirName + ofilenameFullPath;
5490 if (returnCode != 0)
5505 std::vector<std::string> &values)
5508 if (options[oIndex]) {
5509 const int nVals = options[oIndex].count();
5510 values.reserve(nVals);
5511 int optionIndex = 0;
5514 << optionIndex <<
"/" << nVals <<
" "
5515 << opt->arg << std::endl;
5517 values.push_back(opt->arg);
5528 const char *descriptor)
5530 if (options[optionIndex]) {
5532 "*** genereflex: %s is not supported anymore.\n",
5589 enum optionIndex { UNKNOWN,
5620 enum optionTypes { NOTYPE, STRING } ;
5623 const char *genreflexUsage =
5624 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5625 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5628 const char *selectionFilenameUsage =
5629 "-s, --selection_file\tSelection filename\n"
5630 " Class selection file to specify for which classes the dictionary\n"
5631 " will be generated. The final set can be crafted with exclusion and\n"
5632 " exclusion rules.\n"
5633 " Properties can be specified. Some have special meaning:\n"
5634 " - name [string] name of the entity to select with an exact matching\n"
5635 " - pattern [string] name with wildcards (*) to select entities\n"
5636 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5637 " file where the C++ entities reside and not to C++ entities themselves.\n"
5638 " - transient/persistent [string: true/false] The fields to which they are\n"
5639 " applied will not be persistified if requested.\n"
5640 " - comment [string]: what you could write in code after an inline comment\n"
5641 " without \"//\". For example comment=\"!\" or \"||\".\n"
5642 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5643 " Default value is 'false'\n"
5644 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5645 " to 'true'. Default value is 'false'\n"
5649 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5650 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5651 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5652 " [noInputOperator=\"true/false\"] />\n"
5653 " <class name=\"classname\" >\n"
5654 " <field name=\"m_transient\" transient=\"true\"/>\n"
5655 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5656 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5657 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5659 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5660 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5661 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5664 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5665 " <method name=\"unwanted\" />\n"
5670 " If no selection file is specified, the class with the filename without\n"
5671 " extension will be selected, i.e. myClass.h as argument without any\n"
5672 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5674 const char *outputFilenameUsage =
5675 "-o, --output\tOutput filename\n"
5676 " Output file name. If an existing directory is specified instead of a file,\n"
5677 " then a filename will be built using the name of the input file and will\n"
5678 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5679 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5680 " have unique names.\n";
5683 const char *targetLib =
5684 "-l, --library\tTarget library\n"
5685 " The flag -l must be followed by the name of the library that will\n"
5686 " contain the object file corresponding to the dictionary produced by\n"
5687 " this invocation of genreflex.\n"
5688 " The name takes priority over the one specified for the rootmapfile.\n"
5689 " The name influences the name of the created pcm:\n"
5690 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5691 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5692 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5693 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5694 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5696 const char *rootmapUsage =
5697 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5698 " This file lists the autoload keys. For example classes for which the\n"
5699 " reflection information is provided.\n"
5700 " The format of the rootmap is the following:\n"
5701 " - Forward declarations section\n"
5702 " - Libraries sections\n"
5703 " Rootmaps can be concatenated together, for example with the cat util.\n"
5704 " In order for ROOT to pick up the information in the rootmaps, they\n"
5705 " have to be located in the library path and have the .rootmap extension.\n"
5706 " An example rootmap file could be:\n"
5708 " template <class T> class A;\n"
5709 " [ libMyLib.so ]\n"
5710 " class A<double>\n"
5715 const char *rootmapLibUsage =
5716 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5749 "--multiDict\tSupport for many dictionaries in one library\n"
5750 " Form correct pcm names if multiple dictionaries will be in the same\n"
5751 " library (needs target library switch. See its documentation).\n"
5758 "" ,
"noGlobalUsingStd" ,
5760 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5761 " All header files must have sumbols from std:: namespace fully qualified\n"
5767 "s" ,
"selection_file" ,
5769 selectionFilenameUsage
5783 "" ,
"rootmap-lib" ,
5791 "" ,
"interpreteronly",
5793 "--interpreteronly\tDo not generate I/O related information.\n"
5794 " Generate minimal dictionary required for interactivity.\n"
5802 "--split\tSplit the dictionary\n"
5803 " Split in two the dictionary, isolating the part with\n"
5804 " ClassDef related functions in a separate file.\n"
5812 "-m \tPcm file loaded before any header (option can be repeated).\n"
5820 "-v, --verbose\tPrint some debug information.\n"
5828 "--debug\tPrint all debug information.\n"
5836 "--quiet\tPrint only warnings and errors (default).\n"
5844 "--silent\tPrint no information at all.\n"
5850 "" ,
"writeEmptyPCM",
5852 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5860 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5869 "--help\tPrint usage and exit.\n"
5875 "",
"fail_on_warnings",
5877 "--fail_on_warnings\tFail on warnings and errors.\n"
5883 "",
"selSyntaxOnly",
5885 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5891 "" ,
"noIncludePaths",
5893 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5932 "" ,
"no_membertypedefs" ,
5940 "" ,
"no_templatetypedefs" ,
5945 {0, 0,
nullptr,
nullptr,
nullptr,
nullptr}
5948 std::vector<std::string> headersNames;
5949 const int originalArgc = argc;
5951 const int extractedArgs = extractArgs(argc, argv, headersNames);
5954 argc -=
offset + extractedArgs;
5959 std::vector<ROOT::option::Option> options(stats.
options_max);
5960 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5966 if (parse.
error()) {
5972 if (options[HELP] || originalArgc == 1) {
5977 int numberOfHeaders = checkHeadersNames(headersNames);
5978 if (0 == numberOfHeaders) {
5989 std::string verbosityOption(
"-v2");
5990 if (options[SILENT]) verbosityOption =
"-v0";
5991 if (options[VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5992 if (options[
DEBUG]) verbosityOption =
"-v4";
5997 std::string selectionFileName;
5998 if (options[SELECTIONFILENAME]) {
5999 selectionFileName = options[SELECTIONFILENAME].arg;
6002 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
6003 selectionFileName.c_str());
6018 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
6019 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
6022 std::string targetLibName;
6023 if (options[TARGETLIB]) {
6024 targetLibName = options[TARGETLIB].arg;
6027 "Invalid target library extension: filename is %s and extension %s is expected!\n",
6028 targetLibName.c_str(),
6032 if (options[ROOTMAP]) {
6037 bool isCxxmodule = options[CXXMODULE];
6039 bool multidict =
false;
6040 if (options[MULTIDICT]) multidict =
true;
6042 bool noGlobalUsingStd =
false;
6043 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
6045 if (multidict && targetLibName.empty()) {
6047 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
6051 bool interpreteronly =
false;
6052 if (options[INTERPRETERONLY])
6053 interpreteronly =
true;
6055 bool doSplit =
false;
6059 bool writeEmptyRootPCM =
false;
6060 if (options[WRITEEMPTYROOTPCM])
6061 writeEmptyRootPCM =
true;
6063 bool selSyntaxOnly =
false;
6064 if (options[SELSYNTAXONLY]) {
6065 selSyntaxOnly =
true;
6068 bool noIncludePaths =
false;
6069 if (options[NOINCLUDEPATHS]) {
6070 noIncludePaths =
true;
6073 bool failOnWarnings =
false;
6074 if (options[FAILONWARNINGS]) {
6075 failOnWarnings =
true;
6084 std::vector<std::string> pcmsNames;
6088 std::vector<std::string> preprocDefines;
6092 std::vector<std::string> preprocUndefines;
6096 std::vector<std::string> includes;
6100 std::vector<std::string> warnings;
6111 int returnValue = 0;
6112 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6116 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6117 returnValue = invokeRootCling(verbosityOption,
6140 returnValue = invokeManyRootCling(verbosityOption,
6173 assert(!
gDriverConfig &&
"Driver configuration already set!");
6193 if (std::string::npos != exeName.find(
"genreflex"))
6201 ROOT::TMetaUtils::Info(
nullptr,
"Problems have been detected during the generation of the dictionary.\n");
Select classes and assign properties using C++ syntax.
The file contains utilities which are foundational and could be used across the core component of ROO...
This is the only file required to use The Lean Mean C++ Option Parser.
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void 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 data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
const AttributesMap_t & GetAttributes() const
std::unordered_map< std::string, std::string > AttributesMap_t
Custom diag client for clang that verifies that each implicitly build module is a system module.
CheckModuleBuildClient(clang::DiagnosticConsumer *Child, bool OwnsChild, clang::ModuleMap &Map)
clang::DiagnosticConsumer * fChild
~CheckModuleBuildClient()
virtual void BeginSourceFile(const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) override
virtual void finish() override
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
virtual void clear() override
virtual bool IncludeInDiagnosticCounts() const override
virtual void EndSourceFile() override
const std::list< VariableSelectionRule > & GetFieldSelectionRules() const
bool LoadIncludes(std::string &extraInclude)
bool Parse(SelectionRules &sr, llvm::StringRef code, const std::vector< std::string > &parserArgs, const char *llvmdir)
void GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlClass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
void WriteClassInit(std::ostream &strm, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const ROOT::TMetaUtils::RConstructorTypes &, bool &needCollectionProxy, void(*emitStreamerInfo)(const char *))
void WriteUmbrellaHeader(std::ostream &out) const
Write a header file pulling in the content of this module through a series of #defined,...
const std::string & GetUmbrellaName() const
const std::vector< std::string > & GetIncludePaths() const
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes, bool hasCxxModule) const
const std::vector< std::string > & GetHeaders() const
void WriteContentHeader(std::ostream &out) const
Write a header file describing the content of this module through a series of variables inside the na...
int GetErrorCount() const
const std::string & GetModuleFileName() const
std::ostream & WritePPUndefines(std::ostream &out) const
Write #ifdef FOO # undef FOO #endif
void ParseArgs(const std::vector< std::string > &args)
Parse -I -D -U headers.h SomethingLinkdef.h.
const std::string & GetContentName() const
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO # define FOO=bar #endif
A parsed option from the command line together with its argument if it has one.
Option * next()
Returns a pointer to the next element of the linked list or NULL if called on last().
Checks argument vectors for validity and parses them into data structures that are easier to work wit...
bool error()
Returns true if an unrecoverable error occurred while parsing options.
void Scan(const clang::ASTContext &C)
std::vector< ROOT::TMetaUtils::AnnotatedRecordDecl > ClassColl_t
const DeclsSelRulesMap_t & GetDeclsSelRulesMap() const
FunctionColl_t fSelectedFunctions
std::vector< const clang::FunctionDecl * > FunctionColl_t
NamespaceColl_t fSelectedNamespaces
TypedefColl_t fSelectedTypedefs
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
std::map< const clang::Decl *, const BaseSelectionRule * > DeclsSelRulesMap_t
EnumColl_t fSelectedEnums
std::vector< const clang::TypedefNameDecl * > TypedefColl_t
std::vector< const clang::VarDecl * > VariableColl_t
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
VariableColl_t fSelectedVariables
std::vector< const clang::EnumDecl * > EnumColl_t
ClassColl_t fSelectedClasses
The class representing the collection of selection rules.
bool AreAllSelectionRulesUsed() const
bool SearchNames(cling::Interpreter &interp)
void PrintSelectionRules() const
unsigned int Size() const
void SetSelectionFileType(ESelectionFileTypes fileType)
void InclusionDirective(clang::SourceLocation, const clang::Token &, llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange, clang::OptionalFileEntryRef, llvm::StringRef, llvm::StringRef, const clang::Module *, clang::SrcMgr::CharacteristicKind) override
std::list< std::string > & fFilesIncludedByLinkdef
void EnteredSubmodule(clang::Module *M, clang::SourceLocation ImportLoc, bool ForPragma) override
TRootClingCallbacks(cling::Interpreter *interp, std::list< std::string > &filesIncludedByLinkdef)
bool Parse(const std::string &fileName, SelectionRules &out)
Little helper class to bookkeep the files names which we want to make temporary.
void addFileName(std::string &nameStr)
Adds the name and the associated temp name to the catalog.
const std::string & getFileName(const std::string &tmpFileName)
std::vector< std::string > m_names
std::vector< std::string > m_tempNames
const std::string m_emptyString
std::string getTmpFileName(const std::string &filename)
static bool FromCygToNativePath(std::string &path)
std::string GetCurrentDir()
std::string MakePathRelative(const std::string &path, const std::string &base, bool isBuildingROOT=false)
void printUsage(OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN SchemaRuleClassMap_t gReadRules
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
R__EXTERN SchemaRuleClassMap_t gReadRawRules
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
void Init(TClassEdit::TInterpreterLookupHelper *helper)
void header2outputName(std::string &fileName)
Replace the extension with "_rflx.cpp".
void AddToArgVectorSplit(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
void changeExtension(std::string &filename, const std::string &newExtension)
int invokeRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &ofilename)
int invokeManyRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &outputDirName_const="")
Get the right ofilenames and invoke several times rootcling One invokation per header.
unsigned int checkHeadersNames(std::vector< std::string > &headersNames)
Loop on arguments: stop at the first which starts with -.
void headers2outputsNames(const std::vector< std::string > &headersNames, std::vector< std::string > &ofilesnames)
Get a proper name for the output file.
char * string2charptr(const std::string &str)
The caller is responsible for deleting the string!
unsigned int extractArgs(int argc, char **argv, std::vector< std::string > &args)
Extract the arguments from the command line.
void AddToArgVector(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
int FinalizeStreamerInfoWriting(cling::Interpreter &interp, bool writeEmptyRootPCM=false)
Make up for skipping RegisterModule, now that dictionary parsing is done and these headers cannot be ...
std::list< std::string > CollapseIdenticalNamespaces(const std::list< std::string > &fwdDeclarationsList)
If two identical namespaces are there, just declare one only Example: namespace A { namespace B { fwd...
static llvm::cl::opt< bool > gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
int RootClingMain(int argc, char **argv, bool isGenreflex=false)
static llvm::StringRef GetModuleNameFromRdictName(llvm::StringRef rdictName)
static llvm::cl::opt< bool > gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), llvm::cl::cat(gRootclingOptions), llvm::cl::init("-"))
int STLContainerStreamer(const clang::FieldDecl &m, int rwmode, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
Create Streamer code for an STL container.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static llvm::cl::opt< bool > gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
static llvm::cl::list< std::string > gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), llvm::cl::cat(gRootclingOptions))
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
static void MaybeSuppressWin32CrashDialogs()
void RecordDeclCallback(const clang::RecordDecl *recordDecl)
void CheckClassNameForRootMap(const std::string &classname, map< string, string > &autoloads)
bool Which(cling::Interpreter &interp, const char *fname, string &pname)
Find file name in path specified via -I statements to Cling.
void AdjustRootMapNames(std::string &rootmapFileName, std::string &rootmapLibName)
void AddNamespaceSTDdeclaration(std::ostream &dictStream)
static llvm::cl::list< std::string > gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptModuleByproducts("mByproduct", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("The list of the expected implicit modules build as part of building the current module."), llvm::cl::cat(gRootclingOptions))
map< string, string > gAutoloads
static llvm::cl::opt< bool > gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), llvm::cl::cat(gRootclingOptions))
static bool CheckModuleValid(TModuleGenerator &modGen, const std::string &resourceDir, cling::Interpreter &interpreter, llvm::StringRef LinkdefPath, const std::string &moduleName)
Check moduleName validity from modulemap. Check if this module is defined or not.
static void CheckForMinusW(std::string arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance, llvm::StringRef iSysRoot, clang::Module *module=nullptr)
Write the AST of the given CompilerInstance to the given File while respecting the given isysroot.
static llvm::cl::opt< bool > gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), llvm::cl::cat(gRootclingOptions))
void ExtractFilePath(const std::string &path, std::string &dirname)
Extract the path from a fullpath finding the last \ or / according to the content in gPathSeparator.
int STLStringStreamer(const clang::FieldDecl &m, int rwmode, std::ostream &dictStream)
Create Streamer code for a standard string object.
void CreateDictHeader(std::ostream &dictStream, const std::string &main_dictname)
const char * GetExePath()
Returns the executable path name, used e.g. by SetRootSys().
const std::string gPathSeparator(ROOT::TMetaUtils::GetPathSeparator())
static llvm::cl::list< std::string > gOptBareClingSink(llvm::cl::OneOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes options and sends them to cling."), llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gBareClingSubcommand))
bool InheritsFromTObject(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static bool InjectModuleUtilHeader(const char *argv0, TModuleGenerator &modGen, cling::Interpreter &interp, bool umbrella)
Write the extra header injected into the module: umbrella header if (umbrella) else content header.
static llvm::cl::list< std::string > gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), llvm::cl::cat(gRootclingOptions))
int ExtractClassesListAndDeclLines(RScanner &scan, std::list< std::string > &classesList, std::list< std::string > &classesListForRootmap, std::list< std::string > &fwdDeclarationsList, const cling::Interpreter &interpreter)
void ParseRootMapFileNewFormat(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map, using the new format.
static llvm::cl::OptionCategory gRootclingOptions("rootcling common options")
static llvm::cl::list< std::string > gOptSysIncludePaths("isystem", llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a system include path."), llvm::cl::cat(gRootclingOptions))
void ExtractHeadersForDecls(const RScanner::ClassColl_t &annotatedRcds, const RScanner::TypedefColl_t tDefDecls, const RScanner::FunctionColl_t funcDecls, const RScanner::VariableColl_t varDecls, const RScanner::EnumColl_t enumDecls, HeadersDeclsMap_t &headersClassesMap, HeadersDeclsMap_t &headersDeclsMap, const cling::Interpreter &interp)
bool ParsePragmaLine(const std::string &line, const char *expectedTokens[], size_t *end=nullptr)
Check whether the #pragma line contains expectedTokens (0-terminated array).
static llvm::cl::opt< bool > gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static bool 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.
void GetMostExternalEnclosingClassName(const clang::DeclContext &theContext, std::string &ctxtName, const cling::Interpreter &interpreter, bool treatParent=true)
Extract the proper autoload key for nested classes The routine does not erase the name,...
std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, cling::Interpreter &interp)
int ExtractAutoloadKeys(std::list< std::string > &names, const COLL &decls, const cling::Interpreter &interp)
static llvm::cl::opt< std::string > gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), llvm::cl::cat(gRootclingOptions))
void WriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
#define rootclingStringify(s)
void GetMostExternalEnclosingClassNameFromDecl(const clang::Decl &theDecl, std::string &ctxtName, const cling::Interpreter &interpreter)
static llvm::cl::opt< bool > gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::ZeroOrMore, llvm::cl::desc("<list of dictionary header files> <LinkDef file>"), llvm::cl::cat(gRootclingOptions))
void SetRootSys()
Set the ROOTSYS env var based on the executable location.
bool CheckInputOperator(const char *what, const char *proto, const string &fullname, const clang::RecordDecl *cl, cling::Interpreter &interp)
Check if the specified operator (what) has been properly declared if the user has requested a custom ...
void GenerateNecessaryIncludes(std::ostream &dictStream, const std::string &includeForSource, const std::string &extraIncludes)
void StrcpyArg(string &dest, const char *original)
Copy the command line argument, stripping MODULE/inc if necessary.
static llvm::cl::list< std::string > gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), llvm::cl::cat(gRootclingOptions))
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
static llvm::cl::opt< bool > gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), llvm::cl::cat(gRootclingOptions))
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
static std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
static llvm::cl::opt< bool > gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), llvm::cl::cat(gRootclingOptions))
const char * CopyArg(const char *original)
If the argument starts with MODULE/inc, strip it to make it the name we can use in #includes.
string GetNonConstMemberName(const clang::FieldDecl &m, const string &prefix="")
Return the name of the data member so that it can be used by non-const operation (so it includes a co...
static llvm::cl::list< std::string > gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), llvm::cl::cat(gRootclingOptions))
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
void ExtractSelectedNamespaces(RScanner &scan, std::list< std::string > &nsList)
Loop on selected classes and put them in a list.
static bool IncludeHeaders(const std::vector< std::string > &headers, cling::Interpreter &interpreter)
Includes all given headers in the interpreter.
clang::QualType GetPointeeTypeIfPossible(const clang::QualType &qt)
Get the pointee type if possible.
void AnnotateDecl(clang::CXXRecordDecl &CXXRD, const RScanner::DeclsSelRulesMap_t &declSelRulesMap, cling::Interpreter &interpreter, bool isGenreflex)
static llvm::cl::opt< VerboseLevel > gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), llvm::cl::values(clEnumVal(v, "Show errors."), clEnumVal(v0, "Show only fatal errors."), clEnumVal(v1, "Show errors (the same as -v)."), clEnumVal(v2, "Show warnings (default)."), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), llvm::cl::cat(gRootclingOptions))
void GenerateLinkdef(llvm::cl::list< std::string > &InputFiles, std::string &code_for_parser)
static llvm::cl::opt< std::string > gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include <header> but expands the header content."), llvm::cl::cat(gRootclingOptions))
bool isPointerToPointer(const clang::FieldDecl &m)
int CreateNewRootMapFile(const std::string &rootmapFileName, const std::string &rootmapLibName, const std::list< std::string > &classesDefsList, const std::list< std::string > &classesNames, const std::list< std::string > &nsNames, const std::list< std::string > &tdNames, const std::list< std::string > &enNames, const std::list< std::string > &varNames, const HeadersDeclsMap_t &headersClassesMap, const std::unordered_set< std::string > headersToIgnore)
Generate a rootmap file in the new format, like { decls } namespace A { namespace B { template <typen...
static llvm::cl::opt< std::string > gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::desc("<output dictionary file>"), llvm::cl::cat(gRootclingOptions))
bool IsSelectionXml(const char *filename)
bool IsGoodLibraryName(const std::string &name)
static llvm::cl::opt< bool > gOptReflex("reflex", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
llvm::StringRef GrabIndex(const cling::Interpreter &interp, const clang::FieldDecl &member, int printError)
GrabIndex returns a static string (so use it or copy it immediately, do not call GrabIndex twice in t...
static llvm::cl::opt< bool > gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), llvm::cl::cat(gRootclingOptions))
bool IsSelectionFile(const char *filename)
const std::string GenerateStringFromHeadersForClasses(const HeadersDeclsMap_t &headersClassesMap, const std::string &detectedUmbrella, bool payLoadOnly=false)
Generate a string for the dictionary from the headers-classes map.
bool IsSupportedClassName(const char *name)
static llvm::cl::opt< bool > gOptIgnoreExistingDict("r", llvm::cl::desc("Deprecated. Similar to -f but it ignores the dictionary generation. \
When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptForce("f", llvm::cl::desc("Overwrite <file>s."), llvm::cl::cat(gRootclingOptions))
static void AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules)
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
static llvm::cl::list< std::string > gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), llvm::cl::cat(gRootclingOptions))
int CheckClassesForInterpreterOnlyDicts(cling::Interpreter &interp, RScanner &scan)
bool InheritsFromTSelector(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static void EmitTypedefs(const std::vector< const clang::TypedefNameDecl * > &tdvec)
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
bool Namespace__HasMethod(const clang::NamespaceDecl *cl, const char *name, const cling::Interpreter &interp)
static llvm::cl::list< std::string > gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), llvm::cl::cat(gRootclingOptions))
bool IsCorrectClingArgument(const std::string &argument)
Check if the argument is a sane cling argument.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)
void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream &dictStream, bool autoLoad=false)
Write the code to set the class name and the initialization object.
static llvm::cl::list< std::string > gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the <path> in the dictionary."), llvm::cl::cat(gRootclingOptions))
std::list< std::string > RecordDecl2Headers(const clang::CXXRecordDecl &rcd, const cling::Interpreter &interp, std::set< const clang::CXXRecordDecl * > &visitedDecls)
Extract the list of headers necessary for the Decl.
void EmitStreamerInfo(const char *normName)
static llvm::cl::opt< bool > gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), llvm::cl::cat(gRootclingOptions))
bool HasPath(const std::string &name)
Check if file has a path.
static llvm::cl::opt< std::string > gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), llvm::cl::cat(gRootclingOptions))
int CheckForUnsupportedClasses(const RScanner::ClassColl_t &annotatedRcds)
Check if the list of selected classes contains any class which is not supported.
static void EmitEnums(const std::vector< const clang::EnumDecl * > &enumvec)
int GenerateFullDict(std::ostream &dictStream, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool isSelXML, bool writeEmptyRootPCM)
bool CheckClassDef(const clang::RecordDecl &cl, const cling::Interpreter &interp)
Return false if the class does not have ClassDef even-though it should.
bool NeedsSelection(const char *name)
int extractMultipleOptions(std::vector< ROOT::option::Option > &options, int oIndex, std::vector< std::string > &values)
Extract from options multiple values with the same option.
int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
cling::Interpreter *(* fTCling__GetInterpreter)()
bool(* fCloseStreamerInfoROOTFile)(bool writeEmptyRootPCM)
void(* fAddEnumToROOTFile)(const char *tdname)
void(* fInitializeStreamerInfoROOTFile)(const char *filename)
const char *(* fTROOT__GetIncludeDir)()
void(* fAddTypedefToROOTFile)(const char *tdname)
const char *(* fTROOT__GetEtcDir)()
void(* fAddStreamerInfoToROOTFile)(const char *normName)
const char ***(* fTROOT__GetExtraInterpreterArgs)()
static ArgStatus None(const Option &, bool)
For options that don't take an argument: Returns ARG_NONE.
Describes an option, its help text (usage) and how it should be parsed.
static option::ArgStatus Required(const option::Option &option, bool msg)
Determines the minimum lengths of the buffer and options arrays used for Parser.
unsigned options_max
Number of elements needed for an options[] array to be used for parsing the same argument vectors tha...
unsigned buffer_max
Number of elements needed for a buffer[] array to be used for parsing the same argument vectors that ...
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.