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
151static llvm::cl::opt<bool>
153 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
154When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
174static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
178 for (
const auto td : tdvec)
181static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
185 for (
const auto en : enumvec) {
187 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
188 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
189 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
199 static std::string exepath;
202 exepath = _dyld_get_image_name(0);
204#if defined(__linux) || defined(__linux__)
205 char linkname[PATH_MAX];
211 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
212 int ret = readlink(linkname, buf, 1024);
213 if (ret > 0 && ret < 1024) {
219 procstat* ps = procstat_open_sysctl();
220 kinfo_proc* kp = kinfo_getproc(getpid());
223 char path_str[PATH_MAX] =
"";
224 procstat_getpathname(ps, kp, path_str,
sizeof(path_str));
232 char *buf =
new char[MAX_MODULE_NAME32 + 1];
233 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
235 while ((
p = strchr(
p,
'\\')))
241 return exepath.c_str();
247 const cling::Interpreter &interp)
255 const std::list<VariableSelectionRule> &fieldSelRules)
263 if (fieldSelRules.empty())
return;
265 clang::ASTContext &C = decl.getASTContext();
267 const std::string declName(decl.getNameAsString());
269 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
270 it != fieldSelRules.end(); ++it) {
271 if (! it->GetAttributeValue(propNames::name, varName))
continue;
272 if (declName == varName) {
275 BaseSelectionRule::AttributesMap_t::iterator iter;
276 std::string userDefinedProperty;
277 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
278 const std::string &
name = iter->first;
279 const std::string &
value = iter->second;
281 if (
name == propNames::name)
continue;
286 if (
name == propNames::iotype &&
287 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
288 const char *msg =
"Data member \"%s\" is an array or a pointer. "
289 "It is not possible to assign to it the iotype \"%s\". "
290 "This transformation is possible only with data members "
291 "which are not pointers or arrays.\n";
293 msg, varName.c_str(),
value.c_str());
301 if (
name == propNames::comment) {
302 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
value));
306 if ((
name == propNames::transient &&
value ==
"true") ||
307 (
name == propNames::persistent &&
value ==
"false")) {
308 userDefinedProperty = propNames::comment + propNames::separator +
"!";
312 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
"!"));
317 userDefinedProperty =
name + propNames::separator +
value;
320 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty));
331 cling::Interpreter &interpreter,
339 using namespace clang;
340 SourceLocation commentSLoc;
341 llvm::StringRef comment;
343 ASTContext &C = CXXRD.getASTContext();
346 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
347 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
348 if (declSelRulePair == declSelRulesMap.end()){
349 const std::string thisClassName(CXXRD.getName());
350 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
355 if (thisClassBaseSelectionRule) {
358 BaseSelectionRule::AttributesMap_t::iterator iter;
359 std::string userDefinedProperty;
361 const std::string &
name =
attr.first;
366 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty));
373 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
374 E = CXXRD.decls_end();
I != E; ++
I) {
378 if (!(*I)->isImplicit()
379 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
383 if (isClassDefMacro) {
384 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
390 if (comment.size()) {
392 if (isClassDefMacro) {
393 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str()));
394 }
else if (!isGenreflex) {
400 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str()));
405 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
409 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
423 llvm::APInt
len = arrayType->getSize();
424 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
425 len *= subArrayType->getSize();
426 arrayType = subArrayType;
428 return len.getLimitedValue();
434 const cling::Interpreter &interp)
436 static const clang::CXXRecordDecl *TObject_decl
439 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
446 const cling::Interpreter &interp)
448 static const clang::CXXRecordDecl *TObject_decl
461 return (0 == strcasecmp(
filename + (
len - xmllen),
".xml"));
487 if (exepath && *exepath) {
489 char *ep =
new char[PATH_MAX];
490 if (!realpath(exepath, ep)) {
491 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
492 strlcpy(ep, exepath, PATH_MAX);
495 int nche = strlen(exepath) + 1;
496 char *ep =
new char[nche];
497 strlcpy(ep, exepath, nche);
501 if ((s = strrchr(ep,
'/'))) {
503 int removesubdirs = 2;
504 if (!strncmp(s + 1,
"rootcling_stage1.exe", 20)) {
508 }
else if (!strncmp(s + 1,
"rootcling_stage1", 16)) {
513 for (
int i = 1; s && i < removesubdirs; ++i) {
515 s = strrchr(ep,
'/');
529 int ncha = strlen(ep) + 10;
530 char *env =
new char[ncha];
531 snprintf(env, ncha,
"ROOTSYS=%s", ep);
552 const char *expectedTokens[],
553 size_t *end =
nullptr)
556 if (
line[0] !=
'#')
return false;
558 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
559 while (isspace(
line[pos])) ++pos;
560 size_t lenToken = strlen(*iToken);
561 if (
line.compare(pos, lenToken, *iToken)) {
580 if (recordDecl->hasOwningModule()) {
581 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
584 std::string qual_name;
590 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
599 if (classname.find(
':') == std::string::npos)
return;
602 int slen = classname.size();
603 for (
int k = 0; k < slen; ++k) {
604 if (classname[k] ==
':') {
605 if (k + 1 >= slen || classname[k + 1] !=
':') {
610 string base = classname.substr(0, k);
615 autoloads[base] =
"";
619 }
else if (classname[k] ==
'<') {
631 std::string classname;
633 while (file >>
line) {
635 if (
line.find(
"Library.") != 0)
continue;
637 int pos =
line.find(
":", 8);
638 classname =
line.substr(8, pos - 8);
643 getline(file,
line,
'\n');
644 while (
line[0] ==
' ')
line.replace(0, 1,
"");
648 if (classname ==
"ROOT::TImpProxy") {
652 autoloads[classname] =
line;
667 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
669 while (getline(file,
line,
'\n')) {
670 if (
line ==
"{ decls }") {
671 while (getline(file,
line,
'\n')) {
672 if (
line[0] ==
'[')
break;
675 const char firstChar =
line[0];
676 if (firstChar ==
'[') {
678 libs =
line.substr(1,
line.find(
']') - 1);
679 while (libs[0] ==
' ') libs.replace(0, 1,
"");
680 }
else if (0 != keyLenMap.count(firstChar)) {
681 unsigned int keyLen = keyLenMap.at(firstChar);
682 keyname =
line.substr(keyLen,
line.length() - keyLen);
684 autoloads[keyname] = libs;
694void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
696 std::ifstream filelist(fileListName.c_str());
703 if (llvm::sys::fs::is_directory(
filename))
continue;
709 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
711 file.seekg(0, std::ios::beg);
732 const string &fullname,
733 const clang::RecordDecl *cl,
734 cling::Interpreter &interp)
737 const clang::FunctionDecl *method
742 clang::TranslationUnitDecl *TU =
743 cl->getASTContext().getTranslationUnitDecl();
747 bool has_input_error =
false;
748 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
750 if (strstr(
filename.c_str(),
"TBuffer.h") !=
nullptr ||
751 strstr(
filename.c_str(),
"Rtypes.h") !=
nullptr) {
753 has_input_error =
true;
756 has_input_error =
true;
758 if (has_input_error) {
760 const char *maybeconst =
"";
761 const char *mayberef =
"&";
762 if (
what[strlen(
what) - 1] ==
'<') {
763 maybeconst =
"const ";
767 "in this version of ROOT, the option '!' used in a linkdef file\n"
768 " implies the actual existence of customized operators.\n"
769 " The following declaration is now required:\n"
770 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
772 return has_input_error;
784 int ncha = fullname.length() + 13;
785 char *
proto =
new char[ncha];
797 return has_input_error;
803bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
809 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
813 bool isAbstract = clxx->isAbstract();
816 std::string qualName;
818 const char *qualName_c = qualName.c_str();
820 "because it inherits from TObject but does not "
821 "have its own ClassDef.\n",
834 if (
m.getType().isConstQualified()) {
835 string ret =
"const_cast< ";
838 if (type_name.substr(0,6)==
"const ") {
839 ret += type_name.c_str()+6;
845 ret +=
m.getName().str();
849 return prefix +
m.getName().str();
859 const cling::Interpreter &interp,
861 std::ostream &dictStream)
864 std::string mTypename;
877 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
879 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
880 if (!tmplt_specialization)
return 0;
886 string fulName1, fulName2;
887 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
888 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
889 clang::QualType ti = arg0.getAsType();
893 fulName1 = ti.getAsString();
896 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
897 clang::QualType tmplti = arg1.getAsType();
900 fulName2 = tmplti.getAsString();
907 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
913 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
917 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
919 }
else if (
m.getType()->isPointerType()) {
924 dictStream <<
" {" << std::endl;
926 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
931 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
934 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
937 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
938 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
939 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
942 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
943 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
944 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
948 dictStream <<
" R__stl.clear();" << std::endl;
951 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
952 <<
" if (R__tcl1==0) {" << std::endl
953 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
954 << fulName1.c_str() <<
"!\");" << std::endl
955 <<
" return;" << std::endl
956 <<
" }" << std::endl;
959 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
960 <<
" if (R__tcl2==0) {" << std::endl
961 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
962 << fulName2.c_str() <<
"!\");" << std::endl
963 <<
" return;" << std::endl
964 <<
" }" << std::endl;
967 dictStream <<
" int R__i, R__n;" << std::endl
968 <<
" R__b >> R__n;" << std::endl;
971 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
973 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
977 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
997 std::string keyName(ti.getAsString());
998 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
999 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
1000 <<
" R__stl.insert(R__t3);" << std::endl;
1008 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1013 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1016 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1021 dictStream <<
" }" << std::endl
1022 <<
" }" << std::endl;
1023 if (isArr) dictStream <<
" }" << std::endl;
1029 dictStream <<
" for (Int_t R__l = 0; R__l < " <<
len <<
"; R__l++) {" << std::endl;
1031 dictStream <<
" {" << std::endl;
1034 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1037 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1040 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1043 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1047 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1048 <<
" R__b << R__n;" << std::endl
1049 <<
" if(R__n) {" << std::endl;
1052 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1053 <<
" if (R__tcl1==0) {" << std::endl
1054 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1055 << fulName1.c_str() <<
"!\");" << std::endl
1056 <<
" return;" << std::endl
1057 <<
" }" << std::endl;
1060 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1061 <<
" if (R__tcl2==0) {" << std::endl
1062 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1063 <<
" return;" << std::endl
1064 <<
" }" << std::endl;
1067 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1068 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1070 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1071 clang::QualType tmplti = arg1.getAsType();
1078 dictStream <<
" }" << std::endl
1079 <<
" }" << std::endl
1080 <<
" }" << std::endl;
1081 if (isArr) dictStream <<
" }" << std::endl;
1093 std::string mTypenameStr;
1097 if (!strcmp(mTypeName,
"string")) {
1099 std::string fieldname =
m.getName().str();
1102 if (
m.getType()->isConstantArrayType()) {
1103 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1104 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1106 std::stringstream fullIdx;
1107 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1110 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1111 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1112 fullIdx <<
"[R__i" << dim <<
"]";
1113 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1116 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1117 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1120 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1121 if (
m.getType()->isPointerType())
1122 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1123 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1125 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1129 if (
m.getType()->isPointerType())
1130 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1131 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1132 else if (
m.getType()->isConstantArrayType()) {
1133 std::stringstream fullIdx;
1134 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1137 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1138 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1139 fullIdx <<
"[R__i" << dim <<
"]";
1140 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1143 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1145 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1156 if (
m.getType()->isPointerType()) {
1157 if (
m.getType()->getPointeeType()->isPointerType()) {
1169 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1171 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1173 dictStream <<
"[0]";
1174 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1189 int enclSpaceNesting = 0;
1196 dictStream <<
"#include \"TInterpreter.h\"\n";
1198 dictStream <<
"//_______________________________________"
1199 <<
"_______________________________________" << std::endl;
1200 if (add_template_keyword) dictStream <<
"template <> ";
1201 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1204 <<
"//_______________________________________"
1205 <<
"_______________________________________" << std::endl;
1206 if (add_template_keyword) dictStream <<
"template <> ";
1207 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1208 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1210 dictStream <<
"//_______________________________________"
1211 <<
"_______________________________________" << std::endl;
1212 if (add_template_keyword) dictStream <<
"template <> ";
1213 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1214 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1215 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1217 <<
"//_______________________________________"
1218 <<
"_______________________________________" << std::endl;
1219 if (add_template_keyword) dictStream <<
"template <> ";
1220 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1221 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1222 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1224 <<
"//_______________________________________"
1225 <<
"_______________________________________" << std::endl;
1226 if (add_template_keyword) dictStream <<
"template <> ";
1227 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1231 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1232 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1233 <<
"*)nullptr)->GetClass();" << std::endl
1234 <<
" return fgIsA;\n"
1235 <<
"}" << std::endl << std::endl
1237 <<
"//_______________________________________"
1238 <<
"_______________________________________" << std::endl;
1239 if (add_template_keyword) dictStream <<
"template <> ";
1240 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1242 dictStream <<
" Dictionary();\n";
1244 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1245 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1247 dictStream <<
" return fgIsA;" << std::endl
1248 <<
"}" << std::endl << std::endl;
1250 while (enclSpaceNesting) {
1251 dictStream <<
"} // namespace " << nsname << std::endl;
1260 cling::Interpreter &interp,
1261 std::ostream &dictStream)
1263 if (cl->isAnonymousNamespace()) {
1275 if (classname !=
"ROOT") {
1279 dictStream <<
" namespace ROOTDict {" << std::endl;
1282 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1286 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1287 dictStream << std::endl
1289 <<
" // Function generating the singleton type initializer" << std::endl
1292 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1293 <<
" {" << std::endl
1295 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1296 <<
" {" << std::endl
1299 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1301 <<
" instance(\"" << classname.c_str() <<
"\", ";
1304 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1306 dictStream <<
"0 /*version*/, ";
1310 for (
unsigned int i = 0; i <
filename.length(); i++) {
1314 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1318 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1320 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1323 dictStream << 0 <<
");" << std::endl
1325 <<
" return &instance;" << std::endl
1326 <<
" }" << std::endl
1327 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1328 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1329 <<
" // Static variable to force the class initialization" << std::endl
1331 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1332 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1335 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1336 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1337 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1338 <<
" }" << std::endl << std::endl;
1341 dictStream <<
" }" << std::endl;
1343 dictStream <<
"}" << std::endl;
1345 dictStream << std::endl;
1354llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1357 llvm::StringRef where;
1360 if (
index.size() == 0 && printError) {
1361 const char *errorstring;
1364 errorstring =
"is not an integer";
1367 errorstring =
"has not been defined before the array";
1370 errorstring =
"is a private member of a parent class";
1373 errorstring =
"is not known";
1376 errorstring =
"UNKNOWN ERROR!!!!";
1379 if (where.size() == 0) {
1381 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1384 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1393 const cling::Interpreter &interp,
1395 std::ostream &dictStream)
1397 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1398 if (clxx ==
nullptr)
return;
1405 int enclSpaceNesting = 0;
1411 dictStream <<
"//_______________________________________"
1412 <<
"_______________________________________" << std::endl;
1413 if (add_template_keyword) dictStream <<
"template <> ";
1414 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1415 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1423 int basestreamer = 0;
1424 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1428 string base_fullname;
1431 if (strstr(base_fullname.c_str(),
"::")) {
1433 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1434 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1435 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1437 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1442 if (!basestreamer) {
1443 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1444 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1446 dictStream <<
"}" << std::endl << std::endl;
1447 while (enclSpaceNesting) {
1448 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1455 string classname = fullname;
1456 if (strstr(fullname.c_str(),
"::")) {
1458 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1459 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1460 classname =
"thisClass";
1462 for (
int i = 0; i < 2; i++) {
1467 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1468 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1469 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1471 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1472 dictStream <<
" } else {" << std::endl;
1473 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1478 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1482 string base_fullname;
1485 if (strstr(base_fullname.c_str(),
"::")) {
1487 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1488 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1489 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1492 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1498 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1503 clang::QualType
type = field_iter->getType();
1504 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1514 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1518 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1521 if (strncmp(comment,
"!", 1)) {
1524 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1525 if (
type.getTypePtr()->isConstantArrayType() &&
1526 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1527 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1531 dictStream <<
" int R__i;" << std::endl;
1534 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1536 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());
1537 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1539 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1541 }
else if (
type.getTypePtr()->isPointerType()) {
1542 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1543 if (indexvar.size() == 0) {
1545 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1546 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1548 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1552 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1557 <<
"," << indexvar.str() <<
");" << std::endl;
1558 }
else if (isDouble32) {
1560 <<
"," << indexvar.str() <<
");" << std::endl;
1563 <<
"," << indexvar.str() <<
");" << std::endl;
1567 dictStream <<
" R__b.WriteFastArrayFloat16("
1568 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1569 }
else if (isDouble32) {
1570 dictStream <<
" R__b.WriteFastArrayDouble32("
1571 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1573 dictStream <<
" R__b.WriteFastArray("
1574 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1578 }
else if (
type.getTypePtr()->isArrayType()) {
1580 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1581 if (underling_type->isEnumeralType())
1582 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1586 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1587 }
else if (isDouble32) {
1589 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1592 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1596 if (underling_type->isEnumeralType()) {
1597 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1600 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1601 }
else if (isDouble32) {
1602 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1605 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1610 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1613 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1614 if (underling_type->isEnumeralType())
1615 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1616 << s <<
");" << std::endl;
1617 else if (isFloat16) {
1619 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1620 }
else if (isDouble32) {
1622 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1625 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1628 if (underling_type->isEnumeralType())
1629 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1630 else if (isFloat16) {
1631 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1632 }
else if (isDouble32) {
1633 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1635 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1639 }
else if (underling_type->isEnumeralType()) {
1641 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1642 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1644 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1649 <<
"=Float16_t(R_Dummy);}" << std::endl;
1652 }
else if (isDouble32) {
1655 <<
"=Double32_t(R_Dummy);}" << std::endl;
1677 if (
type.getTypePtr()->isConstantArrayType() &&
1678 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1679 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1683 dictStream <<
" int R__i;" << std::endl;
1686 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1691 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1696 dictStream <<
"[R__i];" << std::endl;
1697 }
else if (
type.getTypePtr()->isPointerType()) {
1705 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1706 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1708 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1712 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1726 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1732 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1736 dictStream <<
" int R__i;" << std::endl;
1739 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1740 std::string mTypeNameStr;
1742 const char *mTypeName = mTypeNameStr.c_str();
1743 const char *constwd =
"const ";
1744 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1745 mTypeName += strlen(constwd);
1746 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1748 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1752 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1758 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1759 << field_iter->getName().str() <<
"));" << std::endl;
1770 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1771 <<
" }" << std::endl
1772 <<
"}" << std::endl << std::endl;
1774 while (enclSpaceNesting) {
1775 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1783 const cling::Interpreter &interp,
1785 std::ostream &dictStream)
1789 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1790 if (clxx ==
nullptr)
return;
1795 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1807 int enclSpaceNesting = 0;
1813 dictStream <<
"//_______________________________________"
1814 <<
"_______________________________________" << std::endl;
1815 if (add_template_keyword) dictStream <<
"template <> ";
1816 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1818 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1819 <<
" if (R__b.IsReading()) {" << std::endl
1820 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1821 <<
" } else {" << std::endl
1822 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1823 <<
" }" << std::endl
1824 <<
"}" << std::endl << std::endl;
1826 while (enclSpaceNesting) {
1827 dictStream <<
"} // namespace " << nsname << std::endl;
1835 const cling::Interpreter &interp,
1837 std::ostream &dictStream,
1838 bool isAutoStreamer)
1840 if (isAutoStreamer) {
1850 std::string &code_for_parser)
1852 code_for_parser +=
"#ifdef __CINT__\n\n";
1853 code_for_parser +=
"#pragma link off all globals;\n";
1854 code_for_parser +=
"#pragma link off all classes;\n";
1855 code_for_parser +=
"#pragma link off all functions;\n\n";
1857 for (std::string& arg : InputFiles) {
1859 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1860 for (
int j = 0; j < 3; j++) {
1861 if (arg[
l] ==
'-') {
1866 if (arg[
l] ==
'!') {
1871 if (arg[
l] ==
'+') {
1877 if (nostr || noinp) {
1879 if (nostr) strlcat(trail,
"-", 3);
1880 if (noinp) strlcat(trail,
"!", 3);
1883 strlcpy(trail,
"+", 3);
1887 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1888 llvm::sys::path::replace_extension(filestem,
"");
1890 code_for_parser +=
"#pragma link C++ class ";
1891 code_for_parser += filestem.str().str();
1892 if (nostr || noinp || bcnt)
1893 code_for_parser += trail;
1894 code_for_parser +=
";\n";
1897 code_for_parser +=
"\n#endif\n";
1905bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1910 static const char *fopenopts =
"rb";
1912 static const char *fopenopts =
"r";
1916 fp = fopen(pname.c_str(), fopenopts);
1922 llvm::SmallVector<std::string, 10> includePaths;
1924 interp.GetIncludePaths(includePaths,
false,
false);
1926 const size_t nPaths = includePaths.size();
1927 for (
size_t i = 0; i < nPaths; i += 1 ) {
1931 fp = fopen(pname.c_str(), fopenopts);
1953 const char *inc = strstr(original,
"\\inc\\");
1955 inc = strstr(original,
"/inc/");
1956 if (inc && strlen(inc) > 5)
1976 cling::Interpreter &interp,
1979 std::ostringstream out;
1984 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1985 const std::string &hdrName
2003static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
2004 llvm::StringRef iSysRoot,
2005 clang::Module *module =
nullptr)
2008 llvm::SmallVector<char, 128> buffer;
2009 llvm::BitstreamWriter stream(buffer);
2010 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
2011 std::unique_ptr<llvm::raw_ostream> out =
2012 compilerInstance->createOutputFile(fileName,
true,
2021 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2023 writer.WriteAST(compilerInstance->getSema(), fileName.str(), module, iSysRoot);
2026 out->write(&buffer.front(), buffer.size());
2038 const std::string ¤tDirectory)
2040 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2042 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2050static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2053 if (headers.empty())
2057 std::stringstream includes;
2058 for (
const std::string &header : headers) {
2059 includes <<
"#include \"" << header <<
"\"\n";
2061 std::string includeListStr = includes.str();
2062 auto result = interpreter.declare(includeListStr);
2063 return result == cling::Interpreter::CompilationResult::kSuccess;
2071 char platformDefines[64] = {0};
2072#ifdef __INTEL_COMPILER
2073 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2074 clingArgs.push_back(platformDefines);
2077 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2078 clingArgs.push_back(platformDefines);
2081 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2082 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2083 clingArgs.push_back(platformDefines);
2085#ifdef __GNUC_MINOR__
2086 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2087 clingArgs.push_back(platformDefines);
2090 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2091 clingArgs.push_back(platformDefines);
2094 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2095 clingArgs.push_back(platformDefines);
2098 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2099 clingArgs.push_back(platformDefines);
2101#ifdef _STLPORT_VERSION
2103 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2104 clingArgs.push_back(platformDefines);
2107 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2108 clingArgs.push_back(platformDefines);
2111 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2112 clingArgs.push_back(platformDefines);
2115 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2116 clingArgs.push_back(platformDefines);
2119 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2120 clingArgs.push_back(platformDefines);
2123 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2124 clingArgs.push_back(platformDefines);
2127 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2128 clingArgs.push_back(platformDefines);
2132 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
2133 clingArgs.push_back(platformDefines);
2136 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2137 clingArgs.push_back(platformDefines);
2138 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2139 clingArgs.push_back(platformDefines);
2148 return llvm::sys::path::filename(path).str();
2158 if (std::string::npos != pos) {
2159 dirname.assign(path.begin(), path.begin() + pos + 1);
2170 std::string dictLocation;
2172 return !dictLocation.empty();
2178 std::string &rootmapLibName)
2182 if (rootmapFileName.empty()) {
2184 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2185 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2186 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2188 rootmapLibName.c_str(),
2189 rootmapFileName.c_str());
2198 std::string &ctxtName,
2199 const cling::Interpreter &interpreter,
2200 bool treatParent =
true)
2202 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2204 if (!outerCtxt)
return;
2206 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2216 std::string &ctxtName,
2217 const cling::Interpreter &interpreter)
2219 const clang::DeclContext *theContext = theDecl.getDeclContext();
2227 const cling::Interpreter &interp)
2229 if (!decls.empty()) {
2230 std::string autoLoadKey;
2231 for (
auto &
d : decls) {
2235 if (autoLoadKey.empty()) {
2236 names.push_back(
d->getQualifiedNameAsString());
2254 const std::string &rootmapLibName,
2255 const std::list<std::string> &classesDefsList,
2256 const std::list<std::string> &classesNames,
2257 const std::list<std::string> &nsNames,
2258 const std::list<std::string> &tdNames,
2259 const std::list<std::string> &enNames,
2260 const std::list<std::string> &varNames,
2262 const std::unordered_set<std::string> headersToIgnore)
2265 std::ofstream rootmapFile(rootmapFileName.c_str());
2273 std::unordered_set<std::string> classesKeys;
2277 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2278 !enNames.empty() || !varNames.empty()) {
2281 if (!classesDefsList.empty()) {
2282 rootmapFile <<
"{ decls }\n";
2283 for (
auto & classDef : classesDefsList) {
2284 rootmapFile << classDef << std::endl;
2286 rootmapFile <<
"\n";
2288 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2291 if (!classesNames.empty()) {
2292 rootmapFile <<
"# List of selected classes\n";
2293 for (
auto & className : classesNames) {
2294 rootmapFile <<
"class " << className << std::endl;
2295 classesKeys.insert(className);
2298 std::unordered_set<std::string> treatedHeaders;
2299 for (
auto & className : classesNames) {
2301 if (className.find(
"<") != std::string::npos)
continue;
2302 if (headersClassesMap.count(className)) {
2303 auto &headers = headersClassesMap.at(className);
2304 if (!headers.empty()){
2305 auto &header = headers.front();
2306 if (treatedHeaders.insert(header).second &&
2307 headersToIgnore.find(header) == headersToIgnore.end() &&
2309 rootmapFile <<
"header " << header << std::endl;
2317 if (!nsNames.empty()) {
2318 rootmapFile <<
"# List of selected namespaces\n";
2319 for (
auto & nsName : nsNames) {
2320 rootmapFile <<
"namespace " << nsName << std::endl;
2325 if (!tdNames.empty()) {
2326 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2327 for (
const auto & autoloadKey : tdNames)
2328 if (classesKeys.insert(autoloadKey).second)
2329 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2334 if (!enNames.empty()){
2335 rootmapFile <<
"# List of selected enums and outer classes\n";
2336 for (
const auto & autoloadKey : enNames)
2337 if (classesKeys.insert(autoloadKey).second)
2338 rootmapFile <<
"enum " << autoloadKey << std::endl;
2342 if (!varNames.empty()){
2343 rootmapFile <<
"# List of selected vars\n";
2344 for (
const auto & autoloadKey : varNames)
2345 if (classesKeys.insert(autoloadKey).second)
2346 rootmapFile <<
"var " << autoloadKey << std::endl;
2360 auto nsPattern =
'{';
auto nsPatternLength = 1;
2361 auto foundNsPos =
line.find_last_of(nsPattern);
2362 if (foundNsPos == std::string::npos)
return {
"",
""};
2363 foundNsPos+=nsPatternLength;
2364 auto extNs =
line.substr(0,foundNsPos);
2366 auto nsEndPattern =
'}';
2367 auto foundEndNsPos =
line.find(nsEndPattern);
2368 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2370 return {extNs, contained};
2386 std::map<std::string, std::string> nsEntitiesMap;
2387 std::list<std::string> optFwdDeclList;
2388 for (
auto const & fwdDecl : fwdDeclarationsList){
2391 if (extNsAndEntities.first.empty()) {
2393 optFwdDeclList.push_front(fwdDecl);
2395 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2396 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2400 std::string optFwdDecl;
2401 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2402 optFwdDecl = extNsAndEntities.first;
2403 optFwdDecl += extNsAndEntities.second;
2404 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2407 optFwdDeclList.push_front(optFwdDecl);
2410 return optFwdDeclList;
2418 std::list<std::string> &el_list,
2419 std::unordered_set<std::string> &el_set)
2421 std::stringstream elStream(el);
2424 while (getline(elStream, tmp,
'\n')) {
2426 if (el_set.insert(tmp).second && !tmp.empty()) {
2427 el_list.push_back(tmp);
2438 std::list<std::string> &classesList,
2439 std::list<std::string> &classesListForRootmap,
2440 std::list<std::string> &fwdDeclarationsList,
2441 const cling::Interpreter &interpreter)
2449 std::unordered_set<std::string> classesSet;
2450 std::unordered_set<std::string> outerMostClassesSet;
2452 std::string attrName, attrValue;
2453 bool isClassSelected;
2454 std::unordered_set<std::string> availableFwdDecls;
2455 std::string fwdDeclaration;
2457 fwdDeclaration =
"";
2463 fwdDeclaration =
"";
2470 isClassSelected =
true;
2471 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2472 std::string normalizedName;
2473 normalizedName = selClass.GetNormalizedName();
2474 if (!normalizedName.empty() &&
2475 !classesSet.insert(normalizedName).second &&
2476 outerMostClassesSet.count(normalizedName) == 0) {
2477 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2478 <<
" was already selected. This means that two different instances of"
2479 <<
" clang::RecordDecl had the same name, which is not possible."
2480 <<
" This can be a hint of a serious problem in the class selection."
2481 <<
" In addition, the generated dictionary would not even compile.\n";
2484 classesList.push_back(normalizedName);
2487 const char *reqName(selClass.GetRequestedName());
2490 fwdDeclaration =
"";
2495 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2496 fwdDeclaration =
"";
2499 std::string fwdDeclarationTemplateSpec;
2501 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2509 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2511 attrName ==
"rootmap" &&
2512 attrValue ==
"false") {
2513 attrName = attrValue =
"";
2514 isClassSelected =
false;
2518 if (isClassSelected) {
2534 std::string outerMostClassName;
2536 if (!outerMostClassName.empty() &&
2537 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2538 classesSet.insert(outerMostClassName).second &&
2539 outerMostClassesSet.insert(outerMostClassName).second) {
2540 classesListForRootmap.push_back(outerMostClassName);
2542 classesListForRootmap.push_back(normalizedName);
2543 if (reqName && reqName[0] && reqName != normalizedName) {
2544 classesListForRootmap.push_back(reqName);
2549 std::string demangledName = selClass.GetDemangledTypeInfo();
2550 if (!demangledName.empty()) {
2555 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2557 classesListForRootmap.push_back(demangledName);
2563 classesListForRootmap.sort();
2576 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2591 if (clang::CXXRecordDecl *CXXRD =
2592 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2604 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2607 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2610 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2626 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2627 "#include \"TFile.h\"\n"
2628 "#include \"TObjArray.h\"\n"
2629 "#include \"TVirtualArray.h\"\n"
2630 "#include \"TStreamerElement.h\"\n"
2631 "#include \"TProtoClass.h\"\n"
2632 "#include \"TBaseClass.h\"\n"
2633 "#include \"TListOfDataMembers.h\"\n"
2634 "#include \"TListOfEnums.h\"\n"
2635 "#include \"TListOfEnumsWithLock.h\"\n"
2636 "#include \"TDataMember.h\"\n"
2637 "#include \"TEnum.h\"\n"
2638 "#include \"TEnumConstant.h\"\n"
2639 "#include \"TDictAttributeMap.h\"\n"
2640 "#include \"TMessageHandler.h\"\n"
2641 "#include \"TArray.h\"\n"
2642 "#include \"TRefArray.h\"\n"
2643 "#include \"root_std_complex.h\"\n")
2644 != cling::Interpreter::kSuccess)
2655 cling::Interpreter &interp,
2661 bool writeEmptyRootPCM)
2665 bool needsCollectionProxy =
false;
2687 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2688 if (nsName.find(
"(anonymous)") == std::string::npos)
2693 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2697 if (selClass.RequestOnlyTClass()) {
2705 if (clang::CXXRecordDecl *CXXRD =
2706 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2710 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2718 }
else if (CRD->getName() ==
"RVec") {
2719 static const clang::DeclContext *vecOpsDC =
nullptr;
2721 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2722 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2723 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2731 needsCollectionProxy);
2746 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2750 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2762 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2766 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2771 needsCollectionProxy);
2806 if (finRetCode != 0)
return finRetCode;
2816 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2817 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2820 <<
"#define R__NO_DEPRECATION" << std::endl
2825 <<
"\n/*******************************************************************/\n"
2826 <<
"#include <stddef.h>\n"
2827 <<
"#include <stdio.h>\n"
2828 <<
"#include <stdlib.h>\n"
2829 <<
"#include <string.h>\n"
2830 <<
"#include <assert.h>\n"
2831 <<
"#define G__DICTIONARY\n"
2832 <<
"#include \"ROOT/RConfig.hxx\"\n"
2833 <<
"#include \"TClass.h\"\n"
2834 <<
"#include \"TDictAttributeMap.h\"\n"
2835 <<
"#include \"TInterpreter.h\"\n"
2836 <<
"#include \"TROOT.h\"\n"
2837 <<
"#include \"TBuffer.h\"\n"
2838 <<
"#include \"TMemberInspector.h\"\n"
2839 <<
"#include \"TInterpreter.h\"\n"
2840 <<
"#include \"TVirtualMutex.h\"\n"
2841 <<
"#include \"TError.h\"\n\n"
2842 <<
"#ifndef G__ROOT\n"
2843 <<
"#define G__ROOT\n"
2845 <<
"#include \"RtypesImp.h\"\n"
2846 <<
"#include \"TIsAProxy.h\"\n"
2847 <<
"#include \"TFileMergeInfo.h\"\n"
2848 <<
"#include <algorithm>\n"
2849 <<
"#include \"TCollectionProxyInfo.h\"\n"
2850 <<
"/*******************************************************************/\n\n"
2851 <<
"#include \"TDataMember.h\"\n\n";
2858 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2859 <<
"namespace std {} using namespace std;\n\n";
2865 const std::string &includeForSource,
2866 const std::string &extraIncludes)
2868 dictStream <<
"// Header files passed as explicit arguments\n"
2869 << includeForSource << std::endl
2870 <<
"// Header files passed via #pragma extra_include\n"
2871 << extraIncludes << std::endl;
2877#if defined(R__IOSSIM) || defined(R__IOS)
2902 return filename +
"_tmp_" + std::to_string(getpid());
2909 if (nameStr.empty())
return;
2911 std::string tmpNameStr(getTmpFileName(nameStr));
2914 const char *
name(nameStr.c_str());
2915 const char *tmpName(tmpNameStr.c_str());
2917 m_names.push_back(nameStr);
2918 m_tempNames.push_back(tmpNameStr);
2922 if (0 == std::rename(
name , tmpName)) {
2927 nameStr = tmpNameStr;
2938 for (
unsigned int i = 0; i < m_size; ++i) {
2939 const char *tmpName = m_tempNames[i].c_str();
2941 std::ifstream ifile(tmpName);
2946 if (ifile.is_open())
2948 if (0 != std::remove(tmpName)) {
2961 for (
unsigned int i = 0; i < m_size; ++i) {
2962 const char *tmpName = m_tempNames[i].c_str();
2963 const char *
name = m_names[i].c_str();
2965 std::ifstream ifile(tmpName);
2970 if (ifile.is_open())
2976 if (0 != std::rename(tmpName ,
name)) {
2977 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2978 llvm::sys::fs::remove(tmpName);
2982 if (0 != std::rename(tmpName ,
name)) {
2994 size_t i = std::distance(m_tempNames.begin(),
2995 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2996 if (i == m_tempNames.size())
return m_emptyString;
3003 std::cout <<
"Restoring files in temporary file catalog:\n";
3004 for (
unsigned int i = 0; i < m_size; ++i) {
3005 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3022 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
3023 const size_t dotPos = splitDictName.find_last_of(
".");
3024 splitDictName.insert(dotPos,
"_classdef");
3026 return new std::ofstream(splitDictName.c_str());
3035 std::list<std::string> &diagnosticPragmas)
3037 static const std::string pattern(
"-Wno-");
3039 if (arg.find(pattern) != 0)
3044 diagnosticPragmas.push_back(arg);
3050 cling::Interpreter &interp)
3053 std::string fwdDecl;
3054 std::string initStr(
"{");
3056 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3057 auto &clTemplDecl = *strigNargsToKeepPair.first;
3058 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3061 + std::to_string(strigNargsToKeepPair.second)
3064 if (!fwdDeclnArgsToSkipColl.empty())
3075 if (qt.isNull())
return qt;
3076 clang::QualType thisQt(qt);
3077 while (thisQt->isPointerType() ||
3078 thisQt->isReferenceType()) {
3079 thisQt = thisQt->getPointeeType();
3089 const cling::Interpreter &interp,
3090 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3092 std::list<std::string> headers;
3095 cling::Interpreter::PushTransactionRAII RAII(&interp);
3098 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3102 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3105 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3106 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3108 if (tArgQualType.isNull())
continue;
3109 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3110 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3117 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3119 if (baseQualType.isNull())
continue;
3120 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3121 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3126 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3127 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3129 if (fieldQualType.isNull()) continue ;
3130 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3131 if (fieldCxxRcd->hasDefinition())
3132 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3138 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3140 for (
auto & fPar : methodIt->parameters()) {
3142 if (fParQualType.isNull())
continue;
3143 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3144 if (fParCxxRcd->hasDefinition())
3145 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3150 if (retQualType.isNull())
continue;
3151 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3152 if (retCxxRcd->hasDefinition())
3161 headers.emplace_back(header);
3174 if (
auto dclCtxt= rcd.getDeclContext()){
3175 if (! dclCtxt->isStdNamespace()){
3184 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3185 if (!clAsTmplSpecDecl)
return false;
3190 auto& astCtxt = rcd.getASTContext();
3191 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3192 for (
auto&& arg : templInstArgs.asArray()){
3194 auto argKind = arg.getKind();
3195 if (argKind != clang::TemplateArgument::Type){
3196 if (argKind == clang::TemplateArgument::Integral)
continue;
3200 auto argQualType = arg.getAsType();
3201 auto isPOD = argQualType.isPODType(astCtxt);
3203 if (isPOD)
continue;
3205 auto argType = argQualType.getTypePtr();
3206 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3209 if (isArgGoodForAutoParseMap)
continue;
3228 const cling::Interpreter &interp)
3230 std::set<const clang::CXXRecordDecl *> visitedDecls;
3231 std::unordered_set<std::string> buffer;
3232 std::string autoParseKey;
3235 for (
auto & annotatedRcd : annotatedRcds) {
3236 if (
const clang::CXXRecordDecl *cxxRcd =
3237 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3239 visitedDecls.clear();
3243 headers.remove_if([&buffer](
const std::string & s) {
3244 return !buffer.insert(s).second;
3247 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3249 headersDeclsMap[autoParseKey] = headers;
3250 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3252 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3257 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3258 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3259 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3265 for (
auto & tDef : tDefDecls) {
3266 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3268 visitedDecls.clear();
3273 headers.remove_if([&buffer](
const std::string & s) {
3274 return !buffer.insert(s).second;
3277 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3278 headersDeclsMap[autoParseKey] = headers;
3283 for (
auto & func : funcDecls) {
3289 for (
auto & var : varDecls) {
3295 for (
auto & en : enumDecls) {
3305 const cling::Interpreter &interp)
3307 std::string newFwdDeclString;
3311 std::string fwdDeclString;
3313 std::unordered_set<std::string> fwdDecls;
3334 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3339 selectedDecls.begin(),
3343 selectedDecls.push_back(TD);
3348 std::string fwdDeclLogs;
3356 std::cout <<
"Logs from forward decl printer: \n"
3373 if (fwdDeclString.empty()) fwdDeclString =
"";
3374 return fwdDeclString;
3381 const std::string &detectedUmbrella,
3382 bool payLoadOnly =
false)
3384 std::string headerName;
3387 std::cout <<
"Class-headers Mapping:\n";
3388 std::string headersClassesMapString =
"";
3389 for (
auto const & classHeaders : headersClassesMap) {
3391 std::cout <<
" o " << classHeaders.first <<
" --> ";
3392 headersClassesMapString +=
"\"";
3393 headersClassesMapString += classHeaders.first +
"\"";
3394 for (
auto const & header : classHeaders.second) {
3395 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3396 headersClassesMapString +=
", " + headerName;
3398 std::cout <<
", " << headerName;
3403 std::cout << std::endl;
3404 headersClassesMapString +=
", \"@\",\n";
3406 headersClassesMapString +=
"nullptr";
3407 return headersClassesMapString;
3430 static const std::vector<std::string> namePrfxes {
3433 auto pos = find_if(namePrfxes.begin(),
3435 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3436 return namePrfxes.end() == pos;
3443 static const std::vector<std::string> uclNamePrfxes {
3447 static const std::set<std::string> unsupportedClassesNormNames{
3450 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3451 auto pos = find_if(uclNamePrfxes.begin(),
3452 uclNamePrfxes.end(),
3453 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3454 return uclNamePrfxes.end() == pos;
3464 for (
auto&& aRcd : annotatedRcds){
3465 auto clName = aRcd.GetNormalizedName();
3467 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3468 <<
"currently the support for its I/O is not yet available. Note that "
3469 << clName <<
", even if not selected, will be available for "
3470 <<
"interpreted code.\n";
3474 std::cerr <<
"Error: It is not necessary to explicitly select class "
3475 << clName <<
". I/O is supported for it transparently.\n";
3487 bool isLocked =
false;
3490 InterpreterCallbacks(interp),
3491 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3496 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3497 clang::OptionalFileEntryRef , llvm::StringRef ,
3498 llvm::StringRef ,
const clang::Module * ,
3499 clang::SrcMgr::CharacteristicKind )
override
3501 if (isLocked)
return;
3502 if (IsAngled)
return;
3503 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3504 auto curLexer = PP.getCurrentFileLexer();
3505 if (!curLexer)
return;
3506 auto fileEntry = curLexer->getFileEntry();
3507 if (!fileEntry)
return;
3508 auto thisFileName = fileEntry->getName();
3509 auto fileNameAsString = FileName.str();
3511 if (isThisLinkdef) {
3513 if (isTheIncludedLinkdef) {
3514 fFilesIncludedByLinkdef.clear();
3517 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3531 clang::SourceLocation ImportLoc,
3532 bool ForPragma)
override {
3534 using namespace clang;
3535 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3536 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3537 HeaderSearch& HS = PP.getHeaderSearchInfo();
3539 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3541 assert(M &&
"Must have module Core");
3542 PP.makeModuleVisible(CoreModule, ImportLoc);
3547static llvm::cl::list<std::string>
3550 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3553static llvm::cl::opt<std::string>
3555 llvm::cl::desc(
"<output dictionary file>"),
3575 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3587 using namespace clang::diag;
3593 std::string moduleName;
3594 const clang::Module *module =
nullptr;
3597 const auto &ID =
Info.getID();
3598 if (ID == remark_module_build || ID == remark_module_build_done) {
3599 moduleName =
Info.getArgStdStr(0);
3600 module = fMap.findModule(moduleName);
3606 "Couldn't find module %s in the available modulemaps. This"
3607 "prevents us from correctly diagnosing wrongly built modules.\n",
3608 moduleName.c_str());
3621 bool isByproductModule
3623 if (!isByproductModule)
3624 fChild->HandleDiagnostic(DiagLevel,
Info);
3626 if (ID == remark_module_build && !isByproductModule) {
3628 "Building module '%s' implicitly. If '%s' requires a \n"
3629 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3630 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3632 moduleName.c_str(), moduleName.c_str());
3640 DiagnosticConsumer::clear();
3643 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3645 fChild->BeginSourceFile(LangOpts, PP);
3646 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3651 fChild->EndSourceFile();
3652 DiagnosticConsumer::EndSourceFile();
3658 DiagnosticConsumer::finish();
3665#if defined(_WIN32) && defined(_MSC_VER)
3669 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3670 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3671 ::_set_error_mode(_OUT_TO_STDERR);
3672 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3673 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3674 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3675 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3676 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3677 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3682static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3684static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3695static llvm::cl::opt<VerboseLevel>
3697 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3698 clEnumVal(
v0,
"Show only fatal errors."),
3699 clEnumVal(
v1,
"Show errors (the same as -v)."),
3700 clEnumVal(
v2,
"Show warnings (default)."),
3701 clEnumVal(
v3,
"Show notes."),
3702 clEnumVal(
v4,
"Show information.")),
3706static llvm::cl::opt<bool>
3707gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3710static llvm::cl::opt<bool>
3711gOptReflex(
"reflex", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3714static llvm::cl::opt<bool>
3715gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3718static llvm::cl::opt<std::string>
3720 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3723static llvm::cl::opt<bool>
3725 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3728static llvm::cl::opt<bool>
3729gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3731static llvm::cl::opt<bool>
3732gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3734static llvm::cl::list<std::string>
3736 llvm::cl::desc(
"Generate rootmap file."),
3738static llvm::cl::opt<std::string>
3740 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3742static llvm::cl::opt<bool>
3744 llvm::cl::desc(
"Generate a C++ module."),
3746static llvm::cl::list<std::string>
3748 llvm::cl::desc(
"Specify a C++ modulemap file."),
3751static llvm::cl::opt<bool>
3753 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3755static llvm::cl::opt<bool>
3757 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3759static llvm::cl::opt<bool>
3761 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3763static llvm::cl::opt<bool>
3765 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3767static llvm::cl::opt<bool>
3769 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3770information and another the interactivity support."),
3772static llvm::cl::opt<bool>
3775 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3777static llvm::cl::opt<std::string>
3779 llvm::cl::desc(
"The path to the library of the built dictionary."),
3781static llvm::cl::list<std::string>
3783 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3785static llvm::cl::list<std::string>
3787 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3791static llvm::cl::opt<bool>
3793 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3801static llvm::cl::opt<bool>
3804 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3806static llvm::cl::opt<bool>
3808 llvm::cl::desc(
"Check the selection syntax only."),
3810static llvm::cl::opt<bool>
3812 llvm::cl::desc(
"Fail if there are warnings."),
3814static llvm::cl::opt<bool>
3816 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3818static llvm::cl::opt<std::string>
3820 llvm::cl::desc(
"Specify an isysroot."),
3822 llvm::cl::init(
"-"));
3823static llvm::cl::list<std::string>
3825 llvm::cl::desc(
"Specify an include path."),
3827static llvm::cl::list<std::string>
3829 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3831static llvm::cl::list<std::string>
3833 llvm::cl::desc(
"Specify a system include path."),
3835static llvm::cl::list<std::string>
3837 llvm::cl::desc(
"Specify defined macros."),
3839static llvm::cl::list<std::string>
3841 llvm::cl::desc(
"Specify undefined macros."),
3843static llvm::cl::list<std::string>
3845 llvm::cl::desc(
"Specify compiler diagnostics options."),
3848static llvm::cl::list<std::string>
3850 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file>"),
3852static llvm::cl::list<std::string>
3854 llvm::cl::desc(
"Consumes all unrecognized options."),
3857static llvm::cl::SubCommand
3860static llvm::cl::list<std::string>
3862 llvm::cl::desc(
"Consumes options and sends them to cling."),
3872 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3875 std::vector<clang::Module::Header> moduleHeaders;
3877 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3879 bool foundAllHeaders =
true;
3881 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3882 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3883 if (header == moduleHeader.NameAsWritten)
3891 for (
const std::string &header : modGen.
GetHeaders()) {
3892 if (isHeaderInModule(header))
3895 clang::ModuleMap::KnownHeader SuggestedModule;
3896 clang::ConstSearchDirIterator *CurDir =
nullptr;
3897 if (
auto FE = headerSearch.LookupFile(
3898 header, clang::SourceLocation(),
3901 clang::ArrayRef<std::pair<const clang::FileEntry *, const clang::DirectoryEntry *>>(),
3904 0, &SuggestedModule,
3911 if (
auto OtherModule = SuggestedModule.getModule()) {
3912 std::string OtherModuleName;
3913 auto TLM = OtherModule->getTopLevelModuleName();
3915 OtherModuleName = TLM.str();
3917 OtherModuleName = OtherModule->Name;
3924 missingHeaders.push_back({header, OtherModuleName});
3927 missingHeaders.push_back({header, {}});
3929 foundAllHeaders =
false;
3931 return foundAllHeaders;
3937 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3939 clang::CompilerInstance *CI = interpreter.getCI();
3940 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3941 headerSearch.loadTopLevelSystemModules();
3944 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3949 moduleName.c_str());
3956 std::vector<std::array<std::string, 2>> missingHdrMod;
3959 std::stringstream msgStream;
3960 msgStream <<
"after creating module \"" << module->Name <<
"\" ";
3961 if (!module->PresumedModuleMapFile.empty())
3962 msgStream <<
"using modulemap \"" << module->PresumedModuleMapFile <<
"\" ";
3963 msgStream <<
"the following headers are not part of that module:\n";
3964 for (
auto &
H : missingHdrMod) {
3965 msgStream <<
" " <<
H[0];
3967 msgStream <<
" (already part of module \"" <<
H[1] <<
"\")";
3970 std::string warningMessage = msgStream.str();
3972 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3983 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3984 warningMessage.c_str(),
3991 std::vector<std::string> missingHeaders;
3992 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
3993 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
3996 module->Name.c_str());
4006 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
4007 moduleName.consume_front(
"lib");
4008 moduleName.consume_back(
".pcm");
4009 moduleName.consume_back(
"_rdict");
4017 bool isGenreflex =
false)
4028 const char *executableFileName = argv[0];
4030 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
4031 llvm::PrettyStackTraceProgram X(argc, argv);
4034#if defined(R__WIN32) && !defined(R__WINGCC)
4039 for (
int iic = 1 ; iic < argc; ++iic) {
4040 std::string iiarg(argv[iic]);
4042 size_t len = iiarg.length();
4044 char *argviic =
new char[
len + 1];
4045 strlcpy(argviic, iiarg.c_str(),
len + 1);
4046 argv[iic] = argviic;
4055 auto &opts = llvm::cl::getRegisteredOptions();
4056 llvm::cl::Option* optHelp = opts[
"help"];
4057 llvm::cl::alias optHelpAlias1(
"h",
4058 llvm::cl::desc(
"Alias for -help"),
4059 llvm::cl::aliasopt(*optHelp));
4060 llvm::cl::alias optHelpAlias2(
"?",
4061 llvm::cl::desc(
"Alias for -help"),
4062 llvm::cl::aliasopt(*optHelp));
4064 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
4068 std::vector<const char *> clingArgsC;
4069 clingArgsC.push_back(executableFileName);
4071 clingArgsC.push_back(
"-I");
4078 clingArgsC.push_back(Opt.c_str());
4080 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
4082 llvmResourceDir.c_str());
4085 return interp->getDiagnostics().hasFatalErrorOccurred();
4088 std::string dictname;
4102 llvm::cl::PrintHelpMessage();
4117 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
4118 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4145 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4146 llvm::cl::PrintHelpMessage();
4150 std::vector<std::string> clingArgs;
4151 clingArgs.push_back(executableFileName);
4152 clingArgs.push_back(
"-iquote.");
4158 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4164 if (GetErrorIgnoreLevel() >
kWarning)
4166 GetWarningsAreErrors() =
true;
4180 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4185 clingArgs.push_back(std::string(
"-D") + PPDefine);
4188 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4191 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4198 clingArgs.push_back(
"-isystem");
4199 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4203 for (
const std::string &WDiag :
gOptWDiags) {
4204 const std::string FullWDiag = std::string(
"-W") + WDiag;
4208 clingArgs.push_back(FullWDiag);
4212 clingArgs.push_back(std::string(
"-I") + includeDir);
4214 std::vector<std::string> pcmArgs;
4215 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4216 auto thisArg = clingArgs[parg];
4218 if (thisArg ==
"-c" ||
4224 while (
c ==
' ')
c = thisArg[++
offset];
4228 [&](
const std::string& path){
4229 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4230 if (excludePathsEnd != excludePathPos)
continue;
4232 pcmArgs.push_back(thisArg);
4239 clingArgs.push_back(
"-D__ROOTCLING__");
4242 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4243#elif defined(R__WIN32)
4244 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4247 clingArgs.push_back(
"-D_XKEYCHECK_H");
4249 clingArgs.push_back(
"-DNOMINMAX");
4251 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4254 clingArgs.push_back(
"-fsyntax-only");
4256 clingArgs.push_back(
"-fPIC");
4258 clingArgs.push_back(
"-Xclang");
4259 clingArgs.push_back(
"-fmodules-embed-all-files");
4260 clingArgs.push_back(
"-Xclang");
4261 clingArgs.push_back(
"-main-file-name");
4262 clingArgs.push_back(
"-Xclang");
4263 clingArgs.push_back((dictname +
".h").c_str());
4271 std::string outputFile;
4273 llvm::StringRef moduleName;
4278 auto clingArgsInterpreter = clingArgs;
4287 clingArgsInterpreter.push_back(
"-fmodules");
4288 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4291 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4293 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4297 if (llvm::sys::fs::exists(ModuleMapCWD))
4298 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4306 clingArgsInterpreter.push_back(
"-Xclang");
4307 clingArgsInterpreter.push_back(
"-fmodule-feature");
4308 clingArgsInterpreter.push_back(
"-Xclang");
4311 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4321 if (moduleName ==
"Core") {
4323 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4324 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4325 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4326 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4328 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4329 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4333 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4335 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4337 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4338 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4339 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4340 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4341 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4342 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4343 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4344 }
else if (moduleName ==
"MathCore") {
4345 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4350 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4354 clingArgsInterpreter.push_back(
"-v");
4357 std::vector<const char *> clingArgsC;
4358 for (
auto const &clingArg : clingArgsInterpreter) {
4360 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4361 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4364 clingArgsC.push_back(clingArg.c_str());
4368 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4369 cling::Interpreter* interpPtr =
nullptr;
4371 std::list<std::string> filesIncludedByLinkdef;
4375 clingArgsC.push_back(
"-ffast-math");
4378 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4379 llvmResourceDir.c_str()));
4380 interpPtr = owningInterpPtr.get();
4383 clingArgsC.push_back(
"-resource-dir");
4384 clingArgsC.push_back(llvmResourceDir.c_str());
4385 clingArgsC.push_back(
nullptr);
4387 extraArgs = &clingArgsC[1];
4390 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4391 interpPtr->setCallbacks(std::move(callBacks));
4394 cling::Interpreter &interp = *interpPtr;
4395 clang::CompilerInstance *CI = interp.getCI();
4397 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4398 CI->getSourceManager().setAllFilesAreTransient(
true);
4400 clang::Preprocessor &PP = CI->getPreprocessor();
4401 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4402 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4403 auto &diags = interp.getDiagnostics();
4410 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4415 diags.setClient(recordingClient,
true);
4421 interp.DumpIncludePath();
4426 interp.printIncludedFiles(llvm::outs());
4427 llvm::outs() <<
"\n\n";
4428 llvm::outs().flush();
4431 const clang::LangOptions& LangOpts
4432 = interp.getCI()->getASTContext().getLangOpts();
4433#define LANGOPT(Name, Bits, Default, Description) \
4434 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4435#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4436#include "clang/Basic/LangOptions.def"
4440 interp.getOptions().ErrorOut =
true;
4441 interp.enableRawInput(
true);
4445 if (DepMod.endswith(
"_rdict.pcm")) {
4452 cling::Interpreter::PushTransactionRAII RAII(&interp);
4453 if (!interp.loadModule(DepMod.str(),
false)) {
4462 if (interp.declare(
"#include <assert.h>\n"
4463 "#include \"Rtypes.h\"\n"
4464 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4472 if (interp.declare(
"#include <string>\n"
4473 "#include <RtypesCore.h>\n"
4474 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4485 clingArgs.push_back(
"-D__CINT__");
4486 clingArgs.push_back(
"-D__MAKECINT__");
4492 std::string interpPragmaSource;
4493 std::string includeForSource;
4494 std::string interpreterDeclarations;
4495 std::string linkdef;
4501 if (isSelectionFile) {
4503 linkdef = optHeaderFileName;
4506 executableFileName, optHeaderFileName.c_str());
4512 std::string fullheader(optHeaderFileName);
4515 if (fullheader[fullheader.length() - 1] ==
'+') {
4516 fullheader.erase(fullheader.length() - 1);
4521 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4522 if (!isSelectionFile) {
4530 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4531 pcmArgs.push_back(header);
4533 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4538 bool hasSelectionFile = !linkdef.empty();
4539 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4550 if (!newName.empty())
4563 string incCurDir =
"-I";
4564 incCurDir += currentDirectory;
4565 pcmArgs.push_back(incCurDir);
4570 std::stringstream res;
4571 const char* delim=
"\n";
4572 std::copy(diagnosticPragmas.begin(),
4573 diagnosticPragmas.end(),
4574 std::ostream_iterator<std::string>(res, delim));
4575 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4581 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4583 IgnoringPragmaHandler(
const char* pragma):
4584 clang::PragmaNamespace(pragma) {}
4585 void HandlePragma(clang::Preprocessor &PP,
4586 clang::PragmaIntroducer Introducer,
4587 clang::Token &tok)
override {
4588 PP.DiscardUntilEndOfDirective();
4594 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4595 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4596 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4597 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4599 if (!interpreterDeclarations.empty() &&
4600 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4612 pcmArgs.push_back(linkdef);
4620 interp.AddIncludePath(inclPath);
4622 std::stringstream definesUndefinesStr;
4625 if (!definesUndefinesStr.str().empty()) {
4626 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4627 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4638 if (linkdef.empty()) {
4644 std::ofstream fileout;
4646 std::ostream *splitDictStream =
nullptr;
4647 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4669 splitDeleter.reset(splitDictStream);
4671 splitDictStream = &dictStream;
4674 size_t dh = main_dictname.rfind(
'.');
4675 if (dh != std::string::npos) {
4676 main_dictname.erase(dh);
4679 std::string main_dictname_copy(main_dictname);
4701 string linkdefFilename;
4702 if (linkdef.empty()) {
4703 linkdefFilename =
"in memory";
4705 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4713 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4719 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4721 std::string extraIncludes;
4726 const unsigned int selRulesInitialSize = selectionRules.
Size();
4730 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4734 int rootclingRetCode(0);
4738 std::ifstream file(linkdefFilename.c_str());
4739 if (file.is_open()) {
4752 clingArgs.push_back(
"-Ietc/cling/cint");
4754 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4755 llvmResourceDir.c_str())) {
4757 rootclingRetCode += 1;
4767 }
else if (isSelXML) {
4771 std::ifstream file(linkdefFilename.c_str());
4772 if (file.is_open()) {
4776 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4812 dictStream <<
"#include \"TBuffer.h\"\n"
4813 <<
"#include \"TVirtualObject.h\"\n"
4814 <<
"#include <vector>\n"
4815 <<
"#include \"TSchemaHelper.h\"\n\n";
4817 std::list<std::string> includes;
4819 for (
auto & incFile : includes) {
4820 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4822 dictStream << std::endl;
4827 int scannerVerbLevel = 0;
4830 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4832 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4855 scan.
Scan(CI->getASTContext());
4857 bool has_input_error =
false;
4864 !dictSelRulesPresent &&
4871 if (rootclingRetCode)
return rootclingRetCode;
4878 if (annRcd.RequestNoInputOperator()) {
4890 if (has_input_error) {
4900 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4901 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4929 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4930 constructorTypes.emplace_back(
"__void__", interp);
4931 constructorTypes.emplace_back(
"", interp);
4962 if (rootclingRetCode != 0) {
4963 return rootclingRetCode;
4982 std::string detectedUmbrella;
4983 for (
auto & arg : pcmArgs) {
4985 detectedUmbrella = arg;
4991 headersDeclsMap.clear();
4995 std::string headersClassesMapString =
"\"\"";
4996 std::string fwdDeclsString =
"\"\"";
5012 if (modGen.
IsPCH()) {
5015 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
5025 ofstream outputfile(liblist_filename.c_str(), ios::out);
5028 executableFileName, liblist_filename.c_str());
5030 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
5031 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
5033 outputfile <<
"# Now the list of classes\n";
5038 outputfile << annRcd.GetNormalizedName() << endl;
5045 if (0 != rootclingRetCode)
return rootclingRetCode;
5051 [](
const std::string &
a,
const std::string &
b) -> std::string {
5052 if (a.empty()) return b;
5053 else return a +
" " + b;
5058 std::list<std::string> classesNames;
5059 std::list<std::string> classesNamesForRootmap;
5060 std::list<std::string> classesDefsList;
5064 classesNamesForRootmap,
5068 std::list<std::string> enumNames;
5073 std::list<std::string> varNames;
5078 if (0 != rootclingRetCode)
return rootclingRetCode;
5081 if (rootMapNeeded) {
5083 std::list<std::string> nsNames;
5092 rootmapLibName.c_str());
5095 std::unordered_set<std::string> headersToIgnore;
5098 headersToIgnore.insert(optHeaderFileName.c_str());
5100 std::list<std::string> typedefsRootmapLines;
5108 classesNamesForRootmap,
5110 typedefsRootmapLines,
5116 if (0 != rootclingRetCode)
return 1;
5126 cling::Interpreter::PushTransactionRAII RAII(&interp);
5127 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5138 if(rootclingRetCode == 0) {
5139 rootclingRetCode += tmpCatalog.
commit();
5144 return rootclingRetCode;
5155 unsigned int numberOfHeaders = 0;
5156 for (std::vector<std::string>::iterator it = headersNames.begin();
5157 it != headersNames.end(); ++it) {
5158 const std::string headername(*it);
5163 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5164 headername.c_str());
5167 return numberOfHeaders;
5173 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5176 unsigned int argvCounter = 0;
5177 for (
int i = 1; i < argc; ++i) {
5180 args.push_back(argv[i]);
5182 }
else if (argvCounter) {
5183 argv[i - argvCounter] = argv[i];
5190 std::cout <<
"Args: \n";
5191 for (std::vector<std::string>::iterator it = args.begin();
5192 it < args.end(); ++it) {
5193 std::cout << i <<
") " << *it << std::endl;
5207 if (std::string::npos !=
result) {
5219 const unsigned int size(str.size());
5220 char *
a =
new char[
size + 1];
5222 memcpy(
a, str.c_str(),
size);
5238 std::vector<std::string> &ofilesnames)
5240 ofilesnames.reserve(headersNames.size());
5242 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5243 it != headersNames.end(); ++it) {
5244 std::string ofilename(*it);
5246 ofilesnames.push_back(ofilename);
5253 const std::vector<std::string> &argsToBeAdded,
5254 const std::string &optName =
"")
5256 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5257 it != argsToBeAdded.end(); ++it) {
5265 const std::vector<std::string> &argsToBeAdded,
5266 const std::string &optName =
"")
5268 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5269 it != argsToBeAdded.end(); ++it) {
5270 if (optName.length()) {
5280 const std::string &selectionFileName,
5281 const std::string &targetLibName,
5283 const std::vector<std::string> &pcmsNames,
5284 const std::vector<std::string> &includes,
5285 const std::vector<std::string> &preprocDefines,
5286 const std::vector<std::string> &preprocUndefines,
5287 const std::vector<std::string> &warnings,
5288 const std::string &rootmapFileName,
5289 const std::string &rootmapLibName,
5290 bool interpreteronly,
5293 bool writeEmptyRootPCM,
5295 bool noIncludePaths,
5296 bool noGlobalUsingStd,
5297 const std::vector<std::string> &headersNames,
5298 bool failOnWarnings,
5299 const std::string &ofilename)
5303 std::vector<char *> argvVector;
5314 std::string dictLocation;
5320 std::string newRootmapLibName(rootmapLibName);
5321 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5322 if (headersNames.size() != 1) {
5324 "*** genreflex: No rootmap lib and several header specified!\n");
5327 newRootmapLibName =
"lib";
5328 newRootmapLibName += cleanHeaderName;
5334 std::string newRootmapFileName(rootmapFileName);
5335 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5336 newRootmapFileName = dictLocation + newRootmapFileName;
5341 if (!newRootmapFileName.empty()) {
5347 if (!newRootmapLibName.empty()) {
5353 if (interpreteronly)
5361 if (!targetLibName.empty()) {
5371 if (noGlobalUsingStd)
5381 if (writeEmptyRootPCM)
5404 if (!selectionFileName.empty()) {
5408 const int argc = argvVector.size();
5412 std::cout <<
"Rootcling commandline:\n";
5413 for (
int i = 0; i < argc; i++)
5414 std::cout << i <<
") " << argvVector[i] << std::endl;
5417 char **argv = & (argvVector[0]);
5422 for (
int i = 0; i < argc; i++)
5423 delete [] argvVector[i];
5425 return rootclingReturnCode;
5434 const std::string &selectionFileName,
5435 const std::string &targetLibName,
5437 const std::vector<std::string> &pcmsNames,
5438 const std::vector<std::string> &includes,
5439 const std::vector<std::string> &preprocDefines,
5440 const std::vector<std::string> &preprocUndefines,
5441 const std::vector<std::string> &warnings,
5442 const std::string &rootmapFileName,
5443 const std::string &rootmapLibName,
5444 bool interpreteronly,
5447 bool writeEmptyRootPCM,
5449 bool noIncludePaths,
5450 bool noGlobalUsingStd,
5451 const std::vector<std::string> &headersNames,
5452 bool failOnWarnings,
5453 const std::string &outputDirName_const =
"")
5455 std::string outputDirName(outputDirName_const);
5457 std::vector<std::string> ofilesNames;
5464 std::vector<std::string> namesSingleton(1);
5465 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5466 namesSingleton[0] = headersNames[i];
5467 std::string ofilenameFullPath(ofilesNames[i]);
5468 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5469 ofilenameFullPath = outputDirName + ofilenameFullPath;
5491 if (returnCode != 0)
5506 std::vector<std::string> &values)
5509 if (options[oIndex]) {
5510 const int nVals = options[oIndex].count();
5511 values.reserve(nVals);
5512 int optionIndex = 0;
5515 << optionIndex <<
"/" << nVals <<
" "
5516 << opt->arg << std::endl;
5518 values.push_back(opt->arg);
5529 const char *descriptor)
5531 if (options[optionIndex]) {
5533 "*** genereflex: %s is not supported anymore.\n",
5590 enum optionIndex { UNKNOWN,
5621 enum optionTypes { NOTYPE, STRING } ;
5624 const char *genreflexUsage =
5625 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5626 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5629 const char *selectionFilenameUsage =
5630 "-s, --selection_file\tSelection filename\n"
5631 " Class selection file to specify for which classes the dictionary\n"
5632 " will be generated. The final set can be crafted with exclusion and\n"
5633 " exclusion rules.\n"
5634 " Properties can be specified. Some have special meaning:\n"
5635 " - name [string] name of the entity to select with an exact matching\n"
5636 " - pattern [string] name with wildcards (*) to select entities\n"
5637 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5638 " file where the C++ entities reside and not to C++ entities themselves.\n"
5639 " - transient/persistent [string: true/false] The fields to which they are\n"
5640 " applied will not be persistified if requested.\n"
5641 " - comment [string]: what you could write in code after an inline comment\n"
5642 " without \"//\". For example comment=\"!\" or \"||\".\n"
5643 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5644 " Default value is 'false'\n"
5645 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5646 " to 'true'. Default value is 'false'\n"
5650 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5651 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5652 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5653 " [noInputOperator=\"true/false\"] />\n"
5654 " <class name=\"classname\" >\n"
5655 " <field name=\"m_transient\" transient=\"true\"/>\n"
5656 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5657 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5658 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5660 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5661 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5662 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5665 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5666 " <method name=\"unwanted\" />\n"
5671 " If no selection file is specified, the class with the filename without\n"
5672 " extension will be selected, i.e. myClass.h as argument without any\n"
5673 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5675 const char *outputFilenameUsage =
5676 "-o, --output\tOutput filename\n"
5677 " Output file name. If an existing directory is specified instead of a file,\n"
5678 " then a filename will be built using the name of the input file and will\n"
5679 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5680 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5681 " have unique names.\n";
5684 const char *targetLib =
5685 "-l, --library\tTarget library\n"
5686 " The flag -l must be followed by the name of the library that will\n"
5687 " contain the object file corresponding to the dictionary produced by\n"
5688 " this invocation of genreflex.\n"
5689 " The name takes priority over the one specified for the rootmapfile.\n"
5690 " The name influences the name of the created pcm:\n"
5691 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5692 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5693 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5694 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5695 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5697 const char *rootmapUsage =
5698 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5699 " This file lists the autoload keys. For example classes for which the\n"
5700 " reflection information is provided.\n"
5701 " The format of the rootmap is the following:\n"
5702 " - Forward declarations section\n"
5703 " - Libraries sections\n"
5704 " Rootmaps can be concatenated together, for example with the cat util.\n"
5705 " In order for ROOT to pick up the information in the rootmaps, they\n"
5706 " have to be located in the library path and have the .rootmap extension.\n"
5707 " An example rootmap file could be:\n"
5709 " template <class T> class A;\n"
5710 " [ libMyLib.so ]\n"
5711 " class A<double>\n"
5716 const char *rootmapLibUsage =
5717 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5750 "--multiDict\tSupport for many dictionaries in one library\n"
5751 " Form correct pcm names if multiple dictionaries will be in the same\n"
5752 " library (needs target library switch. See its documentation).\n"
5759 "" ,
"noGlobalUsingStd" ,
5761 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5762 " All header files must have sumbols from std:: namespace fully qualified\n"
5768 "s" ,
"selection_file" ,
5770 selectionFilenameUsage
5784 "" ,
"rootmap-lib" ,
5792 "" ,
"interpreteronly",
5794 "--interpreteronly\tDo not generate I/O related information.\n"
5795 " Generate minimal dictionary required for interactivity.\n"
5803 "--split\tSplit the dictionary\n"
5804 " Split in two the dictionary, isolating the part with\n"
5805 " ClassDef related functions in a separate file.\n"
5813 "-m \tPcm file loaded before any header (option can be repeated).\n"
5821 "-v, --verbose\tPrint some debug information.\n"
5829 "--debug\tPrint all debug information.\n"
5837 "--quiet\tPrint only warnings and errors (default).\n"
5845 "--silent\tPrint no information at all.\n"
5851 "" ,
"writeEmptyPCM",
5853 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5861 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5870 "--help\tPrint usage and exit.\n"
5876 "",
"fail_on_warnings",
5878 "--fail_on_warnings\tFail on warnings and errors.\n"
5884 "",
"selSyntaxOnly",
5886 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5892 "" ,
"noIncludePaths",
5894 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5933 "" ,
"no_membertypedefs" ,
5941 "" ,
"no_templatetypedefs" ,
5946 {0, 0,
nullptr,
nullptr,
nullptr,
nullptr}
5949 std::vector<std::string> headersNames;
5950 const int originalArgc = argc;
5952 const int extractedArgs = extractArgs(argc, argv, headersNames);
5955 argc -=
offset + extractedArgs;
5960 std::vector<ROOT::option::Option> options(stats.
options_max);
5961 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5967 if (parse.
error()) {
5973 if (options[HELP] || originalArgc == 1) {
5978 int numberOfHeaders = checkHeadersNames(headersNames);
5979 if (0 == numberOfHeaders) {
5990 std::string verbosityOption(
"-v2");
5991 if (options[SILENT]) verbosityOption =
"-v0";
5992 if (options[VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5993 if (options[
DEBUG]) verbosityOption =
"-v4";
5998 std::string selectionFileName;
5999 if (options[SELECTIONFILENAME]) {
6000 selectionFileName = options[SELECTIONFILENAME].arg;
6003 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
6004 selectionFileName.c_str());
6019 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
6020 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
6023 std::string targetLibName;
6024 if (options[TARGETLIB]) {
6025 targetLibName = options[TARGETLIB].arg;
6028 "Invalid target library extension: filename is %s and extension %s is expected!\n",
6029 targetLibName.c_str(),
6033 if (options[ROOTMAP]) {
6038 bool isCxxmodule = options[CXXMODULE];
6040 bool multidict =
false;
6041 if (options[MULTIDICT]) multidict =
true;
6043 bool noGlobalUsingStd =
false;
6044 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
6046 if (multidict && targetLibName.empty()) {
6048 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
6052 bool interpreteronly =
false;
6053 if (options[INTERPRETERONLY])
6054 interpreteronly =
true;
6056 bool doSplit =
false;
6060 bool writeEmptyRootPCM =
false;
6061 if (options[WRITEEMPTYROOTPCM])
6062 writeEmptyRootPCM =
true;
6064 bool selSyntaxOnly =
false;
6065 if (options[SELSYNTAXONLY]) {
6066 selSyntaxOnly =
true;
6069 bool noIncludePaths =
false;
6070 if (options[NOINCLUDEPATHS]) {
6071 noIncludePaths =
true;
6074 bool failOnWarnings =
false;
6075 if (options[FAILONWARNINGS]) {
6076 failOnWarnings =
true;
6085 std::vector<std::string> pcmsNames;
6089 std::vector<std::string> preprocDefines;
6093 std::vector<std::string> preprocUndefines;
6097 std::vector<std::string> includes;
6101 std::vector<std::string> warnings;
6112 int returnValue = 0;
6113 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6117 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6118 returnValue = invokeRootCling(verbosityOption,
6141 returnValue = invokeManyRootCling(verbosityOption,
6174 assert(!
gDriverConfig &&
"Driver configuration already set!");
6194 if (std::string::npos != exeName.find(
"genreflex"))
6202 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.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
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.