12#include "rootclingCommandLineOptionsHelp.h"
14#include "RConfigure.h"
34#include <unordered_map>
35#include <unordered_set>
47#define PATH_MAX _MAX_PATH
55#include <mach-o/dyld.h>
63#include <libprocstat.h>
72#include "cling/Interpreter/Interpreter.h"
73#include "cling/Interpreter/InterpreterCallbacks.h"
74#include "cling/Interpreter/LookupHelper.h"
75#include "cling/Interpreter/Value.h"
76#include "clang/AST/CXXInheritance.h"
77#include "clang/Basic/Diagnostic.h"
78#include "clang/Frontend/CompilerInstance.h"
79#include "clang/Frontend/FrontendActions.h"
80#include "clang/Frontend/FrontendDiagnostic.h"
81#include "clang/Lex/HeaderSearch.h"
82#include "clang/Lex/Preprocessor.h"
83#include "clang/Lex/ModuleMap.h"
84#include "clang/Lex/Pragma.h"
85#include "clang/Sema/Sema.h"
86#include "clang/Serialization/ASTWriter.h"
87#include "cling/Utils/AST.h"
89#include "llvm/ADT/StringRef.h"
91#include "llvm/Support/CommandLine.h"
92#include "llvm/Support/Path.h"
93#include "llvm/Support/PrettyStackTrace.h"
94#include "llvm/Support/Signals.h"
118#include <mach-o/dyld.h>
123#define strcasecmp _stricmp
124#define strncasecmp _strnicmp
132#define rootclingStringify(s) rootclingStringifyx(s)
133#define rootclingStringifyx(s) #s
140using std::string, std::map, std::ifstream, std::ofstream, std::endl, std::ios, std::vector;
157static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
161 for (
const auto td : tdvec)
162 gDriverConfig->fAddTypedefToROOTFile(td->getQualifiedNameAsString().c_str());
164static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
168 for (
const auto en : enumvec) {
170 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
171 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
172 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
173 gDriverConfig->fAddEnumToROOTFile(en->getQualifiedNameAsString().c_str());
182 static std::string exepath;
185 exepath = _dyld_get_image_name(0);
187#if defined(__linux) || defined(__linux__)
188 char linkname[PATH_MAX];
194 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
195 int ret = readlink(linkname, buf, 1024);
196 if (
ret > 0 &&
ret < 1024) {
202 procstat* ps = procstat_open_sysctl();
203 kinfo_proc* kp = kinfo_getproc(getpid());
206 char path_str[PATH_MAX] =
"";
207 procstat_getpathname(ps, kp, path_str,
sizeof(path_str));
215 char *buf =
new char[MAX_MODULE_NAME32 + 1];
216 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
218 while ((p = strchr(p,
'\\')))
224 return exepath.c_str();
230 const cling::Interpreter &interp)
238 const std::list<VariableSelectionRule> &fieldSelRules)
246 if (fieldSelRules.empty())
return;
248 clang::ASTContext &C = decl.getASTContext();
250 const std::string declName(decl.getNameAsString());
252 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
253 it != fieldSelRules.end(); ++it) {
255 if (declName == varName) {
258 BaseSelectionRule::AttributesMap_t::iterator iter;
259 std::string userDefinedProperty;
260 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
261 const std::string &
name = iter->first;
262 const std::string &value = iter->second;
270 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
271 const char *msg =
"Data member \"%s\" is an array or a pointer. "
272 "It is not possible to assign to it the iotype \"%s\". "
273 "This transformation is possible only with data members "
274 "which are not pointers or arrays.\n";
276 msg, varName.c_str(), value.c_str());
285 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, value,
nullptr, 0));
295 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C,
"!",
nullptr, 0));
303 decl.addAttr(clang::AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
313 cling::Interpreter &interpreter,
321 using namespace clang;
322 SourceLocation commentSLoc;
323 llvm::StringRef comment;
325 ASTContext &C = CXXRD.getASTContext();
328 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
329 auto declSelRulePair = declSelRulesMap.find(declBaseClassPtr->getCanonicalDecl());
330 if (declSelRulePair == declSelRulesMap.end()){
331 const std::string thisClassName(CXXRD.getName());
332 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
337 if (thisClassBaseSelectionRule) {
340 BaseSelectionRule::AttributesMap_t::iterator iter;
341 std::string userDefinedProperty;
342 for (
auto const & attr : thisClassBaseSelectionRule->
GetAttributes()) {
343 const std::string &
name = attr.first;
345 const std::string &value = attr.second;
348 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, userDefinedProperty,
nullptr, 0));
355 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
356 E = CXXRD.decls_end();
I != E; ++
I) {
360 if (!(*I)->isImplicit()
361 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
365 if (isClassDefMacro) {
366 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
372 if (comment.size()) {
374 if (isClassDefMacro) {
375 CXXRD.addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
376 }
else if (!isGenreflex) {
382 (*I)->addAttr(AnnotateAttr::CreateImplicit(C, comment.str(),
nullptr, 0));
387 if (isGenreflex && thisClassSelectionRule !=
nullptr) {
391 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
405 llvm::APInt len = arrayType->getSize();
406 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
407 len *= subArrayType->getSize();
408 arrayType = subArrayType;
410 return len.getLimitedValue();
416 const cling::Interpreter &interp)
418 static const clang::CXXRecordDecl *TObject_decl
421 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
428 const cling::Interpreter &interp)
430 static const clang::CXXRecordDecl *TObject_decl
440 size_t len = strlen(filename);
442 if (strlen(filename) >= xmllen) {
443 return (0 == strcasecmp(filename + (len - xmllen),
".xml"));
467 const char *expectedTokens[],
468 size_t *end =
nullptr)
471 if (
line[0] !=
'#')
return false;
473 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
475 size_t lenToken = strlen(*iToken);
476 if (
line.compare(
pos, lenToken, *iToken)) {
495 if (recordDecl->hasOwningModule()) {
496 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
499 std::string qual_name;
505 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
514 if (classname.find(
':') == std::string::npos)
return;
517 int slen = classname.size();
518 for (
int k = 0; k < slen; ++k) {
519 if (classname[k] ==
':') {
520 if (k + 1 >= slen || classname[k + 1] !=
':') {
525 string base = classname.substr(0, k);
530 autoloads[base] =
"";
534 }
else if (classname[k] ==
'<') {
546 std::string classname;
548 while (file >>
line) {
550 if (
line.find(
"Library.") != 0)
continue;
553 classname =
line.substr(8,
pos - 8);
558 getline(file,
line,
'\n');
559 while (
line[0] ==
' ')
line.replace(0, 1,
"");
563 if (classname ==
"ROOT::TImpProxy") {
567 autoloads[classname] =
line;
582 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
584 while (getline(file,
line,
'\n')) {
585 if (
line ==
"{ decls }") {
586 while (getline(file,
line,
'\n')) {
587 if (
line[0] ==
'[')
break;
590 const char firstChar =
line[0];
591 if (firstChar ==
'[') {
593 libs =
line.substr(1,
line.find(
']') - 1);
594 while (libs[0] ==
' ') libs.replace(0, 1,
"");
595 }
else if (0 != keyLenMap.count(firstChar)) {
596 unsigned int keyLen = keyLenMap.at(firstChar);
597 keyname =
line.substr(keyLen,
line.length() - keyLen);
599 autoloads[keyname] = libs;
609void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
611 std::ifstream filelist(fileListName.c_str());
613 std::string filename;
616 while (filelist >> filename) {
618 if (llvm::sys::fs::is_directory(filename))
continue;
620 ifstream file(filename.c_str());
624 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
626 file.seekg(0, std::ios::beg);
647 const string &fullname,
648 const clang::RecordDecl *cl,
649 cling::Interpreter &interp)
652 const clang::FunctionDecl *method
657 clang::TranslationUnitDecl *TU =
658 cl->getASTContext().getTranslationUnitDecl();
662 bool has_input_error =
false;
663 if (method !=
nullptr && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
665 if (strstr(filename.c_str(),
"TBuffer.h") !=
nullptr ||
666 strstr(filename.c_str(),
"Rtypes.h") !=
nullptr) {
668 has_input_error =
true;
671 has_input_error =
true;
673 if (has_input_error) {
675 const char *maybeconst =
"";
676 const char *mayberef =
"&";
677 if (
what[strlen(
what) - 1] ==
'<') {
678 maybeconst =
"const ";
682 "in this version of ROOT, the option '!' used in a linkdef file\n"
683 " implies the actual existence of customized operators.\n"
684 " The following declaration is now required:\n"
685 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
687 return has_input_error;
699 int ncha = fullname.length() + 13;
700 char *
proto =
new char[ncha];
712 return has_input_error;
718bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
724 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
728 bool isAbstract = clxx->isAbstract();
731 std::string qualName;
733 const char *qualName_c = qualName.c_str();
735 "because it inherits from TObject but does not "
736 "have its own ClassDef.\n",
749 if (
m.getType().isConstQualified()) {
750 string ret =
"const_cast< ";
753 if (type_name.substr(0,6)==
"const ") {
754 ret += type_name.c_str()+6;
760 ret +=
m.getName().str();
764 return prefix +
m.getName().str();
774 const cling::Interpreter &interp,
776 std::ostream &dictStream)
779 std::string mTypename;
792 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
794 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
795 if (!tmplt_specialization)
return 0;
801 string fulName1, fulName2;
802 const char *tcl1 =
nullptr, *tcl2 =
nullptr;
803 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
804 clang::QualType ti = arg0.getAsType();
808 fulName1 = ti.getAsString();
811 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
812 clang::QualType tmplti = arg1.getAsType();
815 fulName2 = tmplti.getAsString();
822 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
828 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
832 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
834 }
else if (
m.getType()->isPointerType()) {
839 dictStream <<
" {" << std::endl;
841 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
846 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
849 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
852 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
853 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
854 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
857 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
858 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
859 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
863 dictStream <<
" R__stl.clear();" << std::endl;
866 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
867 <<
" if (R__tcl1==0) {" << std::endl
868 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
869 << fulName1.c_str() <<
"!\");" << std::endl
870 <<
" return;" << std::endl
871 <<
" }" << std::endl;
874 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
875 <<
" if (R__tcl2==0) {" << std::endl
876 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
877 << fulName2.c_str() <<
"!\");" << std::endl
878 <<
" return;" << std::endl
879 <<
" }" << std::endl;
882 dictStream <<
" int R__i, R__n;" << std::endl
883 <<
" R__b >> R__n;" << std::endl;
886 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
888 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
892 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
912 std::string keyName(ti.getAsString());
913 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
914 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
915 <<
" R__stl.insert(R__t3);" << std::endl;
923 dictStream <<
" R__stl.insert(R__t);" << std::endl;
928 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
931 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
936 dictStream <<
" }" << std::endl
937 <<
" }" << std::endl;
938 if (isArr) dictStream <<
" }" << std::endl;
944 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
946 dictStream <<
" {" << std::endl;
949 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
952 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
955 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
958 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
962 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
963 <<
" R__b << R__n;" << std::endl
964 <<
" if(R__n) {" << std::endl;
967 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
968 <<
" if (R__tcl1==0) {" << std::endl
969 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
970 << fulName1.c_str() <<
"!\");" << std::endl
971 <<
" return;" << std::endl
972 <<
" }" << std::endl;
975 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
976 <<
" if (R__tcl2==0) {" << std::endl
977 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
978 <<
" return;" << std::endl
979 <<
" }" << std::endl;
982 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
983 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
985 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
986 clang::QualType tmplti = arg1.getAsType();
993 dictStream <<
" }" << std::endl
995 <<
" }" << std::endl;
996 if (isArr) dictStream <<
" }" << std::endl;
1008 std::string mTypenameStr;
1012 if (!strcmp(mTypeName,
"string")) {
1014 std::string fieldname =
m.getName().str();
1017 if (
m.getType()->isConstantArrayType()) {
1018 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1019 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1021 std::stringstream fullIdx;
1022 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1025 dictStream <<
" for (int R__i" <<
dim <<
"=0; R__i" <<
dim <<
"<"
1026 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" <<
dim <<
" )" << std::endl;
1027 fullIdx <<
"[R__i" <<
dim <<
"]";
1028 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1031 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1032 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1035 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1036 if (
m.getType()->isPointerType())
1037 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1038 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1040 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1044 if (
m.getType()->isPointerType())
1045 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1046 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1047 else if (
m.getType()->isConstantArrayType()) {
1048 std::stringstream fullIdx;
1049 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1052 dictStream <<
" for (int R__i" <<
dim <<
"=0; R__i" <<
dim <<
"<"
1053 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" <<
dim <<
" )" << std::endl;
1054 fullIdx <<
"[R__i" <<
dim <<
"]";
1055 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1058 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1060 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1071 if (
m.getType()->isPointerType()) {
1072 if (
m.getType()->getPointeeType()->isPointerType()) {
1084 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1086 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1088 dictStream <<
"[0]";
1089 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1104 int enclSpaceNesting = 0;
1111 dictStream <<
"#include \"TInterpreter.h\"\n";
1113 dictStream <<
"//_______________________________________"
1114 <<
"_______________________________________" << std::endl;
1115 if (add_template_keyword) dictStream <<
"template <> ";
1116 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(nullptr); // static to hold class pointer" << std::endl
1119 <<
"//_______________________________________"
1120 <<
"_______________________________________" << std::endl;
1121 if (add_template_keyword) dictStream <<
"template <> ";
1122 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1123 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1125 dictStream <<
"//_______________________________________"
1126 <<
"_______________________________________" << std::endl;
1127 if (add_template_keyword) dictStream <<
"template <> ";
1128 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1129 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1130 <<
"*)nullptr)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1132 <<
"//_______________________________________"
1133 <<
"_______________________________________" << std::endl;
1134 if (add_template_keyword) dictStream <<
"template <> ";
1135 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1136 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1137 <<
"*)nullptr)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1139 <<
"//_______________________________________"
1140 <<
"_______________________________________" << std::endl;
1141 if (add_template_keyword) dictStream <<
"template <> ";
1142 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1146 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1147 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1148 <<
"*)nullptr)->GetClass();" << std::endl
1149 <<
" return fgIsA;\n"
1150 <<
"}" << std::endl << std::endl
1152 <<
"//_______________________________________"
1153 <<
"_______________________________________" << std::endl;
1154 if (add_template_keyword) dictStream <<
"template <> ";
1155 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1157 dictStream <<
" Dictionary();\n";
1159 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1160 dictStream << fullname <<
"*)nullptr)->GetClass(); }" << std::endl;
1162 dictStream <<
" return fgIsA;" << std::endl
1163 <<
"}" << std::endl << std::endl;
1165 while (enclSpaceNesting) {
1166 dictStream <<
"} // namespace " << nsname << std::endl;
1175 cling::Interpreter &interp,
1176 std::ostream &dictStream)
1178 if (cl->isAnonymousNamespace()) {
1190 if (classname !=
"ROOT") {
1194 dictStream <<
" namespace ROOTDict {" << std::endl;
1197 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1201 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1202 dictStream << std::endl
1204 <<
" // Function generating the singleton type initializer" << std::endl
1207 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1208 <<
" {" << std::endl
1210 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1211 <<
" {" << std::endl
1214 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1216 <<
" instance(\"" << classname.c_str() <<
"\", ";
1219 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1221 dictStream <<
"0 /*version*/, ";
1225 for (
unsigned int i = 0; i < filename.length(); i++) {
1226 if (filename[i] ==
'\\') filename[i] =
'/';
1229 <<
" ::ROOT::Internal::DefineBehavior((void*)nullptr,(void*)nullptr)," << std::endl
1233 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1235 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1238 dictStream << 0 <<
");" << std::endl
1240 <<
" return &instance;" << std::endl
1241 <<
" }" << std::endl
1242 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1243 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1244 <<
" // Static variable to force the class initialization" << std::endl
1246 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1247 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1250 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1251 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1252 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1253 <<
" }" << std::endl << std::endl;
1256 dictStream <<
" }" << std::endl;
1258 dictStream <<
"}" << std::endl;
1260 dictStream << std::endl;
1269llvm::StringRef
GrabIndex(
const cling::Interpreter& interp,
const clang::FieldDecl &member,
int printError)
1272 llvm::StringRef where;
1275 if (index.size() == 0 && printError) {
1276 const char *errorstring;
1279 errorstring =
"is not an integer";
1282 errorstring =
"has not been defined before the array";
1285 errorstring =
"is a private member of a parent class";
1288 errorstring =
"is not known";
1291 errorstring =
"UNKNOWN ERROR!!!!";
1294 if (where.size() == 0) {
1296 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1299 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1308 const cling::Interpreter &interp,
1310 std::ostream &dictStream)
1312 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1313 if (clxx ==
nullptr)
return;
1320 int enclSpaceNesting = 0;
1326 dictStream <<
"//_______________________________________"
1327 <<
"_______________________________________" << std::endl;
1328 if (add_template_keyword) dictStream <<
"template <> ";
1329 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1330 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1338 int basestreamer = 0;
1339 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1343 string base_fullname;
1346 if (strstr(base_fullname.c_str(),
"::")) {
1348 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1349 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1350 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1352 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1357 if (!basestreamer) {
1358 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1359 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1361 dictStream <<
"}" << std::endl << std::endl;
1362 while (enclSpaceNesting) {
1363 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1370 string classname = fullname;
1371 if (strstr(fullname.c_str(),
"::")) {
1373 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1374 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1375 classname =
"thisClass";
1377 for (
int i = 0; i < 2; i++) {
1382 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1383 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1384 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1386 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1387 dictStream <<
" } else {" << std::endl;
1388 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1393 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1397 string base_fullname;
1400 if (strstr(base_fullname.c_str(),
"::")) {
1402 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1403 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1404 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1407 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1413 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1418 clang::QualType
type = field_iter->getType();
1419 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1429 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1433 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1436 if (strncmp(comment,
"!", 1)) {
1439 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1440 if (
type.getTypePtr()->isConstantArrayType() &&
1441 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1442 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1446 dictStream <<
" int R__i;" << std::endl;
1449 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1451 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());
1452 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1454 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1456 }
else if (
type.getTypePtr()->isPointerType()) {
1457 llvm::StringRef indexvar =
GrabIndex(interp, **field_iter, i == 0);
1458 if (indexvar.size() == 0) {
1460 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1461 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1463 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1467 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1472 <<
"," << indexvar.str() <<
");" << std::endl;
1473 }
else if (isDouble32) {
1475 <<
"," << indexvar.str() <<
");" << std::endl;
1478 <<
"," << indexvar.str() <<
");" << std::endl;
1482 dictStream <<
" R__b.WriteFastArrayFloat16("
1483 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1484 }
else if (isDouble32) {
1485 dictStream <<
" R__b.WriteFastArrayDouble32("
1486 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1488 dictStream <<
" R__b.WriteFastArray("
1489 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1493 }
else if (
type.getTypePtr()->isArrayType()) {
1495 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1496 if (underling_type->isEnumeralType())
1497 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1501 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1502 }
else if (isDouble32) {
1504 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1507 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1511 if (underling_type->isEnumeralType()) {
1512 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1515 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1516 }
else if (isDouble32) {
1517 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1520 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1525 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1528 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1529 if (underling_type->isEnumeralType())
1530 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1531 << s <<
");" << std::endl;
1532 else if (isFloat16) {
1534 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1535 }
else if (isDouble32) {
1537 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1540 <<
"*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1543 if (underling_type->isEnumeralType())
1544 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1545 else if (isFloat16) {
1546 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1547 }
else if (isDouble32) {
1548 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1550 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " << s <<
");" << std::endl;
1554 }
else if (underling_type->isEnumeralType()) {
1556 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1557 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1559 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1564 <<
"=Float16_t(R_Dummy);}" << std::endl;
1567 }
else if (isDouble32) {
1570 <<
"=Double32_t(R_Dummy);}" << std::endl;
1592 if (
type.getTypePtr()->isConstantArrayType() &&
1593 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1594 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1598 dictStream <<
" int R__i;" << std::endl;
1601 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1606 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1611 dictStream <<
"[R__i];" << std::endl;
1612 }
else if (
type.getTypePtr()->isPointerType()) {
1620 ROOT::TMetaUtils::Error(
nullptr,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1621 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1623 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1627 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1641 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1647 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1651 dictStream <<
" int R__i;" << std::endl;
1654 dictStream <<
" for (R__i = 0; R__i < " << s <<
"; R__i++)" << std::endl;
1655 std::string mTypeNameStr;
1657 const char *mTypeName = mTypeNameStr.c_str();
1658 const char *constwd =
"const ";
1659 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1660 mTypeName += strlen(constwd);
1661 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1663 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1667 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1673 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1674 << field_iter->getName().str() <<
"));" << std::endl;
1685 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1686 <<
" }" << std::endl
1687 <<
"}" << std::endl << std::endl;
1689 while (enclSpaceNesting) {
1690 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1698 const cling::Interpreter &interp,
1700 std::ostream &dictStream)
1704 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1705 if (clxx ==
nullptr)
return;
1710 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1722 int enclSpaceNesting = 0;
1728 dictStream <<
"//_______________________________________"
1729 <<
"_______________________________________" << std::endl;
1730 if (add_template_keyword) dictStream <<
"template <> ";
1731 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1733 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1734 <<
" if (R__b.IsReading()) {" << std::endl
1735 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1736 <<
" } else {" << std::endl
1737 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1738 <<
" }" << std::endl
1739 <<
"}" << std::endl << std::endl;
1741 while (enclSpaceNesting) {
1742 dictStream <<
"} // namespace " << nsname << std::endl;
1750 const cling::Interpreter &interp,
1752 std::ostream &dictStream,
1753 bool isAutoStreamer)
1755 if (isAutoStreamer) {
1767bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1772 static const char *fopenopts =
"rb";
1774 static const char *fopenopts =
"r";
1778 fp = fopen(pname.c_str(), fopenopts);
1784 llvm::SmallVector<std::string, 10> includePaths;
1786 interp.GetIncludePaths(includePaths,
false,
false);
1788 const size_t nPaths = includePaths.size();
1789 for (
size_t i = 0; i < nPaths; i += 1 ) {
1793 fp = fopen(pname.c_str(), fopenopts);
1815 const char *inc = strstr(original,
"\\inc\\");
1817 inc = strstr(original,
"/inc/");
1818 if (inc && strlen(inc) > 5)
1838 cling::Interpreter &interp,
1841 std::ostringstream out;
1846 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1847 const std::string &hdrName
1865static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
1866 llvm::StringRef iSysRoot,
1867 clang::Module *module =
nullptr)
1870 llvm::SmallVector<char, 128> buffer;
1871 llvm::BitstreamWriter stream(buffer);
1872 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
1873 std::unique_ptr<llvm::raw_ostream> out =
1874 compilerInstance->createOutputFile(fileName,
true,
1883 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
1885 writer.WriteAST(&compilerInstance->getSema(), fileName.str(), module, iSysRoot);
1888 out->write(&buffer.front(), buffer.size());
1900 const std::string ¤tDirectory)
1902 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
1904 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
1912static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
1915 if (headers.empty())
1919 std::stringstream includes;
1920 for (
const std::string &header : headers) {
1921 includes <<
"#include \"" << header <<
"\"\n";
1923 std::string includeListStr = includes.str();
1924 auto result = interpreter.declare(includeListStr);
1925 return result == cling::Interpreter::CompilationResult::kSuccess;
1933 char platformDefines[64] = {0};
1934#ifdef __INTEL_COMPILER
1935 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
1936 clingArgs.push_back(platformDefines);
1939 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
1940 clingArgs.push_back(platformDefines);
1943 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
1944 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
1945 clingArgs.push_back(platformDefines);
1947#ifdef __GNUC_MINOR__
1948 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
1949 clingArgs.push_back(platformDefines);
1952 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
1953 clingArgs.push_back(platformDefines);
1956 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
1957 clingArgs.push_back(platformDefines);
1960 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
1961 clingArgs.push_back(platformDefines);
1963#ifdef _STLPORT_VERSION
1965 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
1966 clingArgs.push_back(platformDefines);
1969 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
1970 clingArgs.push_back(platformDefines);
1973 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
1974 clingArgs.push_back(platformDefines);
1977 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
1978 clingArgs.push_back(platformDefines);
1981 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
1982 clingArgs.push_back(platformDefines);
1985 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
1986 clingArgs.push_back(platformDefines);
1989 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
1990 clingArgs.push_back(platformDefines);
1994 snprintf(platformDefines, 64,
"-DG__WIN64=%ld", (
long)_WIN64);
1995 clingArgs.push_back(platformDefines);
1998 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
1999 clingArgs.push_back(platformDefines);
2000 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2001 clingArgs.push_back(platformDefines);
2002#if defined(_WIN64) && defined(_DEBUG)
2003 snprintf(platformDefines, 64,
"-D_ITERATOR_DEBUG_LEVEL=0");
2004 clingArgs.push_back(platformDefines);
2014 return llvm::sys::path::filename(path).str();
2024 if (std::string::npos !=
pos) {
2025 dirname.assign(path.begin(), path.begin() +
pos + 1);
2036 std::string dictLocation;
2038 return !dictLocation.empty();
2044 std::string &rootmapLibName)
2048 if (rootmapFileName.empty()) {
2050 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2051 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2052 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2054 rootmapLibName.c_str(),
2055 rootmapFileName.c_str());
2064 std::string &ctxtName,
2065 const cling::Interpreter &interpreter,
2066 bool treatParent =
true)
2068 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2070 if (!outerCtxt)
return;
2072 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2082 std::string &ctxtName,
2083 const cling::Interpreter &interpreter)
2085 const clang::DeclContext *theContext = theDecl.getDeclContext();
2093 const cling::Interpreter &interp)
2095 if (!decls.empty()) {
2096 std::string autoLoadKey;
2097 for (
auto &
d : decls) {
2101 if (autoLoadKey.empty()) {
2102 names.push_back(
d->getQualifiedNameAsString());
2120 const std::string &rootmapLibName,
2121 const std::list<std::string> &classesDefsList,
2122 const std::list<std::string> &classesNames,
2123 const std::list<std::string> &nsNames,
2124 const std::list<std::string> &tdNames,
2125 const std::list<std::string> &enNames,
2126 const std::list<std::string> &varNames,
2128 const std::unordered_set<std::string> headersToIgnore)
2131 std::ofstream rootmapFile(rootmapFileName.c_str());
2139 std::unordered_set<std::string> classesKeys;
2143 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2144 !enNames.empty() || !varNames.empty()) {
2147 if (!classesDefsList.empty()) {
2148 rootmapFile <<
"{ decls }\n";
2149 for (
auto & classDef : classesDefsList) {
2150 rootmapFile << classDef << std::endl;
2152 rootmapFile <<
"\n";
2154 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2157 if (!classesNames.empty()) {
2158 rootmapFile <<
"# List of selected classes\n";
2159 for (
auto & className : classesNames) {
2160 rootmapFile <<
"class " << className << std::endl;
2161 classesKeys.insert(className);
2164 std::unordered_set<std::string> treatedHeaders;
2165 for (
auto & className : classesNames) {
2167 if (className.find(
"<") != std::string::npos)
continue;
2168 if (headersClassesMap.count(className)) {
2169 auto &headers = headersClassesMap.at(className);
2170 if (!headers.empty()){
2171 auto &header = headers.front();
2172 if (treatedHeaders.insert(header).second &&
2173 headersToIgnore.find(header) == headersToIgnore.end() &&
2175 rootmapFile <<
"header " << header << std::endl;
2183 if (!nsNames.empty()) {
2184 rootmapFile <<
"# List of selected namespaces\n";
2185 for (
auto & nsName : nsNames) {
2186 rootmapFile <<
"namespace " << nsName << std::endl;
2191 if (!tdNames.empty()) {
2192 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2193 for (
const auto & autoloadKey : tdNames)
2194 if (classesKeys.insert(autoloadKey).second)
2195 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2200 if (!enNames.empty()){
2201 rootmapFile <<
"# List of selected enums and outer classes\n";
2202 for (
const auto & autoloadKey : enNames)
2203 if (classesKeys.insert(autoloadKey).second)
2204 rootmapFile <<
"enum " << autoloadKey << std::endl;
2208 if (!varNames.empty()){
2209 rootmapFile <<
"# List of selected vars\n";
2210 for (
const auto & autoloadKey : varNames)
2211 if (classesKeys.insert(autoloadKey).second)
2212 rootmapFile <<
"var " << autoloadKey << std::endl;
2226 auto nsPattern =
'{';
auto nsPatternLength = 1;
2227 auto foundNsPos =
line.find_last_of(nsPattern);
2228 if (foundNsPos == std::string::npos)
return {
"",
""};
2229 foundNsPos+=nsPatternLength;
2230 auto extNs =
line.substr(0,foundNsPos);
2232 auto nsEndPattern =
'}';
2233 auto foundEndNsPos =
line.find(nsEndPattern);
2234 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2236 return {extNs, contained};
2252 std::map<std::string, std::string> nsEntitiesMap;
2253 std::list<std::string> optFwdDeclList;
2254 for (
auto const & fwdDecl : fwdDeclarationsList){
2257 if (extNsAndEntities.first.empty()) {
2259 optFwdDeclList.push_front(fwdDecl);
2261 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2262 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2266 std::string optFwdDecl;
2267 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2268 optFwdDecl = extNsAndEntities.first;
2269 optFwdDecl += extNsAndEntities.second;
2270 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2273 optFwdDeclList.push_front(optFwdDecl);
2276 return optFwdDeclList;
2284 std::list<std::string> &el_list,
2285 std::unordered_set<std::string> &el_set)
2287 std::stringstream elStream(el);
2290 while (getline(elStream, tmp,
'\n')) {
2292 if (el_set.insert(tmp).second && !tmp.empty()) {
2293 el_list.push_back(tmp);
2304 std::list<std::string> &classesList,
2305 std::list<std::string> &classesListForRootmap,
2306 std::list<std::string> &fwdDeclarationsList,
2307 const cling::Interpreter &interpreter)
2315 std::unordered_set<std::string> classesSet;
2316 std::unordered_set<std::string> outerMostClassesSet;
2318 std::string attrName, attrValue;
2319 bool isClassSelected;
2320 std::unordered_set<std::string> availableFwdDecls;
2321 std::string fwdDeclaration;
2323 fwdDeclaration =
"";
2329 fwdDeclaration =
"";
2336 isClassSelected =
true;
2337 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2338 std::string normalizedName;
2339 normalizedName = selClass.GetNormalizedName();
2340 if (!normalizedName.empty() &&
2341 !classesSet.insert(normalizedName).second &&
2342 outerMostClassesSet.count(normalizedName) == 0) {
2343 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2344 <<
" was already selected. This means that two different instances of"
2345 <<
" clang::RecordDecl had the same name, which is not possible."
2346 <<
" This can be a hint of a serious problem in the class selection."
2347 <<
" In addition, the generated dictionary would not even compile.\n";
2350 classesList.push_back(normalizedName);
2353 const char *reqName(selClass.GetRequestedName());
2356 fwdDeclaration =
"";
2361 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2362 fwdDeclaration =
"";
2365 std::string fwdDeclarationTemplateSpec;
2367 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2375 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2377 attrName ==
"rootmap" &&
2378 attrValue ==
"false") {
2379 attrName = attrValue =
"";
2380 isClassSelected =
false;
2384 if (isClassSelected) {
2400 std::string outerMostClassName;
2402 if (!outerMostClassName.empty() &&
2403 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2404 classesSet.insert(outerMostClassName).second &&
2405 outerMostClassesSet.insert(outerMostClassName).second) {
2406 classesListForRootmap.push_back(outerMostClassName);
2408 classesListForRootmap.push_back(normalizedName);
2409 if (reqName && reqName[0] && reqName != normalizedName) {
2410 classesListForRootmap.push_back(reqName);
2415 std::string demangledName = selClass.GetDemangledTypeInfo();
2416 if (!demangledName.empty()) {
2421 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2423 classesListForRootmap.push_back(demangledName);
2429 classesListForRootmap.sort();
2442 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2457 if (clang::CXXRecordDecl *CXXRD =
2458 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2470 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2473 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2476 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2492 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2493 "#include \"TFile.h\"\n"
2494 "#include \"TObjArray.h\"\n"
2495 "#include \"TVirtualArray.h\"\n"
2496 "#include \"TStreamerElement.h\"\n"
2497 "#include \"TProtoClass.h\"\n"
2498 "#include \"TBaseClass.h\"\n"
2499 "#include \"TListOfDataMembers.h\"\n"
2500 "#include \"TListOfEnums.h\"\n"
2501 "#include \"TListOfEnumsWithLock.h\"\n"
2502 "#include \"TDataMember.h\"\n"
2503 "#include \"TEnum.h\"\n"
2504 "#include \"TEnumConstant.h\"\n"
2505 "#include \"TDictAttributeMap.h\"\n"
2506 "#include \"TMessageHandler.h\"\n"
2507 "#include \"TArray.h\"\n"
2508 "#include \"TRefArray.h\"\n"
2509 "#include \"root_std_complex.h\"\n")
2510 != cling::Interpreter::kSuccess)
2512 if (!
gDriverConfig->fCloseStreamerInfoROOTFile(writeEmptyRootPCM)) {
2522 bool isSelXML,
bool writeEmptyRootPCM)
2526 bool needsCollectionProxy =
false;
2546 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2547 if (nsName.find(
"(anonymous)") == std::string::npos)
2552 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2556 if (selClass.RequestOnlyTClass()) {
2564 if (clang::CXXRecordDecl *CXXRD =
2565 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2569 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2577 }
else if (CRD->getName() ==
"RVec") {
2578 static const clang::DeclContext *vecOpsDC =
nullptr;
2580 vecOpsDC = llvm::dyn_cast<clang::DeclContext>(
2581 interp.getLookupHelper().findScope(
"ROOT::VecOps", cling::LookupHelper::NoDiagnostics));
2582 if (vecOpsDC && vecOpsDC->Equals(CRD->getDeclContext())) {
2589 needsCollectionProxy);
2603 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2607 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2619 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2623 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2627 needsCollectionProxy);
2648 std::vector<std::string> standaloneTargets;
2659 if (finRetCode != 0)
return finRetCode;
2669 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2670 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2673 <<
"#define R__NO_DEPRECATION" << std::endl
2678 <<
"\n/*******************************************************************/\n"
2679 <<
"#include <cstddef>\n"
2680 <<
"#include <cstdio>\n"
2681 <<
"#include <cstdlib>\n"
2682 <<
"#include <cstring>\n"
2683 <<
"#include <cassert>\n"
2684 <<
"#define G__DICTIONARY\n"
2685 <<
"#include \"ROOT/RConfig.hxx\"\n"
2686 <<
"#include \"TClass.h\"\n"
2687 <<
"#include \"TDictAttributeMap.h\"\n"
2688 <<
"#include \"TInterpreter.h\"\n"
2689 <<
"#include \"TROOT.h\"\n"
2690 <<
"#include \"TBuffer.h\"\n"
2691 <<
"#include \"TMemberInspector.h\"\n"
2692 <<
"#include \"TInterpreter.h\"\n"
2693 <<
"#include \"TVirtualMutex.h\"\n"
2694 <<
"#include \"TError.h\"\n\n"
2695 <<
"#ifndef G__ROOT\n"
2696 <<
"#define G__ROOT\n"
2698 <<
"#include \"RtypesImp.h\"\n"
2699 <<
"#include \"TIsAProxy.h\"\n"
2700 <<
"#include \"TFileMergeInfo.h\"\n"
2701 <<
"#include <algorithm>\n"
2702 <<
"#include \"TCollectionProxyInfo.h\"\n"
2703 <<
"/*******************************************************************/\n\n"
2704 <<
"#include \"TDataMember.h\"\n\n";
2711 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2712 <<
"namespace std {} using namespace std;\n\n";
2718 const std::string &includeForSource,
2719 const std::string &extraIncludes)
2721 dictStream <<
"// Header files passed as explicit arguments\n"
2722 << includeForSource << std::endl
2723 <<
"// Header files passed via #pragma extra_include\n"
2724 << extraIncludes << std::endl;
2730#if defined(R__IOSSIM) || defined(R__IOS)
2755 return filename +
"_tmp_" + std::to_string(getpid());
2762 if (nameStr.empty())
return;
2767 const char *
name(nameStr.c_str());
2768 const char *tmpName(tmpNameStr.c_str());
2775 if (0 == std::rename(
name , tmpName)) {
2780 nameStr = tmpNameStr;
2791 for (
unsigned int i = 0; i <
m_size; ++i) {
2794 std::ifstream ifile(tmpName);
2799 if (ifile.is_open())
2801 if (0 != std::remove(tmpName)) {
2814 for (
unsigned int i = 0; i <
m_size; ++i) {
2818 std::ifstream ifile(tmpName);
2823 if (ifile.is_open())
2829 if (0 != std::rename(tmpName ,
name)) {
2830 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2831 llvm::sys::fs::remove(tmpName);
2835 if (0 != std::rename(tmpName ,
name)) {
2856 std::cout <<
"Restoring files in temporary file catalog:\n";
2857 for (
unsigned int i = 0; i <
m_size; ++i) {
2875 std::string splitDictName(tmpCatalog.
getFileName(dictpathname));
2876 const size_t dotPos = splitDictName.find_last_of(
".");
2877 splitDictName.insert(dotPos,
"_classdef");
2879 return new std::ofstream(splitDictName.c_str());
2888 std::list<std::string> &diagnosticPragmas)
2890 static const std::string pattern(
"-Wno-");
2892 if (arg.find(pattern) != 0)
2897 diagnosticPragmas.push_back(arg);
2903 cling::Interpreter &interp)
2906 std::string fwdDecl;
2907 std::string initStr(
"{");
2909 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
2910 auto &clTemplDecl = *strigNargsToKeepPair.first;
2914 + std::to_string(strigNargsToKeepPair.second)
2917 if (!fwdDeclnArgsToSkipColl.empty())
2928 if (qt.isNull())
return qt;
2929 clang::QualType thisQt(qt);
2930 while (thisQt->isPointerType() ||
2931 thisQt->isReferenceType()) {
2932 thisQt = thisQt->getPointeeType();
2942 const cling::Interpreter &interp,
2943 std::set<const clang::CXXRecordDecl *> &visitedDecls)
2945 std::list<std::string> headers;
2948 cling::Interpreter::PushTransactionRAII RAII(&interp);
2951 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
2955 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
2958 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
2959 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
2961 if (tArgQualType.isNull())
continue;
2962 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
2963 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
2970 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
2972 if (baseQualType.isNull())
continue;
2973 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
2974 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
2979 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
2980 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
2982 if (fieldQualType.isNull()) continue ;
2983 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
2984 if (fieldCxxRcd->hasDefinition())
2985 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
2991 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
2993 for (
auto & fPar : methodIt->parameters()) {
2995 if (fParQualType.isNull())
continue;
2996 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
2997 if (fParCxxRcd->hasDefinition())
2998 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3003 if (retQualType.isNull())
continue;
3004 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3005 if (retCxxRcd->hasDefinition())
3014 headers.emplace_back(header);
3027 if (
auto dclCtxt= rcd.getDeclContext()){
3028 if (! dclCtxt->isStdNamespace()){
3037 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3038 if (!clAsTmplSpecDecl)
return false;
3043 auto& astCtxt = rcd.getASTContext();
3044 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3045 for (
auto&& arg : templInstArgs.asArray()){
3047 auto argKind = arg.getKind();
3048 if (argKind != clang::TemplateArgument::Type){
3049 if (argKind == clang::TemplateArgument::Integral)
continue;
3053 auto argQualType = arg.getAsType();
3054 auto isPOD = argQualType.isPODType(astCtxt);
3056 if (isPOD)
continue;
3058 auto argType = argQualType.getTypePtr();
3059 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3062 if (isArgGoodForAutoParseMap)
continue;
3081 const cling::Interpreter &interp)
3083 std::set<const clang::CXXRecordDecl *> visitedDecls;
3084 std::unordered_set<std::string> buffer;
3085 std::string autoParseKey;
3088 for (
auto & annotatedRcd : annotatedRcds) {
3089 if (
const clang::CXXRecordDecl *cxxRcd =
3090 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3092 visitedDecls.clear();
3096 headers.remove_if([&buffer](
const std::string & s) {
3097 return !buffer.insert(s).second;
3100 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3102 headersDeclsMap[autoParseKey] = headers;
3103 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3105 ROOT::TMetaUtils::Info(
nullptr,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3110 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3111 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3112 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3118 for (
auto & tDef : tDefDecls) {
3119 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3121 visitedDecls.clear();
3126 headers.remove_if([&buffer](
const std::string & s) {
3127 return !buffer.insert(s).second;
3130 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3131 headersDeclsMap[autoParseKey] = headers;
3136 for (
auto & func : funcDecls) {
3142 for (
auto & var : varDecls) {
3148 for (
auto & en : enumDecls) {
3158 const cling::Interpreter &interp)
3160 std::string newFwdDeclString;
3164 std::string fwdDeclString;
3166 std::unordered_set<std::string> fwdDecls;
3187 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3192 selectedDecls.begin(),
3196 selectedDecls.push_back(TD);
3201 std::string fwdDeclLogs;
3209 std::cout <<
"Logs from forward decl printer: \n"
3226 if (fwdDeclString.empty()) fwdDeclString =
"";
3227 return fwdDeclString;
3234 const std::string &detectedUmbrella,
3235 bool payLoadOnly =
false)
3237 std::string headerName;
3240 std::cout <<
"Class-headers Mapping:\n";
3241 std::string headersClassesMapString =
"";
3242 for (
auto const & classHeaders : headersClassesMap) {
3244 std::cout <<
" o " << classHeaders.first <<
" --> ";
3245 headersClassesMapString +=
"\"";
3246 headersClassesMapString += classHeaders.first +
"\"";
3247 for (
auto const & header : classHeaders.second) {
3248 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3249 headersClassesMapString +=
", " + headerName;
3251 std::cout <<
", " << headerName;
3256 std::cout << std::endl;
3257 headersClassesMapString +=
", \"@\",\n";
3259 headersClassesMapString +=
"nullptr";
3260 return headersClassesMapString;
3283 static const std::vector<std::string> namePrfxes {
3286 auto pos = find_if(namePrfxes.begin(),
3288 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3289 return namePrfxes.end() ==
pos;
3296 static const std::vector<std::string> uclNamePrfxes {
3300 static const std::set<std::string> unsupportedClassesNormNames{
3303 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3304 auto pos = find_if(uclNamePrfxes.begin(),
3305 uclNamePrfxes.end(),
3306 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3307 return uclNamePrfxes.end() ==
pos;
3317 for (
auto&& aRcd : annotatedRcds){
3318 auto clName = aRcd.GetNormalizedName();
3320 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3321 <<
"currently the support for its I/O is not yet available. Note that "
3322 << clName <<
", even if not selected, will be available for "
3323 <<
"interpreted code.\n";
3327 std::cerr <<
"Error: It is not necessary to explicitly select class "
3328 << clName <<
". I/O is supported for it transparently.\n";
3343 InterpreterCallbacks(interp),
3349 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3350 clang::OptionalFileEntryRef , llvm::StringRef ,
3351 llvm::StringRef ,
const clang::Module * ,
bool ,
3352 clang::SrcMgr::CharacteristicKind )
override
3355 if (IsAngled)
return;
3356 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3357 auto curLexer = PP.getCurrentFileLexer();
3358 if (!curLexer)
return;
3359 auto fileEntry = curLexer->getFileEntry();
3360 if (!fileEntry)
return;
3361 auto thisFileName = fileEntry->getName();
3362 auto fileNameAsString = FileName.str();
3364 if (isThisLinkdef) {
3366 if (isTheIncludedLinkdef) {
3384 clang::SourceLocation ImportLoc,
3385 bool ForPragma)
override {
3387 using namespace clang;
3388 if (llvm::StringRef(M->Name).ends_with(
"ACLiC_dict")) {
3389 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3390 HeaderSearch& HS = PP.getHeaderSearchInfo();
3392 Module* CoreModule = HS.lookupModule(
"Core", SourceLocation(),
3394 assert(M &&
"Must have module Core");
3395 PP.makeModuleVisible(CoreModule, ImportLoc);
3401 llvm::cl::desc(
"Allow implicit build of system modules."),
3403static llvm::cl::list<std::string>
3406 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3409static llvm::cl::opt<std::string>
3411 llvm::cl::desc(
"<output dictionary file>"),
3443 using namespace clang::diag;
3449 std::string moduleName;
3450 const clang::Module *module =
nullptr;
3453 const auto &ID =
Info.getID();
3454 if (ID == remark_module_build || ID == remark_module_build_done) {
3455 moduleName =
Info.getArgStdStr(0);
3456 module = fMap.findModule(moduleName);
3462 "Couldn't find module %s in the available modulemaps. This"
3463 "prevents us from correctly diagnosing wrongly built modules.\n",
3464 moduleName.c_str());
3477 bool isByproductModule =
false;
3481 isByproductModule =
true;
3486 isByproductModule =
true;
3489 if (!isByproductModule)
3492 if (ID == remark_module_build && !isByproductModule) {
3494 "Building module '%s' implicitly. If '%s' requires a \n"
3495 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3496 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3498 moduleName.c_str(), moduleName.c_str());
3506 DiagnosticConsumer::clear();
3509 void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3511 fChild->BeginSourceFile(LangOpts, PP);
3512 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3518 DiagnosticConsumer::EndSourceFile();
3524 DiagnosticConsumer::finish();
3531#if defined(_WIN32) && defined(_MSC_VER)
3535 const char *EnablePopups = std::getenv(
"Cling_GuiOnAssert");
3536 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3537 ::_set_error_mode(_OUT_TO_STDERR);
3538 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3539 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3540 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3541 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3542 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3543 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3548static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3550static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3561static llvm::cl::opt<VerboseLevel>
3563 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3564 clEnumVal(
v0,
"Show only fatal errors."),
3565 clEnumVal(
v1,
"Show errors (the same as -v)."),
3566 clEnumVal(
v2,
"Show warnings (default)."),
3567 clEnumVal(
v3,
"Show notes."),
3568 clEnumVal(
v4,
"Show information.")),
3572static llvm::cl::opt<bool>
3573gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3576static llvm::cl::opt<bool>
3577gOptReflex(
"reflex", llvm::cl::desc(
"Behave internally like genreflex."),
3579static llvm::cl::opt<bool>
3580gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3583static llvm::cl::opt<std::string>
3585 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3588static llvm::cl::opt<bool>
3590 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3593static llvm::cl::opt<bool>
3594gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3596static llvm::cl::opt<bool>
3597gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3599static llvm::cl::list<std::string>
3601 llvm::cl::desc(
"Generate rootmap file."),
3603static llvm::cl::opt<std::string>
3605 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3607static llvm::cl::opt<bool>
3609 llvm::cl::desc(
"Generate a C++ module."),
3611static llvm::cl::list<std::string>
3613 llvm::cl::desc(
"Specify a C++ modulemap file."),
3616static llvm::cl::opt<bool>
3618 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3620static llvm::cl::opt<bool>
3622 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3624static llvm::cl::opt<bool>
3626 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3628static llvm::cl::opt<bool>
3630 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3632static llvm::cl::opt<bool>
3634 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3635information and another the interactivity support."),
3637static llvm::cl::opt<bool>
3640 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3642static llvm::cl::opt<std::string>
3644 llvm::cl::desc(
"The path to the library of the built dictionary."),
3646static llvm::cl::list<std::string>
3648 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3650static llvm::cl::list<std::string>
3652 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3656static llvm::cl::opt<bool>
3658 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3666static llvm::cl::opt<bool>
3669 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3671static llvm::cl::opt<bool>
3673 llvm::cl::desc(
"Check the selection syntax only."),
3675static llvm::cl::opt<bool>
3677 llvm::cl::desc(
"Fail if there are warnings."),
3679static llvm::cl::opt<bool>
3681 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3683static llvm::cl::opt<std::string>
3685 llvm::cl::desc(
"Specify an isysroot."),
3687 llvm::cl::init(
"-"));
3688static llvm::cl::list<std::string>
3690 llvm::cl::desc(
"Specify an include path."),
3692static llvm::cl::list<std::string>
3694 llvm::cl::desc(
"Specify a compiler default include path, to suppress unneeded `-isystem` arguments."),
3696static llvm::cl::list<std::string>
3698 llvm::cl::desc(
"Specify a system include path."),
3700static llvm::cl::list<std::string>
3702 llvm::cl::desc(
"Specify defined macros."),
3704static llvm::cl::list<std::string>
3706 llvm::cl::desc(
"Specify undefined macros."),
3708static llvm::cl::list<std::string>
3710 llvm::cl::desc(
"Specify compiler diagnostics options."),
3713static llvm::cl::list<std::string>
3715 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file | selection xml file>"),
3717static llvm::cl::list<std::string>
3719 llvm::cl::desc(
"Consumes all unrecognized options."),
3722static llvm::cl::SubCommand
3725static llvm::cl::list<std::string>
3727 llvm::cl::desc(
"Consumes options and sends them to cling."),
3737 clang::Module *module, std::vector<std::array<std::string, 2>> &missingHeaders)
3740 std::vector<clang::Module::Header> moduleHeaders;
3742 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3744 bool foundAllHeaders =
true;
3746 auto isHeaderInModule = [&moduleHeaders](
const std::string &header) {
3747 for (
const clang::Module::Header &moduleHeader : moduleHeaders)
3748 if (header == moduleHeader.NameAsWritten)
3756 for (
const std::string &header : modGen.
GetHeaders()) {
3757 if (isHeaderInModule(header))
3760 clang::ModuleMap::KnownHeader SuggestedModule;
3761 clang::ConstSearchDirIterator *CurDir =
nullptr;
3762 if (
auto FE = headerSearch.LookupFile(
3763 header, clang::SourceLocation(),
3766 clang::ArrayRef<std::pair<clang::OptionalFileEntryRef, clang::DirectoryEntryRef>>(),
3769 nullptr, &SuggestedModule,
3776 if (
auto OtherModule = SuggestedModule.getModule()) {
3777 std::string OtherModuleName;
3778 auto TLM = OtherModule->getTopLevelModuleName();
3780 OtherModuleName = TLM.str();
3782 OtherModuleName = OtherModule->Name;
3789 missingHeaders.push_back({header, OtherModuleName});
3792 missingHeaders.push_back({header, {}});
3794 foundAllHeaders =
false;
3796 return foundAllHeaders;
3802 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3804 clang::CompilerInstance *CI = interpreter.getCI();
3805 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3806 headerSearch.loadTopLevelSystemModules();
3809 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3814 moduleName.c_str());
3821 std::vector<std::array<std::string, 2>> missingHdrMod;
3824 std::stringstream msgStream;
3825 msgStream <<
"after creating module \"" << module->Name <<
"\" ";
3826 if (!module->PresumedModuleMapFile.empty())
3827 msgStream <<
"using modulemap \"" << module->PresumedModuleMapFile <<
"\" ";
3828 msgStream <<
"the following headers are not part of that module:\n";
3829 for (
auto &
H : missingHdrMod) {
3830 msgStream <<
" " <<
H[0];
3832 msgStream <<
" (already part of module \"" <<
H[1] <<
"\")";
3835 std::string warningMessage = msgStream.str();
3837 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3848 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3849 warningMessage.c_str(),
3856 std::vector<std::string> missingHeaders;
3857 std::transform(missingHdrMod.begin(), missingHdrMod.end(), missingHeaders.begin(),
3858 [](
const std::array<std::string, 2>& HdrMod) { return HdrMod[0];});
3861 module->Name.c_str());
3871 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
3872 moduleName.consume_front(
"lib");
3873 moduleName.consume_back(
".pcm");
3874 moduleName.consume_back(
"_rdict");
3882 bool isGenreflex =
false)
3893 const char *executableFileName = argv[0];
3895 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
3896 llvm::PrettyStackTraceProgram
X(argc, argv);
3899#if defined(R__WIN32) && !defined(R__WINGCC)
3904 for (
int iic = 1 ; iic < argc; ++iic) {
3905 std::string iiarg(argv[iic]);
3907 size_t len = iiarg.length();
3909 char *argviic =
new char[len + 1];
3910 strlcpy(argviic, iiarg.c_str(), len + 1);
3911 argv[iic] = argviic;
3920 auto &opts = llvm::cl::getRegisteredOptions();
3921 llvm::cl::Option* optHelp = opts[
"help"];
3922 llvm::cl::alias optHelpAlias1(
"h",
3923 llvm::cl::desc(
"Alias for -help"),
3924 llvm::cl::aliasopt(*optHelp));
3925 llvm::cl::alias optHelpAlias2(
"?",
3926 llvm::cl::desc(
"Alias for -help"),
3927 llvm::cl::aliasopt(*optHelp));
3929 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
3932 std::string llvmResourceDir = etcDir ? std::string(etcDir) +
"/cling" :
"";
3935 std::vector<const char *> clingArgsC;
3936 clingArgsC.push_back(executableFileName);
3939 clingArgsC.push_back(
"-I");
3940 clingArgsC.push_back(etcDir);
3947 clingArgsC.push_back(Opt.c_str());
3949 auto interp = std::make_unique<cling::Interpreter>(clingArgsC.size(),
3951 llvmResourceDir.c_str());
3954 return interp->getDiagnostics().hasFatalErrorOccurred();
3957 std::string dictname;
3971 llvm::cl::PrintHelpMessage();
3986 if ((fp = fopen(filein.c_str(),
"r")) ==
nullptr) {
3987 ROOT::TMetaUtils::Error(
nullptr,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4014 ROOT::TMetaUtils::Error(
nullptr,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4015 llvm::cl::PrintHelpMessage();
4019 std::vector<std::string> clingArgs;
4020 clingArgs.push_back(executableFileName);
4021 clingArgs.push_back(
"-iquote.");
4027 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4049 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4054 clingArgs.push_back(std::string(
"-D") + PPDefine);
4057 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4060 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4067 clingArgs.push_back(
"-isystem");
4068 clingArgs.push_back(llvm::sys::path::convert_to_slash(IncludePath));
4072 for (
const std::string &WDiag :
gOptWDiags) {
4073 const std::string FullWDiag = std::string(
"-W") + WDiag;
4077 clingArgs.push_back(FullWDiag);
4080 const char *includeDir =
gDriverConfig->fTROOT__GetIncludeDir();
4082 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(includeDir));
4085 std::vector<std::string> pcmArgs;
4086 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4087 auto thisArg = clingArgs[parg];
4089 if (thisArg ==
"-c" ||
4093 unsigned int offset = 2;
4094 char c = thisArg[offset];
4095 while (
c ==
' ')
c = thisArg[++offset];
4099 [&](
const std::string& path){
4100 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4101 if (excludePathsEnd != excludePathPos)
continue;
4103 pcmArgs.push_back(thisArg);
4108 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(etcDir));
4112 clingArgs.push_back(
"-D__ROOTCLING__");
4115 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4116#elif defined(R__WIN32)
4117 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4120 clingArgs.push_back(
"-D_XKEYCHECK_H");
4122 clingArgs.push_back(
"-DNOMINMAX");
4124 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4127 clingArgs.push_back(
"-fsyntax-only");
4129 clingArgs.push_back(
"-fPIC");
4131 clingArgs.push_back(
"-Xclang");
4132 clingArgs.push_back(
"-fmodules-embed-all-files");
4133 clingArgs.push_back(
"-Xclang");
4134 clingArgs.push_back(
"-main-file-name");
4135 clingArgs.push_back(
"-Xclang");
4136 clingArgs.push_back((dictname +
".h").c_str());
4144 std::string outputFile;
4146 llvm::StringRef moduleName;
4151 auto clingArgsInterpreter = clingArgs;
4160 clingArgsInterpreter.push_back(
"-fmodules");
4161 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4164 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4167 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + std::string(includeDir) +
"/ROOT.modulemap");
4170 if (llvm::sys::fs::exists(ModuleMapCWD))
4171 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4179 clingArgsInterpreter.push_back(
"-Xclang");
4180 clingArgsInterpreter.push_back(
"-fmodule-feature");
4181 clingArgsInterpreter.push_back(
"-Xclang");
4184 clingArgsInterpreter.push_back(
"-fmodule-name=" + moduleName.str());
4194 if (moduleName ==
"Core") {
4196 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4197 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4198 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4199 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4201 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4202 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4206 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4208 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4210 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4211 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4212 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4213 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4214 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4215 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4216 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4217 }
else if (moduleName ==
"MathCore") {
4218 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4223 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4227 clingArgsInterpreter.push_back(
"-v");
4230 std::vector<const char *> clingArgsC;
4231 for (
auto const &clingArg : clingArgsInterpreter) {
4233 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4234 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4237 clingArgsC.push_back(clingArg.c_str());
4241 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4242 cling::Interpreter* interpPtr =
nullptr;
4244 std::list<std::string> filesIncludedByLinkdef;
4248 clingArgsC.push_back(
"-ffast-math");
4251 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4252 llvmResourceDir.c_str()));
4253 interpPtr = owningInterpPtr.get();
4256 clingArgsC.push_back(
"-resource-dir");
4257 clingArgsC.push_back(llvmResourceDir.c_str());
4258 clingArgsC.push_back(
nullptr);
4259 const char ** &extraArgs = *
gDriverConfig->fTROOT__GetExtraInterpreterArgs();
4260 extraArgs = &clingArgsC[1];
4262 if (!interpPtr->getCI())
4265 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4266 interpPtr->setCallbacks(std::move(callBacks));
4269 cling::Interpreter &interp = *interpPtr;
4270 clang::CompilerInstance *CI = interp.getCI();
4272 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4273 CI->getSourceManager().setAllFilesAreTransient(
true);
4275 clang::Preprocessor &PP = CI->getPreprocessor();
4276 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4277 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4278 auto &diags = interp.getDiagnostics();
4285 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4290 diags.setClient(recordingClient,
true);
4296 interp.DumpIncludePath();
4301 interp.printIncludedFiles(llvm::outs());
4302 llvm::outs() <<
"\n\n";
4303 llvm::outs().flush();
4306 const clang::LangOptions& LangOpts
4307 = interp.getCI()->getASTContext().getLangOpts();
4308#define LANGOPT(Name, Bits, Default, Description) \
4309 ROOT::TMetaUtils::Info(nullptr, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4310#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4311#include "clang/Basic/LangOptions.def"
4315 interp.getOptions().ErrorOut =
true;
4316 interp.enableRawInput(
true);
4320 if (DepMod.ends_with(
"_rdict.pcm")) {
4327 cling::Interpreter::PushTransactionRAII RAII(&interp);
4328 if (!interp.loadModule(DepMod.str(),
false)) {
4337 if (interp.declare(
"#include <cassert>\n"
4338 "#include \"Rtypes.h\"\n"
4339 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4347 if (interp.declare(
"#include <string>\n"
4348 "#include <RtypesCore.h>\n"
4349 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4360 clingArgs.push_back(
"-D__CINT__");
4361 clingArgs.push_back(
"-D__MAKECINT__");
4367 std::string interpPragmaSource;
4368 std::string includeForSource;
4369 std::string interpreterDeclarations;
4370 std::string linkdef;
4376 if (isSelectionFile) {
4378 linkdef = optHeaderFileName;
4381 executableFileName, optHeaderFileName.c_str());
4387 std::string fullheader(optHeaderFileName);
4390 if (fullheader[fullheader.length() - 1] ==
'+') {
4391 fullheader.erase(fullheader.length() - 1);
4396 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4397 if (!isSelectionFile) {
4405 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4406 pcmArgs.push_back(header);
4408 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4413 bool hasSelectionFile = !linkdef.empty();
4414 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4425 if (!newName.empty())
4438 string incCurDir =
"-I";
4439 incCurDir += currentDirectory;
4440 pcmArgs.push_back(incCurDir);
4445 std::stringstream res;
4446 const char* delim=
"\n";
4447 std::copy(diagnosticPragmas.begin(),
4448 diagnosticPragmas.end(),
4449 std::ostream_iterator<std::string>(res, delim));
4450 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4456 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4458 IgnoringPragmaHandler(
const char* pragma):
4459 clang::PragmaNamespace(pragma) {}
4460 void HandlePragma(clang::Preprocessor &PP,
4461 clang::PragmaIntroducer Introducer,
4462 clang::Token &tok)
override {
4463 PP.DiscardUntilEndOfDirective();
4469 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4470 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4471 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4472 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4474 if (!interpreterDeclarations.empty() &&
4475 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4486 if (!
gDriverConfig->fBuildingROOTStage1 && !filesIncludedByLinkdef.empty()) {
4487 pcmArgs.push_back(linkdef);
4495 interp.AddIncludePath(inclPath);
4497 std::stringstream definesUndefinesStr;
4500 if (!definesUndefinesStr.str().empty()) {
4501 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4502 ROOT::TMetaUtils::Error(
nullptr,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4514 std::ofstream fileout;
4516 std::ostream *splitDictStream =
nullptr;
4517 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4536 splitDeleter.reset(splitDictStream);
4538 splitDictStream = &dictStream;
4541 size_t dh = main_dictname.rfind(
'.');
4542 if (dh != std::string::npos) {
4543 main_dictname.erase(dh);
4546 std::string main_dictname_copy(main_dictname);
4568 string linkdefFilename;
4569 if (linkdef.empty()) {
4570 linkdefFilename =
"in memory";
4572 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4580 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4586 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4588 std::string extraIncludes;
4593 const unsigned int selRulesInitialSize = selectionRules.
Size();
4597 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4601 int rootclingRetCode(0);
4605 std::ifstream file(linkdefFilename.c_str());
4606 if (file.is_open()) {
4620 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4621 llvmResourceDir.c_str())) {
4623 rootclingRetCode += 1;
4633 }
else if (isSelXML) {
4637 std::ifstream file(linkdefFilename.c_str());
4638 if (file.is_open()) {
4642 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4665 ROOT::TMetaUtils::Error(
nullptr,
"No selection rules specified and creation of C++ module not requested: did you forget to specify a selection file or to request the creation of a C++ module?\n");
4684 dictStream <<
"#include \"TBuffer.h\"\n"
4685 <<
"#include \"TVirtualObject.h\"\n"
4686 <<
"#include <vector>\n"
4687 <<
"#include \"TSchemaHelper.h\"\n\n";
4689 std::list<std::string> includes;
4691 for (
auto & incFile : includes) {
4692 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4694 dictStream << std::endl;
4699 int scannerVerbLevel = 0;
4727 scan.
Scan(CI->getASTContext());
4729 bool has_input_error =
false;
4736 !dictSelRulesPresent &&
4743 if (rootclingRetCode)
return rootclingRetCode;
4750 if (annRcd.RequestNoInputOperator()) {
4762 if (has_input_error) {
4772 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4773 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4799 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4800 constructorTypes.emplace_back(
"__void__", interp);
4801 constructorTypes.emplace_back(
"", interp);
4826 if (rootclingRetCode != 0) {
4827 return rootclingRetCode;
4846 std::string detectedUmbrella;
4847 for (
auto & arg : pcmArgs) {
4849 detectedUmbrella = arg;
4855 headersDeclsMap.clear();
4859 std::string headersClassesMapString =
"\"\"";
4860 std::string fwdDeclsString =
"\"\"";
4876 if (modGen.
IsPCH()) {
4879 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
4887 ofstream outputfile(liblist_filename.c_str(), ios::out);
4890 executableFileName, liblist_filename.c_str());
4892 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4893 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4895 outputfile <<
"# Now the list of classes\n";
4900 outputfile << annRcd.GetNormalizedName() << endl;
4907 if (0 != rootclingRetCode)
return rootclingRetCode;
4913 [](
const std::string &
a,
const std::string &
b) -> std::string {
4914 if (a.empty()) return b;
4915 else return a +
" " + b;
4920 std::list<std::string> classesNames;
4921 std::list<std::string> classesNamesForRootmap;
4922 std::list<std::string> classesDefsList;
4926 classesNamesForRootmap,
4930 std::list<std::string> enumNames;
4935 std::list<std::string> varNames;
4940 if (0 != rootclingRetCode)
return rootclingRetCode;
4943 if (rootMapNeeded) {
4945 std::list<std::string> nsNames;
4954 rootmapLibName.c_str());
4957 std::unordered_set<std::string> headersToIgnore;
4960 headersToIgnore.insert(optHeaderFileName.c_str());
4962 std::list<std::string> typedefsRootmapLines;
4970 classesNamesForRootmap,
4972 typedefsRootmapLines,
4978 if (0 != rootclingRetCode)
return 1;
4988 cling::Interpreter::PushTransactionRAII RAII(&interp);
4989 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5000 if(rootclingRetCode == 0) {
5001 rootclingRetCode += tmpCatalog.
commit();
5006 return rootclingRetCode;
5017 unsigned int numberOfHeaders = 0;
5018 for (std::vector<std::string>::iterator it = headersNames.begin();
5019 it != headersNames.end(); ++it) {
5020 const std::string headername(*it);
5025 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5026 headername.c_str());
5029 return numberOfHeaders;
5035 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5038 unsigned int argvCounter = 0;
5039 for (
int i = 1; i < argc; ++i) {
5042 args.push_back(argv[i]);
5044 }
else if (argvCounter) {
5045 argv[i - argvCounter] = argv[i];
5052 std::cout <<
"Args: \n";
5053 for (std::vector<std::string>::iterator it = args.begin();
5054 it < args.end(); ++it) {
5055 std::cout << i <<
") " << *it << std::endl;
5068 size_t result = filename.find_last_of(
'.');
5069 if (std::string::npos != result) {
5070 filename.erase(result);
5071 filename.append(newExtension);
5081 const unsigned int size(str.size());
5082 char *
a =
new char[
size + 1];
5084 memcpy(
a, str.c_str(),
size);
5100 std::vector<std::string> &ofilesnames)
5102 ofilesnames.reserve(headersNames.size());
5104 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5105 it != headersNames.end(); ++it) {
5106 std::string ofilename(*it);
5108 ofilesnames.push_back(ofilename);
5115 const std::vector<std::string> &argsToBeAdded,
5116 const std::string &optName =
"")
5118 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5119 it != argsToBeAdded.end(); ++it) {
5127 const std::vector<std::string> &argsToBeAdded,
5128 const std::string &optName =
"")
5130 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5131 it != argsToBeAdded.end(); ++it) {
5132 if (optName.length()) {
5142 const std::string &selectionFileName,
5143 const std::string &targetLibName,
5145 const std::vector<std::string> &pcmsNames,
5146 const std::vector<std::string> &includes,
5147 const std::vector<std::string> &preprocDefines,
5148 const std::vector<std::string> &preprocUndefines,
5149 const std::vector<std::string> &warnings,
5150 const std::string &rootmapFileName,
5151 const std::string &rootmapLibName,
5152 bool interpreteronly,
5155 bool writeEmptyRootPCM,
5157 bool noIncludePaths,
5158 bool noGlobalUsingStd,
5159 const std::vector<std::string> &headersNames,
5160 bool failOnWarnings,
5161 bool printRootclingInvocation,
5162 const std::string &ofilename)
5166 std::vector<char *> argvVector;
5177 std::string dictLocation;
5183 std::string newRootmapLibName(rootmapLibName);
5184 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5185 if (headersNames.size() != 1) {
5187 "*** genreflex: No rootmap lib and several header specified!\n");
5190 newRootmapLibName =
"lib";
5191 newRootmapLibName += cleanHeaderName;
5197 std::string newRootmapFileName(rootmapFileName);
5198 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5199 newRootmapFileName = dictLocation + newRootmapFileName;
5204 if (!newRootmapFileName.empty()) {
5210 if (!newRootmapLibName.empty()) {
5220 if (interpreteronly)
5228 if (!targetLibName.empty()) {
5238 if (noGlobalUsingStd)
5248 if (writeEmptyRootPCM)
5271 if (!selectionFileName.empty()) {
5275 const int argc = argvVector.size();
5280 for (
int i = 0; i < argc; i++) {
5281 cmd += argvVector[i];
5286 std::cout << cmd << std::endl;
5287 if (printRootclingInvocation)
return 0;
5290 char **argv = & (argvVector[0]);
5295 for (
int i = 0; i < argc; i++)
5296 delete [] argvVector[i];
5298 return rootclingReturnCode;
5307 const std::string &selectionFileName,
5308 const std::string &targetLibName,
5310 const std::vector<std::string> &pcmsNames,
5311 const std::vector<std::string> &includes,
5312 const std::vector<std::string> &preprocDefines,
5313 const std::vector<std::string> &preprocUndefines,
5314 const std::vector<std::string> &warnings,
5315 const std::string &rootmapFileName,
5316 const std::string &rootmapLibName,
5317 bool interpreteronly,
5320 bool writeEmptyRootPCM,
5322 bool noIncludePaths,
5323 bool noGlobalUsingStd,
5324 const std::vector<std::string> &headersNames,
5325 bool failOnWarnings,
5326 bool printRootclingInvocation,
5327 const std::string &outputDirName_const =
"")
5329 std::string outputDirName(outputDirName_const);
5331 std::vector<std::string> ofilesNames;
5338 std::vector<std::string> namesSingleton(1);
5339 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5340 namesSingleton[0] = headersNames[i];
5341 std::string ofilenameFullPath(ofilesNames[i]);
5342 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5343 ofilenameFullPath = outputDirName + ofilenameFullPath;
5364 printRootclingInvocation,
5366 if (returnCode != 0)
5381 std::vector<std::string> &values)
5384 if (options[oIndex]) {
5385 const int nVals = options[oIndex].count();
5386 values.reserve(nVals);
5387 int optionIndex = 0;
5390 << optionIndex <<
"/" << nVals <<
" "
5391 << opt->arg << std::endl;
5393 values.push_back(opt->arg);
5404 const char *descriptor)
5406 if (options[optionIndex]) {
5408 "*** genereflex: %s is not supported anymore.\n",
5466 PRINTROOTCLINGINVOCATION,
5497 enum optionTypes { NOTYPE, STRING } ;
5500 const char *genreflexUsage =
5501 "********************************************************************************\n"
5502 "* The genreflex utility does not allow to generate C++ modules containing *\n"
5503 "* reflection information required at runtime. Please use rootcling instead *\n"
5504 "* To print the rootcling invocation that corresponds to the current genreflex *\n"
5505 "* invocation please use the --print-rootcling-invocation flag. *\n"
5506 "********************************************************************************\n"
5508 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5509 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5512 const char *printRootclingInvocationUsage =
5513 "--print-rootcling-invocation\n"
5514 " Print to screen the rootcling invocation corresponding to the current \n"
5515 " genreflex invocation.\n";
5517 const char *selectionFilenameUsage =
5518 "-s, --selection_file\tSelection filename\n"
5519 " Class selection file to specify for which classes the dictionary\n"
5520 " will be generated. The final set can be crafted with exclusion and\n"
5521 " exclusion rules.\n"
5522 " Properties can be specified. Some have special meaning:\n"
5523 " - name [string] name of the entity to select with an exact matching\n"
5524 " - pattern [string] name with wildcards (*) to select entities\n"
5525 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5526 " file where the C++ entities reside and not to C++ entities themselves.\n"
5527 " - transient/persistent [string: true/false] The fields to which they are\n"
5528 " applied will not be persistified if requested.\n"
5529 " - comment [string]: what you could write in code after an inline comment\n"
5530 " without \"//\". For example comment=\"!\" or \"||\".\n"
5531 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5532 " Default value is 'false'\n"
5533 " - rntupleStreamerMode [true/false]: enforce streamed or native writing for RNTuple.\n"
5534 " If unset, RNTuple stores classes in split mode or fails if the class cannot be split.\n"
5535 " - rntupleSoARecord [class name]: marks the class as an RNTuple SoA layout for the underlying record\n"
5536 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5537 " to 'true'. Default value is 'false'\n"
5541 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5542 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5543 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5544 " [noInputOperator=\"true/false\"]\n"
5545 " [rntupleStreamerMode=\"true/false\"] />\n"
5546 " [rntupleSoARecord=\"class_name\"] />\n"
5547 " <class name=\"classname\" >\n"
5548 " <field name=\"m_transient\" transient=\"true\"/>\n"
5549 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5550 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5551 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5553 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5554 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5555 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5558 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5559 " <method name=\"unwanted\" />\n"
5564 " If no selection file is specified, the class with the filename without\n"
5565 " extension will be selected, i.e. myClass.h as argument without any\n"
5566 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5568 const char *outputFilenameUsage =
5569 "-o, --output\tOutput filename\n"
5570 " Output file name. If an existing directory is specified instead of a file,\n"
5571 " then a filename will be built using the name of the input file and will\n"
5572 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5573 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5574 " have unique names.\n";
5577 const char *targetLib =
5578 "-l, --library\tTarget library\n"
5579 " The flag -l must be followed by the name of the library that will\n"
5580 " contain the object file corresponding to the dictionary produced by\n"
5581 " this invocation of genreflex.\n"
5582 " The name takes priority over the one specified for the rootmapfile.\n"
5583 " The name influences the name of the created pcm:\n"
5584 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5585 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5586 " Any \"liblib\" occurrence is transformed in the expected \"lib\".\n"
5587 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5588 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5590 const char *rootmapUsage =
5591 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5592 " This file lists the autoload keys. For example classes for which the\n"
5593 " reflection information is provided.\n"
5594 " The format of the rootmap is the following:\n"
5595 " - Forward declarations section\n"
5596 " - Libraries sections\n"
5597 " Rootmaps can be concatenated together, for example with the cat util.\n"
5598 " In order for ROOT to pick up the information in the rootmaps, they\n"
5599 " have to be located in the library path and have the .rootmap extension.\n"
5600 " An example rootmap file could be:\n"
5602 " template <class T> class A;\n"
5603 " [ libMyLib.so ]\n"
5604 " class A<double>\n"
5609 const char *rootmapLibUsage =
5610 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5624 PRINTROOTCLINGINVOCATION,
5626 "",
"print-rootcling-invocation",
5628 printRootclingInvocationUsage
5652 "--multiDict\tSupport for many dictionaries in one library\n"
5653 " Form correct pcm names if multiple dictionaries will be in the same\n"
5654 " library (needs target library switch. See its documentation).\n"
5661 "" ,
"noGlobalUsingStd" ,
5663 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5664 " All header files must have sumbols from std:: namespace fully qualified\n"
5670 "s" ,
"selection_file" ,
5672 selectionFilenameUsage
5686 "" ,
"rootmap-lib" ,
5694 "" ,
"interpreteronly",
5696 "--interpreteronly\tDo not generate I/O related information.\n"
5697 " Generate minimal dictionary required for interactivity.\n"
5705 "--split\tSplit the dictionary\n"
5706 " Split in two the dictionary, isolating the part with\n"
5707 " ClassDef related functions in a separate file.\n"
5715 "-m \tPcm file loaded before any header (option can be repeated).\n"
5723 "-v, --verbose\tPrint some debug information.\n"
5731 "--debug\tPrint all debug information.\n"
5739 "--quiet\tPrint only warnings and errors (default).\n"
5747 "--silent\tPrint no information at all.\n"
5753 "" ,
"writeEmptyPCM",
5755 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5763 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5772 "--help\tPrint usage and exit.\n"
5778 "",
"fail_on_warnings",
5780 "--fail_on_warnings\tFail on warnings and errors.\n"
5786 "",
"selSyntaxOnly",
5788 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5794 "" ,
"noIncludePaths",
5796 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5835 "" ,
"no_membertypedefs" ,
5843 "" ,
"no_templatetypedefs" ,
5848 {0, 0,
nullptr,
nullptr,
nullptr,
nullptr}
5851 std::vector<std::string> headersNames;
5852 const int originalArgc = argc;
5854 const int extractedArgs =
extractArgs(argc, argv, headersNames);
5856 const int offset = 1;
5857 argc -= offset + extractedArgs;
5862 std::vector<ROOT::option::Option> options(stats.
options_max);
5863 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5869 if (parse.
error()) {
5875 if (options[HELP] || originalArgc == 1) {
5881 if (0 == numberOfHeaders) {
5892 std::string verbosityOption(
"-v2");
5893 if (options[SILENT]) verbosityOption =
"-v0";
5894 if (options[VERBOSE] || std::getenv (
"VERBOSE")) verbosityOption =
"-v3";
5895 if (options[
DEBUG]) verbosityOption =
"-v4";
5900 std::string selectionFileName;
5901 if (options[SELECTIONFILENAME]) {
5902 selectionFileName = options[SELECTIONFILENAME].arg;
5905 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
5906 selectionFileName.c_str());
5921 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
5922 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
5925 std::string targetLibName;
5926 if (options[TARGETLIB]) {
5927 targetLibName = options[TARGETLIB].arg;
5930 "Invalid target library extension: filename is %s and extension %s is expected!\n",
5931 targetLibName.c_str(),
5935 if (options[ROOTMAP]) {
5940 bool isCxxmodule = options[CXXMODULE];
5942 bool multidict =
false;
5943 if (options[MULTIDICT]) multidict =
true;
5945 bool noGlobalUsingStd =
false;
5946 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
5948 if (multidict && targetLibName.empty()) {
5950 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
5954 bool printRootclingInvocation =
false;
5955 if (options[PRINTROOTCLINGINVOCATION])
5956 printRootclingInvocation =
true;
5958 bool interpreteronly =
false;
5959 if (options[INTERPRETERONLY])
5960 interpreteronly =
true;
5962 bool doSplit =
false;
5966 bool writeEmptyRootPCM =
false;
5967 if (options[WRITEEMPTYROOTPCM])
5968 writeEmptyRootPCM =
true;
5970 bool selSyntaxOnly =
false;
5971 if (options[SELSYNTAXONLY]) {
5972 selSyntaxOnly =
true;
5975 bool noIncludePaths =
false;
5976 if (options[NOINCLUDEPATHS]) {
5977 noIncludePaths =
true;
5980 bool failOnWarnings =
false;
5981 if (options[FAILONWARNINGS]) {
5982 failOnWarnings =
true;
5991 std::vector<std::string> pcmsNames;
5995 std::vector<std::string> preprocDefines;
5999 std::vector<std::string> preprocUndefines;
6003 std::vector<std::string> includes;
6007 std::vector<std::string> warnings;
6018 int returnValue = 0;
6019 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6023 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6044 printRootclingInvocation,
6068 printRootclingInvocation,
6082 assert(!
gDriverConfig &&
"Driver configuration already set!");
6102 if (std::string::npos != exeName.find(
"genreflex"))
6110 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
Basic types used by ROOT and required by TInterpreter.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
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.
void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
~CheckModuleBuildClient() override
CheckModuleBuildClient(clang::DiagnosticConsumer *Child, bool OwnsChild, clang::ModuleMap &Map)
clang::DiagnosticConsumer * fChild
bool IncludeInDiagnosticCounts() const override
void EndSourceFile() override
void BeginSourceFile(const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) override
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.
const std::string & GetDictionaryName() const
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.
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)
~TRootClingCallbacks() override
void InclusionDirective(clang::SourceLocation, const clang::Token &, llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange, clang::OptionalFileEntryRef, llvm::StringRef, llvm::StringRef, const clang::Module *, bool, clang::SrcMgr::CharacteristicKind) override
std::list< std::string > & fFilesIncludedByLinkdef
void EnteredSubmodule(clang::Module *M, clang::SourceLocation ImportLoc, bool ForPragma) override
TRootClingCallbacks(cling::Interpreter *interp, std::list< std::string > &filesIncludedByLinkdef)
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.
R__EXTERN SchemaRuleClassMap_t gReadRules
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
R__EXTERN SchemaRuleClassMap_t gReadRawRules
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
void Init(TClassEdit::TInterpreterLookupHelper *helper)
void header2outputName(std::string &fileName)
Replace the extension with "_rflx.cpp".
void AddToArgVectorSplit(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
void changeExtension(std::string &filename, const std::string &newExtension)
int invokeManyRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, bool printRootclingInvocation, const std::string &outputDirName_const="")
Get the right ofilenames and invoke several times rootcling One invokation per header.
int invokeRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, bool printRootclingInvocation, const std::string &ofilename)
unsigned int checkHeadersNames(std::vector< std::string > &headersNames)
Loop on arguments: stop at the first which starts with -.
void headers2outputsNames(const std::vector< std::string > &headersNames, std::vector< std::string > &ofilesnames)
Get a proper name for the output file.
char * string2charptr(const std::string &str)
The caller is responsible for deleting the string!
unsigned int extractArgs(int argc, char **argv, std::vector< std::string > &args)
Extract the arguments from the command line.
void AddToArgVector(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
int FinalizeStreamerInfoWriting(cling::Interpreter &interp, bool writeEmptyRootPCM=false)
Make up for skipping RegisterModule, now that dictionary parsing is done and these headers cannot be ...
int GenerateFullDict(std::ostream &dictStream, std::string dictName, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool isSelXML, bool writeEmptyRootPCM)
std::list< std::string > CollapseIdenticalNamespaces(const std::list< std::string > &fwdDeclarationsList)
If two identical namespaces are there, just declare one only Example: namespace A { namespace B { fwd...
static llvm::cl::opt< bool > gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
int RootClingMain(int argc, char **argv, bool isGenreflex=false)
static llvm::StringRef GetModuleNameFromRdictName(llvm::StringRef rdictName)
static llvm::cl::opt< bool > gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), llvm::cl::cat(gRootclingOptions), llvm::cl::init("-"))
int STLContainerStreamer(const clang::FieldDecl &m, int rwmode, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
Create Streamer code for an STL container.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static llvm::cl::opt< bool > gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
static llvm::cl::list< std::string > gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), llvm::cl::cat(gRootclingOptions))
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
static void MaybeSuppressWin32CrashDialogs()
void RecordDeclCallback(const clang::RecordDecl *recordDecl)
void CheckClassNameForRootMap(const std::string &classname, map< string, string > &autoloads)
bool Which(cling::Interpreter &interp, const char *fname, string &pname)
Find file name in path specified via -I statements to Cling.
void AdjustRootMapNames(std::string &rootmapFileName, std::string &rootmapLibName)
void AddNamespaceSTDdeclaration(std::ostream &dictStream)
static llvm::cl::list< std::string > gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptModuleByproducts("mByproduct", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("The list of the expected implicit modules build as part of building the current module."), llvm::cl::cat(gRootclingOptions))
map< string, string > gAutoloads
static llvm::cl::opt< bool > gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), llvm::cl::cat(gRootclingOptions))
static bool CheckModuleValid(TModuleGenerator &modGen, const std::string &resourceDir, cling::Interpreter &interpreter, llvm::StringRef LinkdefPath, const std::string &moduleName)
Check moduleName validity from modulemap. Check if this module is defined or not.
static void CheckForMinusW(std::string arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance, llvm::StringRef iSysRoot, clang::Module *module=nullptr)
Write the AST of the given CompilerInstance to the given File while respecting the given isysroot.
static llvm::cl::opt< bool > gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), llvm::cl::cat(gRootclingOptions))
void ExtractFilePath(const std::string &path, std::string &dirname)
Extract the path from a fullpath finding the last \ or / according to the content in gPathSeparator.
int STLStringStreamer(const clang::FieldDecl &m, int rwmode, std::ostream &dictStream)
Create Streamer code for a standard string object.
void CreateDictHeader(std::ostream &dictStream, const std::string &main_dictname)
const char * GetExePath()
Returns the executable path name, used e.g. by SetRootSys().
const std::string gPathSeparator(ROOT::TMetaUtils::GetPathSeparator())
static llvm::cl::list< std::string > gOptBareClingSink(llvm::cl::OneOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes options and sends them to cling."), llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gBareClingSubcommand))
bool InheritsFromTObject(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static bool InjectModuleUtilHeader(const char *argv0, TModuleGenerator &modGen, cling::Interpreter &interp, bool umbrella)
Write the extra header injected into the module: umbrella header if (umbrella) else content header.
static llvm::cl::list< std::string > gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), llvm::cl::cat(gRootclingOptions))
int ExtractClassesListAndDeclLines(RScanner &scan, std::list< std::string > &classesList, std::list< std::string > &classesListForRootmap, std::list< std::string > &fwdDeclarationsList, const cling::Interpreter &interpreter)
void ParseRootMapFileNewFormat(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map, using the new format.
static llvm::cl::OptionCategory gRootclingOptions("rootcling common options")
static llvm::cl::list< std::string > gOptSysIncludePaths("isystem", llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a system include path."), llvm::cl::cat(gRootclingOptions))
void ExtractHeadersForDecls(const RScanner::ClassColl_t &annotatedRcds, const RScanner::TypedefColl_t tDefDecls, const RScanner::FunctionColl_t funcDecls, const RScanner::VariableColl_t varDecls, const RScanner::EnumColl_t enumDecls, HeadersDeclsMap_t &headersClassesMap, HeadersDeclsMap_t &headersDeclsMap, const cling::Interpreter &interp)
bool ParsePragmaLine(const std::string &line, const char *expectedTokens[], size_t *end=nullptr)
Check whether the #pragma line contains expectedTokens (0-terminated array).
static llvm::cl::opt< bool > gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static bool ModuleContainsHeaders(TModuleGenerator &modGen, clang::HeaderSearch &headerSearch, clang::Module *module, std::vector< std::array< std::string, 2 > > &missingHeaders)
Returns true iff a given module (and its submodules) contains all headers needed by the given ModuleG...
static bool GenerateAllDict(TModuleGenerator &modGen, clang::CompilerInstance *compilerInstance, const std::string ¤tDirectory)
Generates a PCH from the given ModuleGenerator and CompilerInstance.
void LoadLibraryMap(const std::string &fileListName, map< string, string > &autoloads)
Fill the map of libraries to be loaded in presence of a class Transparently support the old and new r...
std::ostream * CreateStreamPtrForSplitDict(const std::string &dictpathname, tempFileNamesCatalog &tmpCatalog)
Transform name of dictionary.
void WriteNamespaceInit(const clang::NamespaceDecl *cl, cling::Interpreter &interp, std::ostream &dictStream)
Write the code to initialize the namespace name and the initialization object.
static llvm::cl::list< std::string > gOptCompDefaultIncludePaths("compilerI", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a compiler default include path, to suppress unneeded `-isystem` arguments."), llvm::cl::cat(gRootclingOptions))
void AnnotateAllDeclsForPCH(cling::Interpreter &interp, RScanner &scan)
We need annotations even in the PCH: // !, // || etc.
size_t GetFullArrayLength(const clang::ConstantArrayType *arrayType)
static llvm::cl::opt< bool > gOptSplit("split", llvm::cl::desc("Split the dictionary into two parts: one containing the IO (ClassDef)\
information and another the interactivity support."), llvm::cl::cat(gRootclingOptions))
bool ProcessAndAppendIfNotThere(const std::string &el, std::list< std::string > &el_list, std::unordered_set< std::string > &el_set)
Separate multiline strings.
static llvm::cl::opt< bool > gOptNoGlobalUsingStd("noGlobalUsingStd", llvm::cl::desc("Do not declare {using namespace std} in dictionary global scope."), llvm::cl::cat(gRootclingOptions))
const ROOT::Internal::RootCling::DriverConfig * gDriverConfig
static llvm::cl::list< std::string > gOptModuleDependencies("m", llvm::cl::desc("The list of dependent modules of the dictionary."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::SubCommand gBareClingSubcommand("bare-cling", "Call directly cling and exit.")
static llvm::cl::opt< bool > gOptInterpreterOnly("interpreteronly", llvm::cl::desc("Generate minimal dictionary for interactivity (without IO information)."), llvm::cl::cat(gRootclingOptions))
void WriteArrayDimensions(const clang::QualType &type, std::ostream &dictStream)
Write "[0]" for all but the 1st dimension.
static llvm::cl::opt< bool > gOptReflex("reflex", llvm::cl::desc("Behave internally like genreflex."), llvm::cl::cat(gRootclingOptions))
void GetMostExternalEnclosingClassName(const clang::DeclContext &theContext, std::string &ctxtName, const cling::Interpreter &interpreter, bool treatParent=true)
Extract the proper autoload key for nested classes The routine does not erase the name,...
std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, cling::Interpreter &interp)
int ExtractAutoloadKeys(std::list< std::string > &names, const COLL &decls, const cling::Interpreter &interp)
static llvm::cl::opt< std::string > gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), llvm::cl::cat(gRootclingOptions))
void WriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
#define rootclingStringify(s)
void GetMostExternalEnclosingClassNameFromDecl(const clang::Decl &theDecl, std::string &ctxtName, const cling::Interpreter &interpreter)
static llvm::cl::opt< bool > gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
bool CheckInputOperator(const char *what, const char *proto, const string &fullname, const clang::RecordDecl *cl, cling::Interpreter &interp)
Check if the specified operator (what) has been properly declared if the user has requested a custom ...
void GenerateNecessaryIncludes(std::ostream &dictStream, const std::string &includeForSource, const std::string &extraIncludes)
void StrcpyArg(string &dest, const char *original)
Copy the command line argument, stripping MODULE/inc if necessary.
static llvm::cl::list< std::string > gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), llvm::cl::cat(gRootclingOptions))
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
static llvm::cl::opt< bool > gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), llvm::cl::cat(gRootclingOptions))
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
static std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
static llvm::cl::opt< bool > gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), llvm::cl::cat(gRootclingOptions))
const char * CopyArg(const char *original)
If the argument starts with MODULE/inc, strip it to make it the name we can use in #includes.
string GetNonConstMemberName(const clang::FieldDecl &m, const string &prefix="")
Return the name of the data member so that it can be used by non-const operation (so it includes a co...
static llvm::cl::list< std::string > gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), llvm::cl::cat(gRootclingOptions))
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
void ExtractSelectedNamespaces(RScanner &scan, std::list< std::string > &nsList)
Loop on selected classes and put them in a list.
static bool IncludeHeaders(const std::vector< std::string > &headers, cling::Interpreter &interpreter)
Includes all given headers in the interpreter.
clang::QualType GetPointeeTypeIfPossible(const clang::QualType &qt)
Get the pointee type if possible.
void AnnotateDecl(clang::CXXRecordDecl &CXXRD, const RScanner::DeclsSelRulesMap_t &declSelRulesMap, cling::Interpreter &interpreter, bool isGenreflex)
static llvm::cl::opt< VerboseLevel > gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), llvm::cl::values(clEnumVal(v, "Show errors."), clEnumVal(v0, "Show only fatal errors."), clEnumVal(v1, "Show errors (the same as -v)."), clEnumVal(v2, "Show warnings (default)."), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include <header> but expands the header content."), llvm::cl::cat(gRootclingOptions))
bool isPointerToPointer(const clang::FieldDecl &m)
int CreateNewRootMapFile(const std::string &rootmapFileName, const std::string &rootmapLibName, const std::list< std::string > &classesDefsList, const std::list< std::string > &classesNames, const std::list< std::string > &nsNames, const std::list< std::string > &tdNames, const std::list< std::string > &enNames, const std::list< std::string > &varNames, const HeadersDeclsMap_t &headersClassesMap, const std::unordered_set< std::string > headersToIgnore)
Generate a rootmap file in the new format, like { decls } namespace A { namespace B { template <typen...
static llvm::cl::opt< std::string > gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::desc("<output dictionary file>"), llvm::cl::cat(gRootclingOptions))
bool IsSelectionXml(const char *filename)
bool IsGoodLibraryName(const std::string &name)
llvm::StringRef GrabIndex(const cling::Interpreter &interp, const clang::FieldDecl &member, int printError)
GrabIndex returns a static string (so use it or copy it immediately, do not call GrabIndex twice in t...
static llvm::cl::opt< bool > gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), llvm::cl::cat(gRootclingOptions))
bool IsSelectionFile(const char *filename)
const std::string GenerateStringFromHeadersForClasses(const HeadersDeclsMap_t &headersClassesMap, const std::string &detectedUmbrella, bool payLoadOnly=false)
Generate a string for the dictionary from the headers-classes map.
bool IsSupportedClassName(const char *name)
static llvm::cl::opt< bool > gOptForce("f", llvm::cl::desc("Overwrite <file>s."), llvm::cl::cat(gRootclingOptions))
static void AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules)
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
static llvm::cl::list< std::string > gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), llvm::cl::cat(gRootclingOptions))
int CheckClassesForInterpreterOnlyDicts(cling::Interpreter &interp, RScanner &scan)
bool InheritsFromTSelector(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static void EmitTypedefs(const std::vector< const clang::TypedefNameDecl * > &tdvec)
bool Namespace__HasMethod(const clang::NamespaceDecl *cl, const char *name, const cling::Interpreter &interp)
static llvm::cl::list< std::string > gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), llvm::cl::cat(gRootclingOptions))
bool IsCorrectClingArgument(const std::string &argument)
Check if the argument is a sane cling argument.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)
void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream &dictStream, bool autoLoad=false)
Write the code to set the class name and the initialization object.
static llvm::cl::list< std::string > gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the <path> in the dictionary."), llvm::cl::cat(gRootclingOptions))
std::list< std::string > RecordDecl2Headers(const clang::CXXRecordDecl &rcd, const cling::Interpreter &interp, std::set< const clang::CXXRecordDecl * > &visitedDecls)
Extract the list of headers necessary for the Decl.
void EmitStreamerInfo(const char *normName)
static llvm::cl::opt< bool > gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), llvm::cl::cat(gRootclingOptions))
bool HasPath(const std::string &name)
Check if file has a path.
static llvm::cl::opt< std::string > gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::ZeroOrMore, llvm::cl::desc("<list of dictionary header files> <LinkDef file | selection xml file>"), llvm::cl::cat(gRootclingOptions))
int CheckForUnsupportedClasses(const RScanner::ClassColl_t &annotatedRcds)
Check if the list of selected classes contains any class which is not supported.
static void EmitEnums(const std::vector< const clang::EnumDecl * > &enumvec)
static llvm::cl::opt< bool > gOptSystemModuleByproducts("mSystemByproducts", llvm::cl::Hidden, llvm::cl::desc("Allow implicit build of system modules."), llvm::cl::cat(gRootclingOptions))
bool CheckClassDef(const clang::RecordDecl &cl, const cling::Interpreter &interp)
Return false if the class does not have ClassDef even-though it should.
bool NeedsSelection(const char *name)
int extractMultipleOptions(std::vector< ROOT::option::Option > &options, int oIndex, std::vector< std::string > &values)
Extract from options multiple values with the same option.
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.