12 #include "rootclingCommandLineOptionsHelp.h"
14 #include "RConfigure.h"
33 #include <unordered_map>
34 #include <unordered_set>
46 #define PATH_MAX _MAX_PATH
54 #include <mach-o/dyld.h>
57 #if !defined(R__WIN32)
63 #include "cling/Interpreter/Interpreter.h"
64 #include "cling/Interpreter/InterpreterCallbacks.h"
65 #include "cling/Interpreter/LookupHelper.h"
66 #include "cling/Interpreter/Value.h"
67 #include "clang/AST/CXXInheritance.h"
68 #include "clang/Basic/Diagnostic.h"
69 #include "clang/Basic/MemoryBufferCache.h"
70 #include "clang/Frontend/CompilerInstance.h"
71 #include "clang/Frontend/FrontendActions.h"
72 #include "clang/Frontend/FrontendDiagnostic.h"
73 #include "clang/Lex/HeaderSearch.h"
74 #include "clang/Lex/Preprocessor.h"
75 #include "clang/Lex/ModuleMap.h"
76 #include "clang/Lex/Pragma.h"
77 #include "clang/Sema/Sema.h"
78 #include "clang/Serialization/ASTWriter.h"
79 #include "cling/Utils/AST.h"
81 #include "llvm/Bitcode/BitstreamWriter.h"
82 #include "llvm/Support/CommandLine.h"
83 #include "llvm/Support/Path.h"
84 #include "llvm/Support/PrettyStackTrace.h"
85 #include "llvm/Support/Signals.h"
109 #include <mach-o/dyld.h>
112 #if defined(R__WIN32)
114 #define strcasecmp _stricmp
115 #define strncasecmp _strnicmp
127 using namespace ROOT;
141 static llvm::cl::opt<bool>
143 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
144 When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
164 static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
168 for (
const auto td : tdvec)
171 static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
175 for (
const auto en : enumvec) {
177 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
178 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
179 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
189 static std::string exepath;
192 exepath = _dyld_get_image_name(0);
194 #if defined(__linux) || defined(__linux__)
195 char linkname[PATH_MAX];
201 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
202 int ret = readlink(linkname, buf, 1024);
203 if (ret > 0 && ret < 1024) {
209 char *buf =
new char[MAX_MODULE_NAME32 + 1];
212 while ((p = strchr(p,
'\\')))
218 return exepath.c_str();
224 const cling::Interpreter &interp)
232 const std::list<VariableSelectionRule> &fieldSelRules)
240 if (fieldSelRules.empty())
return;
242 clang::ASTContext &
C = decl.getASTContext();
243 clang::SourceRange commentRange;
245 const std::string declName(decl.getNameAsString());
247 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
248 it != fieldSelRules.end(); ++it) {
250 if (declName == varName) {
253 BaseSelectionRule::AttributesMap_t::iterator iter;
254 std::string userDefinedProperty;
255 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
256 const std::string &
name = iter->first;
257 const std::string &value = iter->second;
265 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
266 const char *msg =
"Data member \"%s\" is an array or a pointer. "
267 "It is not possible to assign to it the iotype \"%s\". "
268 "This transformation is possible only with data members "
269 "which are not pointers or arrays.\n";
271 msg, varName.c_str(), value.c_str());
280 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, value, 0));
290 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C,
"!", 0));
298 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
309 cling::Interpreter &interpreter,
317 using namespace clang;
318 SourceLocation commentSLoc;
321 ASTContext &
C = CXXRD.getASTContext();
322 Sema &
S = interpreter.getCI()->getSema();
324 SourceRange commentRange;
327 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
328 auto declSelRulePair = declSelRulesMap.
find(declBaseClassPtr->getCanonicalDecl());
329 if (declSelRulePair == declSelRulesMap.end()){
330 const std::string thisClassName(CXXRD.getName());
331 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
336 if (thisClassBaseSelectionRule) {
339 BaseSelectionRule::AttributesMap_t::iterator iter;
340 std::string userDefinedProperty;
341 for (
auto const & attr : thisClassBaseSelectionRule->
GetAttributes()) {
342 const std::string &
name = attr.first;
344 const std::string &value = attr.second;
347 CXXRD.addAttr(
new(
C) AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
354 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
355 E = CXXRD.decls_end();
I !=
E; ++
I) {
359 if (!(*I)->isImplicit()
360 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
364 SourceLocation maybeMacroLoc = (*I)->getLocation();
365 bool isClassDefMacro = maybeMacroLoc.isMacroID() &&
S.findMacroSpelling(maybeMacroLoc,
"ClassDef");
366 if (isClassDefMacro) {
367 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
376 commentRange = SourceRange(commentSLoc, commentSLoc.getLocWithOffset(
comment.size()));
378 if (isClassDefMacro) {
379 CXXRD.addAttr(
new(
C) AnnotateAttr(commentRange,
C,
comment.str(), 0));
380 }
else if (!isGenreflex) {
386 (*I)->addAttr(
new(
C) AnnotateAttr(commentRange,
C,
comment.str(), 0));
391 if (isGenreflex && thisClassSelectionRule != 0) {
395 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
407 llvm::APInt len = arrayType->getSize();
408 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
409 len *= subArrayType->getSize();
410 arrayType = subArrayType;
412 return len.getLimitedValue();
418 const cling::Interpreter &interp)
420 static const clang::CXXRecordDecl *TObject_decl
423 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
430 const cling::Interpreter &interp)
432 static const clang::CXXRecordDecl *TObject_decl
442 size_t len = strlen(filename);
444 if (strlen(filename) >= xmllen) {
445 return (0 == strcasecmp(filename + (len - xmllen),
".xml"));
471 if (exepath && *exepath) {
473 char *ep =
new char[PATH_MAX];
474 if (!realpath(exepath, ep)) {
475 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
476 strlcpy(ep, exepath, PATH_MAX);
479 int nche = strlen(exepath) + 1;
480 char *ep =
new char[nche];
481 strlcpy(ep, exepath, nche);
485 if ((
s = strrchr(ep,
'/'))) {
487 int removesubdirs = 2;
488 if (!strncmp(
s + 1,
"rootcling_stage1.exe", 20)) {
492 }
else if (!strncmp(
s + 1,
"rootcling_stage1", 16)) {
497 for (
int i = 1;
s && i < removesubdirs; ++i) {
499 s = strrchr(ep,
'/');
513 int ncha = strlen(ep) + 10;
514 char *env =
new char[ncha];
515 snprintf(env, ncha,
"ROOTSYS=%s", ep);
536 const char *expectedTokens[],
540 if (
line[0] !=
'#')
return false;
542 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
543 while (isspace(
line[pos])) ++pos;
544 size_t lenToken = strlen(*iToken);
545 if (
line.compare(pos, lenToken, *iToken)) {
564 if (recordDecl->hasOwningModule()) {
565 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
568 std::string qual_name;
574 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
583 if (classname.find(
':') == std::string::npos)
return;
586 int slen = classname.size();
587 for (
int k = 0; k < slen; ++k) {
588 if (classname[k] ==
':') {
589 if (k + 1 >= slen || classname[k + 1] !=
':') {
594 string base = classname.substr(0, k);
599 autoloads[base] =
"";
603 }
else if (classname[k] ==
'<') {
615 std::string classname;
619 if (
line.find(
"Library.") != 0)
continue;
621 int pos =
line.find(
":", 8);
622 classname =
line.substr(8, pos - 8);
628 while (
line[0] ==
' ')
line.replace(0, 1,
"");
632 if (classname ==
"ROOT::TImpProxy") {
636 autoloads[classname] =
line;
651 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
654 if (
line ==
"{ decls }") {
656 if (
line[0] ==
'[')
break;
659 const char firstChar =
line[0];
660 if (firstChar ==
'[') {
662 libs =
line.substr(1,
line.find(
']') - 1);
663 while (libs[0] ==
' ') libs.replace(0, 1,
"");
664 }
else if (0 != keyLenMap.count(firstChar)) {
665 unsigned int keyLen = keyLenMap.at(firstChar);
666 keyname =
line.substr(keyLen,
line.length() - keyLen);
668 autoloads[keyname] = libs;
678 void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
680 std::ifstream filelist(fileListName.c_str());
682 std::string filename;
685 while (filelist >> filename) {
687 if (llvm::sys::fs::is_directory(filename))
continue;
689 ifstream
file(filename.c_str());
693 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
695 file.seekg(0, std::ios::beg);
716 const string &fullname,
717 const clang::RecordDecl *cl,
718 cling::Interpreter &interp)
721 const clang::FunctionDecl *method
726 clang::TranslationUnitDecl *TU =
727 cl->getASTContext().getTranslationUnitDecl();
731 bool has_input_error =
false;
732 if (method != 0 && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
734 if (strstr(filename.c_str(),
"TBuffer.h") != 0 ||
735 strstr(filename.c_str(),
"Rtypes.h") != 0) {
737 has_input_error =
true;
740 has_input_error =
true;
742 if (has_input_error) {
744 const char *maybeconst =
"";
745 const char *mayberef =
"&";
746 if (
what[strlen(
what) - 1] ==
'<') {
747 maybeconst =
"const ";
751 "in this version of ROOT, the option '!' used in a linkdef file\n"
752 " implies the actual existence of customized operators.\n"
753 " The following declaration is now required:\n"
754 " TBuffer &%s(TBuffer &,%s%s *%s);\n",
what, maybeconst, fullname.c_str(), mayberef);
756 return has_input_error;
768 int ncha = fullname.length() + 13;
769 char *
proto =
new char[ncha];
781 return has_input_error;
787 bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
793 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
797 bool isAbstract = clxx->isAbstract();
800 std::string qualName;
802 const char *qualName_c = qualName.c_str();
804 "because it inherits from TObject but does not "
805 "have its own ClassDef.\n",
818 if (
m.getType().isConstQualified()) {
819 string ret =
"const_cast< ";
822 if (type_name.substr(0,6)==
"const ") {
823 ret += type_name.c_str()+6;
829 ret +=
m.getName().str();
833 return prefix +
m.getName().str();
843 const cling::Interpreter &interp,
845 std::ostream &dictStream)
848 std::string mTypename;
861 if (clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
863 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
864 if (!tmplt_specialization)
return 0;
871 string fulName1, fulName2;
872 const char *tcl1 = 0, *tcl2 = 0;
873 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
874 clang::QualType ti = arg0.getAsType();
878 fulName1 = ti.getAsString();
881 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
882 clang::QualType tmplti = arg1.getAsType();
885 fulName2 = tmplti.getAsString();
892 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
898 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
902 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
904 }
else if (
m.getType()->isPointerType()) {
909 dictStream <<
" {" << std::endl;
911 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
916 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
919 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
922 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
923 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
924 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
927 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
928 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
929 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
933 dictStream <<
" R__stl.clear();" << std::endl;
936 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
937 <<
" if (R__tcl1==0) {" << std::endl
938 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
939 << fulName1.c_str() <<
"!\");" << std::endl
940 <<
" return;" << std::endl
941 <<
" }" << std::endl;
944 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
945 <<
" if (R__tcl2==0) {" << std::endl
946 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
947 << fulName2.c_str() <<
"!\");" << std::endl
948 <<
" return;" << std::endl
949 <<
" }" << std::endl;
952 dictStream <<
" int R__i, R__n;" << std::endl
953 <<
" R__b >> R__n;" << std::endl;
956 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
958 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
962 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
982 std::string keyName(ti.getAsString());
983 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
984 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
985 <<
" R__stl.insert(R__t3);" << std::endl;
993 dictStream <<
" R__stl.insert(R__t);" << std::endl;
998 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1001 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1006 dictStream <<
" }" << std::endl
1007 <<
" }" << std::endl;
1008 if (isArr) dictStream <<
" }" << std::endl;
1014 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
1016 dictStream <<
" {" << std::endl;
1019 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1022 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1025 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1028 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1032 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1033 <<
" R__b << R__n;" << std::endl
1034 <<
" if(R__n) {" << std::endl;
1037 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1038 <<
" if (R__tcl1==0) {" << std::endl
1039 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1040 << fulName1.c_str() <<
"!\");" << std::endl
1041 <<
" return;" << std::endl
1042 <<
" }" << std::endl;
1045 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1046 <<
" if (R__tcl2==0) {" << std::endl
1047 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1048 <<
" return;" << std::endl
1049 <<
" }" << std::endl;
1052 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1053 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1055 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1056 clang::QualType tmplti = arg1.getAsType();
1063 dictStream <<
" }" << std::endl
1064 <<
" }" << std::endl
1065 <<
" }" << std::endl;
1066 if (isArr) dictStream <<
" }" << std::endl;
1078 std::string mTypenameStr;
1082 if (!strcmp(mTypeName,
"string")) {
1084 std::string fieldname =
m.getName().str();
1087 if (
m.getType()->isConstantArrayType()) {
1088 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1089 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1091 std::stringstream fullIdx;
1092 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1095 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1096 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1097 fullIdx <<
"[R__i" << dim <<
"]";
1098 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1101 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1102 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1105 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1106 if (
m.getType()->isPointerType())
1107 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1108 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1110 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1114 if (
m.getType()->isPointerType())
1115 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1116 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1117 else if (
m.getType()->isConstantArrayType()) {
1118 std::stringstream fullIdx;
1119 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1122 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1123 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1124 fullIdx <<
"[R__i" << dim <<
"]";
1125 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1128 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1130 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1141 if (
m.getType()->isPointerType()) {
1142 if (
m.getType()->getPointeeType()->isPointerType()) {
1154 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1156 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1158 dictStream <<
"[0]";
1159 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1174 int enclSpaceNesting = 0;
1181 dictStream <<
"#include \"TInterpreter.h\"\n";
1183 dictStream <<
"//_______________________________________"
1184 <<
"_______________________________________" << std::endl;
1185 if (add_template_keyword) dictStream <<
"template <> ";
1186 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(0); // static to hold class pointer" << std::endl
1189 <<
"//_______________________________________"
1190 <<
"_______________________________________" << std::endl;
1191 if (add_template_keyword) dictStream <<
"template <> ";
1192 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1193 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1195 dictStream <<
"//_______________________________________"
1196 <<
"_______________________________________" << std::endl;
1197 if (add_template_keyword) dictStream <<
"template <> ";
1198 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1199 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1200 <<
"*)0x0)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1202 <<
"//_______________________________________"
1203 <<
"_______________________________________" << std::endl;
1204 if (add_template_keyword) dictStream <<
"template <> ";
1205 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1206 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1207 <<
"*)0x0)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1209 <<
"//_______________________________________"
1210 <<
"_______________________________________" << std::endl;
1211 if (add_template_keyword) dictStream <<
"template <> ";
1212 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1216 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1217 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1218 <<
"*)0x0)->GetClass();" << std::endl
1219 <<
" return fgIsA;\n"
1220 <<
"}" << std::endl << std::endl
1222 <<
"//_______________________________________"
1223 <<
"_______________________________________" << std::endl;
1224 if (add_template_keyword) dictStream <<
"template <> ";
1225 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1227 dictStream <<
" Dictionary();\n";
1229 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1230 dictStream << fullname <<
"*)0x0)->GetClass(); }" << std::endl;
1232 dictStream <<
" return fgIsA;" << std::endl
1233 <<
"}" << std::endl << std::endl;
1235 while (enclSpaceNesting) {
1236 dictStream <<
"} // namespace " << nsname << std::endl;
1245 cling::Interpreter &interp,
1246 std::ostream &dictStream)
1248 if (cl->isAnonymousNamespace()) {
1260 if (classname !=
"ROOT") {
1264 dictStream <<
" namespace ROOT {" << std::endl;
1266 #if !defined(R__AIX)
1267 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1271 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1272 dictStream << std::endl
1274 <<
" // Function generating the singleton type initializer" << std::endl
1276 #if !defined(R__AIX)
1277 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1278 <<
" {" << std::endl
1280 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1281 <<
" {" << std::endl
1284 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1286 <<
" instance(\"" << classname.c_str() <<
"\", ";
1289 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1291 dictStream <<
"0 /*version*/, ";
1295 for (
unsigned int i = 0; i < filename.length(); i++) {
1296 if (filename[i] ==
'\\') filename[i] =
'/';
1299 <<
" ::ROOT::Internal::DefineBehavior((void*)0,(void*)0)," << std::endl
1303 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1305 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1308 dictStream << 0 <<
");" << std::endl
1310 <<
" return &instance;" << std::endl
1311 <<
" }" << std::endl
1312 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1313 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1314 <<
" // Static variable to force the class initialization" << std::endl
1316 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1317 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1320 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1321 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1322 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1323 <<
" }" << std::endl << std::endl;
1326 dictStream <<
" }" << std::endl;
1328 dictStream <<
"}" << std::endl;
1330 dictStream << std::endl;
1339 llvm::StringRef
GrabIndex(
const clang::FieldDecl &member,
int printError)
1342 llvm::StringRef where;
1345 if (index.size() == 0 && printError) {
1346 const char *errorstring;
1349 errorstring =
"is not an integer";
1352 errorstring =
"has not been defined before the array";
1355 errorstring =
"is a private member of a parent class";
1358 errorstring =
"is not known";
1361 errorstring =
"UNKNOWN ERROR!!!!";
1364 if (where.size() == 0) {
1366 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1369 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1378 const cling::Interpreter &interp,
1380 std::ostream &dictStream)
1382 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1383 if (clxx == 0)
return;
1390 int enclSpaceNesting = 0;
1396 dictStream <<
"//_______________________________________"
1397 <<
"_______________________________________" << std::endl;
1398 if (add_template_keyword) dictStream <<
"template <> ";
1399 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1400 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1408 int basestreamer = 0;
1409 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1413 string base_fullname;
1416 if (strstr(base_fullname.c_str(),
"::")) {
1418 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1419 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1420 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1422 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1427 if (!basestreamer) {
1428 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1429 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1431 dictStream <<
"}" << std::endl << std::endl;
1432 while (enclSpaceNesting) {
1433 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1440 string classname = fullname;
1441 if (strstr(fullname.c_str(),
"::")) {
1443 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1444 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1445 classname =
"thisClass";
1447 for (
int i = 0; i < 2; i++) {
1452 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1453 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1454 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1456 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1457 dictStream <<
" } else {" << std::endl;
1458 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1463 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1467 string base_fullname;
1470 if (strstr(base_fullname.c_str(),
"::")) {
1472 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1473 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1474 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1477 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1483 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1488 clang::QualType
type = field_iter->getType();
1489 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1499 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1503 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1506 if (strncmp(
comment,
"!", 1)) {
1509 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1510 if (
type.getTypePtr()->isConstantArrayType() &&
1511 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1512 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1516 dictStream <<
" int R__i;" << std::endl;
1519 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1521 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: array of pointers to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1522 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1524 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1526 }
else if (
type.getTypePtr()->isPointerType()) {
1527 llvm::StringRef indexvar =
GrabIndex(**field_iter, i == 0);
1528 if (indexvar.size() == 0) {
1530 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1531 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1533 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1537 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1542 <<
"," << indexvar.str() <<
");" << std::endl;
1543 }
else if (isDouble32) {
1545 <<
"," << indexvar.str() <<
");" << std::endl;
1548 <<
"," << indexvar.str() <<
");" << std::endl;
1552 dictStream <<
" R__b.WriteFastArrayFloat16("
1553 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1554 }
else if (isDouble32) {
1555 dictStream <<
" R__b.WriteFastArrayDouble32("
1556 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1558 dictStream <<
" R__b.WriteFastArray("
1559 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1563 }
else if (
type.getTypePtr()->isArrayType()) {
1565 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1566 if (underling_type->isEnumeralType())
1567 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1571 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1572 }
else if (isDouble32) {
1574 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1577 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1581 if (underling_type->isEnumeralType()) {
1582 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1585 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1586 }
else if (isDouble32) {
1587 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1590 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1595 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1598 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1599 if (underling_type->isEnumeralType())
1600 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1601 <<
s <<
");" << std::endl;
1602 else if (isFloat16) {
1604 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1605 }
else if (isDouble32) {
1607 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1610 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1613 if (underling_type->isEnumeralType())
1614 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1615 else if (isFloat16) {
1616 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1617 }
else if (isDouble32) {
1618 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1620 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1624 }
else if (underling_type->isEnumeralType()) {
1626 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1627 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1629 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1634 <<
"=Float16_t(R_Dummy);}" << std::endl;
1637 }
else if (isDouble32) {
1640 <<
"=Double32_t(R_Dummy);}" << std::endl;
1662 if (
type.getTypePtr()->isConstantArrayType() &&
1663 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1664 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1668 dictStream <<
" int R__i;" << std::endl;
1671 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1676 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1681 dictStream <<
"[R__i];" << std::endl;
1682 }
else if (
type.getTypePtr()->isPointerType()) {
1690 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1691 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1693 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1697 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1711 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1717 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1721 dictStream <<
" int R__i;" << std::endl;
1724 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1725 std::string mTypeNameStr;
1727 const char *mTypeName = mTypeNameStr.c_str();
1728 const char *constwd =
"const ";
1729 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1730 mTypeName += strlen(constwd);
1731 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1733 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1737 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1743 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1744 << field_iter->getName().str() <<
"));" << std::endl;
1755 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1756 <<
" }" << std::endl
1757 <<
"}" << std::endl << std::endl;
1759 while (enclSpaceNesting) {
1760 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1768 const cling::Interpreter &interp,
1770 std::ostream &dictStream)
1774 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1775 if (clxx == 0)
return;
1780 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1792 int enclSpaceNesting = 0;
1798 dictStream <<
"//_______________________________________"
1799 <<
"_______________________________________" << std::endl;
1800 if (add_template_keyword) dictStream <<
"template <> ";
1801 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1803 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1804 <<
" if (R__b.IsReading()) {" << std::endl
1805 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1806 <<
" } else {" << std::endl
1807 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1808 <<
" }" << std::endl
1809 <<
"}" << std::endl << std::endl;
1811 while (enclSpaceNesting) {
1812 dictStream <<
"} // namespace " << nsname << std::endl;
1820 const cling::Interpreter &interp,
1822 std::ostream &dictStream,
1823 bool isAutoStreamer)
1825 if (isAutoStreamer) {
1835 std::string &code_for_parser)
1837 code_for_parser +=
"#ifdef __CINT__\n\n";
1838 code_for_parser +=
"#pragma link off all globals;\n";
1839 code_for_parser +=
"#pragma link off all classes;\n";
1840 code_for_parser +=
"#pragma link off all functions;\n\n";
1842 for (std::string& arg : InputFiles) {
1844 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1845 for (
int j = 0; j < 3; j++) {
1846 if (arg[
l] ==
'-') {
1851 if (arg[
l] ==
'!') {
1856 if (arg[
l] ==
'+') {
1862 if (nostr || noinp) {
1864 if (nostr) strlcat(trail,
"-", 3);
1865 if (noinp) strlcat(trail,
"!", 3);
1868 strlcpy(trail,
"+", 3);
1872 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1873 llvm::sys::path::replace_extension(filestem,
"");
1875 code_for_parser +=
"#pragma link C++ class ";
1876 code_for_parser += filestem.str().str();
1877 if (nostr || noinp || bcnt)
1878 code_for_parser += trail;
1879 code_for_parser +=
";\n";
1882 code_for_parser +=
"\n#endif\n";
1890 bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1895 static const char *fopenopts =
"rb";
1897 static const char *fopenopts =
"r";
1901 fp = fopen(pname.c_str(), fopenopts);
1907 llvm::SmallVector<std::string, 10> includePaths;
1909 interp.GetIncludePaths(includePaths,
false,
false);
1911 const size_t nPaths = includePaths.size();
1912 for (
size_t i = 0; i < nPaths; i += 1 ) {
1916 fp = fopen(pname.c_str(), fopenopts);
1938 const char *inc = strstr(original,
"\\inc\\");
1940 inc = strstr(original,
"/inc/");
1941 if (inc && strlen(inc) > 5)
1961 cling::Interpreter &interp,
1964 std::ostringstream out;
1969 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1970 const std::string &hdrName
1988 static bool WriteAST(StringRef fileName, clang::CompilerInstance *compilerInstance, StringRef iSysRoot,
1989 clang::Module *
module =
nullptr)
1992 llvm::SmallVector<char, 128> buffer;
1993 llvm::BitstreamWriter stream(buffer);
1994 clang::ASTWriter
writer(stream, buffer, compilerInstance->getPCMCache(), {});
1995 std::unique_ptr<llvm::raw_ostream> out =
1996 compilerInstance->createOutputFile(fileName,
true,
2005 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2007 writer.WriteAST(compilerInstance->getSema(), fileName,
module, iSysRoot);
2010 out->write(&buffer.front(), buffer.size());
2022 const std::string ¤tDirectory)
2024 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2026 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2034 static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2037 if (headers.empty())
2041 std::stringstream includes;
2042 for (
const std::string &header : headers) {
2043 includes <<
"#include \"" << header <<
"\"\n";
2045 std::string includeListStr = includes.str();
2046 auto result = interpreter.declare(includeListStr);
2047 return result == cling::Interpreter::CompilationResult::kSuccess;
2055 char platformDefines[64] = {0};
2056 #ifdef __INTEL_COMPILER
2057 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2058 clingArgs.push_back(platformDefines);
2061 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2062 clingArgs.push_back(platformDefines);
2065 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2066 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2067 clingArgs.push_back(platformDefines);
2069 #ifdef __GNUC_MINOR__
2070 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2071 clingArgs.push_back(platformDefines);
2074 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2075 clingArgs.push_back(platformDefines);
2078 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2079 clingArgs.push_back(platformDefines);
2082 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2083 clingArgs.push_back(platformDefines);
2085 #ifdef _STLPORT_VERSION
2087 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2088 clingArgs.push_back(platformDefines);
2091 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2092 clingArgs.push_back(platformDefines);
2095 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2096 clingArgs.push_back(platformDefines);
2099 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2100 clingArgs.push_back(platformDefines);
2103 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2104 clingArgs.push_back(platformDefines);
2107 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2108 clingArgs.push_back(platformDefines);
2111 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2112 clingArgs.push_back(platformDefines);
2116 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2117 clingArgs.push_back(platformDefines);
2118 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2119 clingArgs.push_back(platformDefines);
2128 return llvm::sys::path::filename(path);
2138 if (std::string::npos != pos) {
2139 dirname.assign(path.begin(), path.begin() + pos + 1);
2150 std::string dictLocation;
2152 return !dictLocation.empty();
2158 std::string &rootmapLibName)
2162 if (rootmapFileName.empty()) {
2164 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2165 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2166 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2168 rootmapLibName.c_str(),
2169 rootmapFileName.c_str());
2178 std::string &ctxtName,
2179 const cling::Interpreter &interpreter,
2180 bool treatParent =
true)
2182 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2184 if (!outerCtxt)
return;
2186 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2196 std::string &ctxtName,
2197 const cling::Interpreter &interpreter)
2199 const clang::DeclContext *theContext = theDecl.getDeclContext();
2204 template<
class COLL>
2207 const cling::Interpreter &interp)
2209 if (!decls.empty()) {
2210 std::string autoLoadKey;
2211 for (
auto &
d : decls) {
2215 if (autoLoadKey.empty()) {
2216 names.push_back(
d->getQualifiedNameAsString());
2234 const std::string &rootmapLibName,
2235 const std::list<std::string> &classesDefsList,
2236 const std::list<std::string> &classesNames,
2237 const std::list<std::string> &nsNames,
2238 const std::list<std::string> &tdNames,
2239 const std::list<std::string> &enNames,
2240 const std::list<std::string> &varNames,
2242 const std::unordered_set<std::string> headersToIgnore)
2245 std::ofstream rootmapFile(rootmapFileName.c_str());
2253 std::unordered_set<std::string> classesKeys;
2257 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2258 !enNames.empty() || !varNames.empty()) {
2261 if (!classesDefsList.empty()) {
2262 rootmapFile <<
"{ decls }\n";
2263 for (
auto & classDef : classesDefsList) {
2264 rootmapFile << classDef << std::endl;
2266 rootmapFile <<
"\n";
2268 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2271 if (!classesNames.empty()) {
2272 rootmapFile <<
"# List of selected classes\n";
2273 for (
auto & className : classesNames) {
2274 rootmapFile <<
"class " << className << std::endl;
2275 classesKeys.insert(className);
2278 std::unordered_set<std::string> treatedHeaders;
2279 for (
auto & className : classesNames) {
2281 if (className.find(
"<") != std::string::npos)
continue;
2282 if (headersClassesMap.count(className)) {
2283 auto &headers = headersClassesMap.at(className);
2284 if (!headers.empty()){
2285 auto &header = headers.front();
2286 if (treatedHeaders.insert(header).second &&
2287 headersToIgnore.find(header) == headersToIgnore.end() &&
2289 rootmapFile <<
"header " << header << std::endl;
2297 if (!nsNames.empty()) {
2298 rootmapFile <<
"# List of selected namespaces\n";
2299 for (
auto & nsName : nsNames) {
2300 rootmapFile <<
"namespace " << nsName << std::endl;
2305 if (!tdNames.empty()) {
2306 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2307 for (
const auto & autoloadKey : tdNames)
2308 if (classesKeys.insert(autoloadKey).second)
2309 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2314 if (!enNames.empty()){
2315 rootmapFile <<
"# List of selected enums and outer classes\n";
2316 for (
const auto & autoloadKey : enNames)
2317 if (classesKeys.insert(autoloadKey).second)
2318 rootmapFile <<
"enum " << autoloadKey << std::endl;
2322 if (!varNames.empty()){
2323 rootmapFile <<
"# List of selected vars\n";
2324 for (
const auto & autoloadKey : varNames)
2325 if (classesKeys.insert(autoloadKey).second)
2326 rootmapFile <<
"var " << autoloadKey << std::endl;
2340 auto nsPattern =
'{';
auto nsPatternLength = 1;
2341 auto foundNsPos =
line.find_last_of(nsPattern);
2342 if (foundNsPos == std::string::npos)
return {
"",
""};
2343 foundNsPos+=nsPatternLength;
2344 auto extNs =
line.substr(0,foundNsPos);
2346 auto nsEndPattern =
'}';
2347 auto foundEndNsPos =
line.find(nsEndPattern);
2348 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2350 return {extNs, contained};
2366 std::map<std::string, std::string> nsEntitiesMap;
2367 std::list<std::string> optFwdDeclList;
2368 for (
auto const & fwdDecl : fwdDeclarationsList){
2371 if (extNsAndEntities.first.empty()) {
2373 optFwdDeclList.push_front(fwdDecl);
2375 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2376 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2380 std::string optFwdDecl;
2381 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2382 optFwdDecl = extNsAndEntities.first;
2383 optFwdDecl += extNsAndEntities.second;
2384 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2387 optFwdDeclList.push_front(optFwdDecl);
2390 return optFwdDeclList;
2398 std::list<std::string> &el_list,
2399 std::unordered_set<std::string> &el_set)
2401 std::stringstream elStream(el);
2404 while (getline(elStream, tmp,
'\n')) {
2406 if (el_set.insert(tmp).second && !tmp.empty()) {
2407 el_list.push_back(tmp);
2418 std::list<std::string> &classesList,
2419 std::list<std::string> &classesListForRootmap,
2420 std::list<std::string> &fwdDeclarationsList,
2421 const cling::Interpreter &interpreter)
2429 std::unordered_set<std::string> classesSet;
2430 std::unordered_set<std::string> outerMostClassesSet;
2432 std::string attrName, attrValue;
2433 bool isClassSelected;
2434 std::unordered_set<std::string> availableFwdDecls;
2435 std::string fwdDeclaration;
2437 fwdDeclaration =
"";
2443 fwdDeclaration =
"";
2450 isClassSelected =
true;
2451 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2452 std::string normalizedName;
2453 normalizedName = selClass.GetNormalizedName();
2454 if (!normalizedName.empty() &&
2455 !classesSet.insert(normalizedName).second &&
2456 outerMostClassesSet.count(normalizedName) == 0) {
2457 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2458 <<
" was already selected. This means that two different instances of"
2459 <<
" clang::RecordDecl had the same name, which is not possible."
2460 <<
" This can be a hint of a serious problem in the class selection."
2461 <<
" In addition, the generated dictionary would not even compile.\n";
2464 classesList.push_back(normalizedName);
2467 const char *reqName(selClass.GetRequestedName());
2470 fwdDeclaration =
"";
2475 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2476 fwdDeclaration =
"";
2483 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2485 attrName ==
"rootmap" &&
2486 attrValue ==
"false") {
2487 attrName = attrValue =
"";
2488 isClassSelected =
false;
2492 if (isClassSelected) {
2508 std::string outerMostClassName;
2510 if (!outerMostClassName.empty() &&
2511 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2512 classesSet.insert(outerMostClassName).second &&
2513 outerMostClassesSet.insert(outerMostClassName).second) {
2514 classesListForRootmap.push_back(outerMostClassName);
2516 classesListForRootmap.push_back(normalizedName);
2517 if (reqName && reqName[0] && reqName != normalizedName) {
2518 classesListForRootmap.push_back(reqName);
2523 std::string demangledName = selClass.GetDemangledTypeInfo();
2524 if (!demangledName.empty()) {
2529 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2531 classesListForRootmap.push_back(demangledName);
2537 classesListForRootmap.sort();
2550 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2565 if (clang::CXXRecordDecl *CXXRD =
2566 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2578 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2581 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2584 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2600 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2601 "#include \"TFile.h\"\n"
2602 "#include \"TObjArray.h\"\n"
2603 "#include \"TVirtualArray.h\"\n"
2604 "#include \"TStreamerElement.h\"\n"
2605 "#include \"TProtoClass.h\"\n"
2606 "#include \"TBaseClass.h\"\n"
2607 "#include \"TListOfDataMembers.h\"\n"
2608 "#include \"TListOfEnums.h\"\n"
2609 "#include \"TListOfEnumsWithLock.h\"\n"
2610 "#include \"TDataMember.h\"\n"
2611 "#include \"TEnum.h\"\n"
2612 "#include \"TEnumConstant.h\"\n"
2613 "#include \"TDictAttributeMap.h\"\n"
2614 "#include \"TMessageHandler.h\"\n"
2615 "#include \"TArray.h\"\n"
2616 "#include \"TRefArray.h\"\n"
2617 "#include \"root_std_complex.h\"\n")
2618 != cling::Interpreter::kSuccess)
2629 cling::Interpreter &interp,
2634 bool writeEmptyRootPCM)
2638 bool needsCollectionProxy =
false;
2660 auto nsName =
ns.GetNamespaceDecl()->getQualifiedNameAsString();
2661 if (nsName.find(
"(anonymous)") == std::string::npos)
2666 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2670 if (selClass.RequestOnlyTClass()) {
2678 if (clang::CXXRecordDecl *CXXRD =
2679 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2683 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2694 needsCollectionProxy);
2709 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2713 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2725 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2729 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2734 needsCollectionProxy);
2763 if (finRetCode != 0)
return finRetCode;
2773 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2774 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2777 <<
"#define R__NO_DEPRECATION" << std::endl
2782 <<
"\n/*******************************************************************/\n"
2783 <<
"#include <stddef.h>\n"
2784 <<
"#include <stdio.h>\n"
2785 <<
"#include <stdlib.h>\n"
2786 <<
"#include <string.h>\n"
2787 <<
"#include <assert.h>\n"
2788 <<
"#define G__DICTIONARY\n"
2789 <<
"#include \"RConfig.h\"\n"
2790 <<
"#include \"TClass.h\"\n"
2791 <<
"#include \"TDictAttributeMap.h\"\n"
2792 <<
"#include \"TInterpreter.h\"\n"
2793 <<
"#include \"TROOT.h\"\n"
2794 <<
"#include \"TBuffer.h\"\n"
2795 <<
"#include \"TMemberInspector.h\"\n"
2796 <<
"#include \"TInterpreter.h\"\n"
2797 <<
"#include \"TVirtualMutex.h\"\n"
2798 <<
"#include \"TError.h\"\n\n"
2799 <<
"#ifndef G__ROOT\n"
2800 <<
"#define G__ROOT\n"
2802 <<
"#include \"RtypesImp.h\"\n"
2803 <<
"#include \"TIsAProxy.h\"\n"
2804 <<
"#include \"TFileMergeInfo.h\"\n"
2805 <<
"#include <algorithm>\n"
2806 <<
"#include \"TCollectionProxyInfo.h\"\n"
2807 <<
"/*******************************************************************/\n\n"
2808 <<
"#include \"TDataMember.h\"\n\n";
2815 dictStream <<
"// The generated code does not explicitly qualifies STL entities\n"
2816 <<
"namespace std {} using namespace std;\n\n";
2822 const std::string &includeForSource,
2823 const std::string &extraIncludes)
2825 dictStream <<
"// Header files passed as explicit arguments\n"
2826 << includeForSource << std::endl
2827 <<
"// Header files passed via #pragma extra_include\n"
2828 << extraIncludes << std::endl;
2834 #if defined(R__IOSSIM) || defined(R__IOS)
2853 class tempFileNamesCatalog {
2856 tempFileNamesCatalog(): m_size(0), m_emptyString(
"") {};
2858 std::string getTmpFileName(
const std::string &filename) {
2859 return filename +
"_tmp_" + std::to_string(getpid());
2865 void addFileName(std::string &nameStr) {
2866 if (nameStr.empty())
return;
2868 std::string tmpNameStr(getTmpFileName(nameStr));
2871 const char *
name(nameStr.c_str());
2872 const char *tmpName(tmpNameStr.c_str());
2874 m_names.push_back(nameStr);
2875 m_tempNames.push_back(tmpNameStr);
2879 if (0 == std::rename(
name , tmpName)) {
2884 nameStr = tmpNameStr;
2895 for (
unsigned int i = 0; i < m_size; ++i) {
2896 const char *tmpName = m_tempNames[i].c_str();
2898 std::ifstream ifile(tmpName);
2902 if (0 != std::remove(tmpName)) {
2915 for (
unsigned int i = 0; i < m_size; ++i) {
2916 const char *tmpName = m_tempNames[i].c_str();
2917 const char *
name = m_names[i].c_str();
2919 std::ifstream ifile(tmpName);
2926 if (ifile.is_open())
2928 if (0 != std::rename(tmpName ,
name)) {
2929 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2930 llvm::sys::fs::remove(tmpName);
2934 if (0 != std::rename(tmpName ,
name)) {
2945 const std::string &getFileName(
const std::string &tmpFileName) {
2946 size_t i = std::distance(m_tempNames.begin(),
2947 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2948 if (i == m_tempNames.size())
return m_emptyString;
2955 std::cout <<
"Restoring files in temporary file catalog:\n";
2956 for (
unsigned int i = 0; i < m_size; ++i) {
2957 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
2962 unsigned int m_size;
2963 const std::string m_emptyString;
2964 std::vector<std::string> m_names;
2965 std::vector<std::string> m_tempNames;
2972 tempFileNamesCatalog &tmpCatalog)
2974 std::string splitDictName(tmpCatalog.getFileName(dictpathname));
2975 const size_t dotPos = splitDictName.find_last_of(
".");
2976 splitDictName.insert(dotPos,
"_classdef");
2977 tmpCatalog.addFileName(splitDictName);
2978 return new std::ofstream(splitDictName.c_str());
2987 std::list<std::string> &diagnosticPragmas)
2989 static const std::string
pattern(
"-Wno-");
2993 if (arg ==
"-Wno-noexcept-type") {
3000 diagnosticPragmas.push_back(arg);
3006 cling::Interpreter &interp)
3009 std::string fwdDecl;
3010 std::string initStr(
"{");
3012 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3013 auto &clTemplDecl = *strigNargsToKeepPair.first;
3017 + std::to_string(strigNargsToKeepPair.second)
3020 if (!fwdDeclnArgsToSkipColl.empty())
3031 if (qt.isNull())
return qt;
3032 clang::QualType thisQt(qt);
3033 while (thisQt->isPointerType() ||
3034 thisQt->isReferenceType()) {
3035 thisQt = thisQt->getPointeeType();
3045 const cling::Interpreter &interp,
3046 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3048 std::list<std::string> headers;
3051 cling::Interpreter::PushTransactionRAII RAII(&interp);
3054 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3058 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3061 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3064 if (tArgQualType.isNull())
continue;
3065 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3066 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3073 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3075 if (baseQualType.isNull())
continue;
3076 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3077 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3082 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3083 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3085 if (fieldQualType.isNull()) continue ;
3086 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3087 if (fieldCxxRcd->hasDefinition())
3088 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3094 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3096 for (
auto & fPar : methodIt->parameters()) {
3098 if (fParQualType.isNull())
continue;
3099 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3100 if (fParCxxRcd->hasDefinition())
3101 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3106 if (retQualType.isNull())
continue;
3107 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3108 if (retCxxRcd->hasDefinition())
3117 headers.emplace_back(header);
3130 if (
auto dclCtxt= rcd.getDeclContext()){
3131 if (! dclCtxt->isStdNamespace()){
3140 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3141 if (!clAsTmplSpecDecl)
return false;
3146 auto& astCtxt = rcd.getASTContext();
3147 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3148 for (
auto&& arg : templInstArgs.asArray()){
3150 auto argKind = arg.getKind();
3152 if (argKind == clang::TemplateArgument::Integral)
continue;
3156 auto argQualType = arg.getAsType();
3157 auto isPOD = argQualType.isPODType(astCtxt);
3159 if (isPOD)
continue;
3161 auto argType = argQualType.getTypePtr();
3162 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3165 if (isArgGoodForAutoParseMap)
continue;
3184 const cling::Interpreter &interp)
3186 std::set<const clang::CXXRecordDecl *> visitedDecls;
3187 std::unordered_set<std::string> buffer;
3188 std::string autoParseKey;
3191 for (
auto & annotatedRcd : annotatedRcds) {
3192 if (
const clang::CXXRecordDecl *cxxRcd =
3193 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3195 visitedDecls.clear();
3199 headers.remove_if([&buffer](
const std::string &
s) {
3200 return !buffer.insert(
s).
second;
3203 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3205 headersDeclsMap[autoParseKey] = headers;
3206 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3208 ROOT::TMetaUtils::Info(0,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3213 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3214 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3215 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3221 for (
auto & tDef : tDefDecls) {
3222 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3224 visitedDecls.clear();
3229 headers.remove_if([&buffer](
const std::string &
s) {
3230 return !buffer.insert(
s).
second;
3233 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3234 headersDeclsMap[autoParseKey] = headers;
3239 for (
auto & func : funcDecls) {
3245 for (
auto & var : varDecls) {
3251 for (
auto & en : enumDecls) {
3261 const cling::Interpreter &interp)
3263 std::string newFwdDeclString;
3267 std::string fwdDeclString;
3269 std::unordered_set<std::string> fwdDecls;
3290 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3295 selectedDecls.begin(),
3299 selectedDecls.push_back(TD);
3323 if (fwdDeclString.empty()) fwdDeclString =
"";
3324 return fwdDeclString;
3331 const std::string &detectedUmbrella,
3332 bool payLoadOnly =
false)
3334 std::string headerName;
3337 std::cout <<
"Class-headers Mapping:\n";
3338 std::string headersClassesMapString =
"";
3339 for (
auto const & classHeaders : headersClassesMap) {
3341 std::cout <<
" o " << classHeaders.first <<
" --> ";
3342 headersClassesMapString +=
"\"";
3343 headersClassesMapString += classHeaders.first +
"\"";
3344 for (
auto const & header : classHeaders.second) {
3345 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3346 headersClassesMapString +=
", " + headerName;
3348 std::cout <<
", " << headerName;
3353 std::cout << std::endl;
3354 headersClassesMapString +=
", \"@\",\n";
3356 headersClassesMapString +=
"nullptr";
3357 return headersClassesMapString;
3380 static const std::vector<std::string> namePrfxes {
3383 auto pos = find_if(namePrfxes.begin(),
3385 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3386 return namePrfxes.end() == pos;
3393 static const std::vector<std::string> uclNamePrfxes {
3397 static const std::set<std::string> unsupportedClassesNormNames{
3400 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3401 auto pos = find_if(uclNamePrfxes.begin(),
3402 uclNamePrfxes.end(),
3403 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3404 return uclNamePrfxes.end() == pos;
3414 for (
auto&& aRcd : annotatedRcds){
3415 auto clName = aRcd.GetNormalizedName();
3417 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3418 <<
"currently the support for its I/O is not yet available. Note that "
3419 << clName <<
", even if not selected, will be available for "
3420 <<
"interpreted code.\n";
3424 std::cerr <<
"Error: It is not necessary to explicitly select class "
3425 << clName <<
". I/O is supported for it transparently.\n";
3434 class TRootClingCallbacks :
public cling::InterpreterCallbacks {
3436 std::list<std::string>& fFilesIncludedByLinkdef;
3437 bool isLocked =
false;
3439 TRootClingCallbacks(cling::Interpreter* interp, std::list<std::string>& filesIncludedByLinkdef):
3440 InterpreterCallbacks(interp),
3441 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3443 ~TRootClingCallbacks(){};
3445 virtual void InclusionDirective(clang::SourceLocation ,
const clang::Token & ,
3446 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3447 const clang::FileEntry * , llvm::StringRef ,
3448 llvm::StringRef ,
const clang::Module * )
3450 if (isLocked)
return;
3451 if (IsAngled)
return;
3452 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3453 auto curLexer = PP.getCurrentFileLexer();
3454 if (!curLexer)
return;
3455 auto fileEntry = curLexer->getFileEntry();
3456 if (!fileEntry)
return;
3457 auto thisFileName = fileEntry->getName();
3458 auto fileNameAsString = FileName.str();
3460 if (isThisLinkdef) {
3462 if (isTheIncludedLinkdef) {
3463 fFilesIncludedByLinkdef.clear();
3466 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3479 virtual void EnteredSubmodule(clang::Module* M,
3480 clang::SourceLocation ImportLoc,
3483 using namespace clang;
3484 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3485 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3486 HeaderSearch& HS = PP.getHeaderSearchInfo();
3488 Module* CoreModule = HS.lookupModule(
"Core",
false);
3489 assert(M &&
"Must have module Core");
3490 PP.makeModuleVisible(CoreModule, ImportLoc);
3495 static llvm::cl::list<std::string>
3498 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3500 static llvm::cl::opt<std::string>
3502 llvm::cl::desc(
"<output dictionary file>"),
3515 class CheckModuleBuildClient :
public clang::DiagnosticConsumer {
3516 clang::DiagnosticConsumer *fChild;
3518 clang::ModuleMap &fMap;
3521 CheckModuleBuildClient(clang::DiagnosticConsumer *Child,
bool OwnsChild, clang::ModuleMap &
Map)
3522 : fChild(Child), fOwnsChild(OwnsChild), fMap(
Map)
3526 ~CheckModuleBuildClient()
3532 virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &
Info)
override
3534 using namespace clang::diag;
3540 std::string moduleName;
3541 const clang::Module *
module =
nullptr;
3544 const auto &ID =
Info.getID();
3545 if (ID == remark_module_build || ID == remark_module_build_done) {
3546 moduleName =
Info.getArgStdStr(0);
3547 module = fMap.findModule(moduleName);
3553 "Couldn't find module %s in the available modulemaps. This"
3554 "prevents us from correctly diagnosing wrongly built modules.\n",
3555 moduleName.c_str());
3568 bool isByproductModule
3570 if (!isByproductModule)
3571 fChild->HandleDiagnostic(DiagLevel,
Info);
3573 if (ID == remark_module_build && !isByproductModule) {
3575 "Building module '%s' implicitly. If '%s' requires a \n"
3576 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3577 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3579 moduleName.c_str(), moduleName.c_str());
3584 virtual void clear()
override
3587 DiagnosticConsumer::clear();
3590 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3592 fChild->BeginSourceFile(LangOpts, PP);
3593 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3596 virtual void EndSourceFile()
override
3598 fChild->EndSourceFile();
3599 DiagnosticConsumer::EndSourceFile();
3602 virtual void finish()
override
3605 DiagnosticConsumer::finish();
3608 virtual bool IncludeInDiagnosticCounts()
const override {
return fChild->IncludeInDiagnosticCounts(); }
3612 #if defined(_WIN32) && defined(_MSC_VER)
3616 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3617 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3618 ::_set_error_mode(_OUT_TO_STDERR);
3619 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3620 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3621 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3622 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3623 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3624 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3629 static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3631 static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3642 static llvm::cl::opt<VerboseLevel>
3644 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3645 clEnumVal(
v0,
"Show only fatal errors."),
3646 clEnumVal(
v1,
"Show errors (the same as -v)."),
3647 clEnumVal(
v2,
"Show warnings (default)."),
3648 clEnumVal(
v3,
"Show notes."),
3649 clEnumVal(
v4,
"Show information.")),
3653 static llvm::cl::opt<bool>
3654 gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3657 static llvm::cl::opt<bool>
3658 gOptReflex(
"reflex", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3661 static llvm::cl::opt<bool>
3662 gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3665 static llvm::cl::opt<std::string>
3667 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3670 static llvm::cl::opt<bool>
3672 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3675 static llvm::cl::opt<bool>
3676 gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3678 static llvm::cl::opt<bool>
3679 gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3681 static llvm::cl::list<std::string>
3683 llvm::cl::desc(
"Generate rootmap file."),
3685 static llvm::cl::opt<std::string>
3687 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3689 static llvm::cl::opt<bool>
3691 llvm::cl::desc(
"Generate a C++ module."),
3693 static llvm::cl::list<std::string>
3695 llvm::cl::desc(
"Specify a C++ modulemap file."),
3698 static llvm::cl::opt<bool>
3700 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3702 static llvm::cl::opt<bool>
3704 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3706 static llvm::cl::opt<bool>
3708 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3710 static llvm::cl::opt<bool>
3712 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3714 static llvm::cl::opt<bool>
3716 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3717 information and another the interactivity support."),
3719 static llvm::cl::opt<bool>
3722 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3724 static llvm::cl::opt<std::string>
3726 llvm::cl::desc(
"The path to the library of the built dictionary."),
3728 static llvm::cl::list<std::string>
3730 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3732 static llvm::cl::list<std::string>
3734 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3738 static llvm::cl::opt<bool>
3740 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3748 static llvm::cl::opt<bool>
3751 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3753 static llvm::cl::opt<bool>
3755 llvm::cl::desc(
"Check the selection syntax only."),
3757 static llvm::cl::opt<bool>
3759 llvm::cl::desc(
"Fail if there are warnings."),
3761 static llvm::cl::opt<bool>
3763 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3765 static llvm::cl::opt<std::string>
3767 llvm::cl::desc(
"Specify an isysroot."),
3769 llvm::cl::init(
"-"));
3770 static llvm::cl::list<std::string>
3772 llvm::cl::desc(
"Specify an include path."),
3774 static llvm::cl::list<std::string>
3776 llvm::cl::desc(
"Specify defined macros."),
3778 static llvm::cl::list<std::string>
3780 llvm::cl::desc(
"Specify undefined macros."),
3782 static llvm::cl::list<std::string>
3784 llvm::cl::desc(
"Specify compiler diagnostics options."),
3786 static llvm::cl::list<std::string>
3788 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file>"),
3790 static llvm::cl::list<std::string>
3792 llvm::cl::desc(
"Consumes all unrecognized options."),
3795 static llvm::cl::SubCommand
3798 static llvm::cl::list<std::string>
3800 llvm::cl::desc(
"Consumes options and sends them to cling."),
3810 std::vector<std::string> &missingHeaders)
3813 std::vector<clang::Module::Header> moduleHeaders;
3815 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3817 bool foundAllHeaders =
true;
3822 for (
const std::string &header : modGen.
GetHeaders()) {
3823 bool headerFound =
false;
3824 for (
const clang::Module::Header &moduleHeader : moduleHeaders) {
3825 if (header == moduleHeader.NameAsWritten) {
3831 missingHeaders.push_back(header);
3832 foundAllHeaders =
false;
3835 return foundAllHeaders;
3841 StringRef LinkdefPath,
const std::string &moduleName)
3843 clang::CompilerInstance *CI = interpreter.getCI();
3844 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3845 headerSearch.loadTopLevelSystemModules();
3848 clang::Module *
module = headerSearch.lookupModule(StringRef(moduleName));
3853 moduleName.c_str());
3860 std::vector<std::string> missingHeaders;
3863 std::stringstream msgStream;
3864 msgStream <<
"warning: Couldn't find in "
3865 <<
module->PresumedModuleMapFile
3866 <<
" the following specified headers in "
3867 <<
"the module " <<
module->Name <<
":\n";
3868 for (
auto &
H : missingHeaders) {
3869 msgStream <<
" " <<
H <<
"\n";
3871 std::string warningMessage = msgStream.str();
3873 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3884 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3885 warningMessage.c_str(),
3904 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
3905 moduleName.consume_front(
"lib");
3906 moduleName.consume_back(
".pcm");
3907 moduleName.consume_back(
"_rdict");
3915 bool isGenreflex =
false)
3918 auto &opts = llvm::cl::getRegisteredOptions();
3919 auto &optHelp = *opts[
"help"];
3920 llvm::cl::alias optHelpAlias1(
"h",
3921 llvm::cl::desc(
"Alias for -help"),
3922 llvm::cl::aliasopt(optHelp));
3923 llvm::cl::alias optHelpAlias2(
"?",
3924 llvm::cl::desc(
"Alias for -help"),
3925 llvm::cl::aliasopt(optHelp));
3931 const char *executableFileName = argv[0];
3933 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
3934 llvm::PrettyStackTraceProgram X(argc, argv);
3937 #if defined(R__WIN32) && !defined(R__WINGCC)
3942 for (
int iic = 1 ; iic < argc; ++iic) {
3943 std::string iiarg(argv[iic]);
3945 size_t len = iiarg.length();
3947 char *argviic =
new char[len + 1];
3948 strlcpy(argviic, iiarg.c_str(), len + 1);
3949 argv[iic] = argviic;
3957 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
3961 std::vector<const char *> clingArgsC;
3962 clingArgsC.push_back(executableFileName);
3964 clingArgsC.push_back(
"-I");
3971 clingArgsC.push_back(Opt.c_str());
3973 auto interp = llvm::make_unique<cling::Interpreter>(clingArgsC.size(),
3975 llvmResourceDir.c_str());
3978 return interp->getDiagnostics().hasFatalErrorOccurred();
3981 std::string dictname;
3995 llvm::cl::PrintHelpMessage();
4010 if ((fp = fopen(filein.c_str(),
"r")) == 0) {
4011 ROOT::TMetaUtils::Error(0,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4038 ROOT::TMetaUtils::Error(0,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4039 llvm::cl::PrintHelpMessage();
4043 std::vector<std::string> clingArgs;
4044 clingArgs.push_back(executableFileName);
4045 clingArgs.push_back(
"-iquote.");
4051 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4073 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4078 clingArgs.push_back(std::string(
"-D") + PPDefine);
4081 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4084 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4086 for (
const std::string &WDiag :
gOptWDiags) {
4087 const std::string FullWDiag = std::string(
"-W") + WDiag;
4091 clingArgs.push_back(FullWDiag);
4095 clingArgs.push_back(std::string(
"-I") + includeDir);
4097 std::vector<std::string> pcmArgs;
4098 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4099 auto thisArg = clingArgs[parg];
4101 if (thisArg ==
"-c" ||
4105 unsigned int offset = 2;
4106 char c = thisArg[offset];
4107 while (
c ==
' ')
c = thisArg[++offset];
4111 [&](
const std::string& path){
4112 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4113 if (excludePathsEnd != excludePathPos)
continue;
4115 pcmArgs.push_back(thisArg);
4122 clingArgs.push_back(
"-D__ROOTCLING__");
4125 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4126 #elif defined(R__WIN32)
4127 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4130 clingArgs.push_back(
"-D_XKEYCHECK_H");
4132 clingArgs.push_back(
"-DNOMINMAX");
4134 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4137 clingArgs.push_back(
"-fsyntax-only");
4139 clingArgs.push_back(
"-fPIC");
4141 clingArgs.push_back(
"-Xclang");
4142 clingArgs.push_back(
"-fmodules-embed-all-files");
4143 clingArgs.push_back(
"-Xclang");
4144 clingArgs.push_back(
"-main-file-name");
4145 clingArgs.push_back(
"-Xclang");
4146 clingArgs.push_back((dictname +
".h").c_str());
4154 std::string outputFile;
4156 StringRef moduleName;
4161 auto clingArgsInterpreter = clingArgs;
4170 clingArgsInterpreter.push_back(
"-fmodules");
4171 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4174 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4176 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4178 "/module.modulemap");
4180 if (llvm::sys::fs::exists(ModuleMapCWD))
4181 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4188 clingArgsInterpreter.push_back(
"-fmodule-name");
4189 clingArgsInterpreter.push_back(moduleName.str());
4199 if (moduleName ==
"Core") {
4201 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4202 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4203 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4204 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4206 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4207 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4211 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4213 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4215 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4216 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4217 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4218 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4219 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4220 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4221 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4226 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4230 clingArgsInterpreter.push_back(
"-v");
4233 std::vector<const char *> clingArgsC;
4234 for (
auto const &clingArg : clingArgsInterpreter) {
4236 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4237 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4240 clingArgsC.push_back(clingArg.c_str());
4244 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4245 cling::Interpreter* interpPtr =
nullptr;
4247 std::list<std::string> filesIncludedByLinkdef;
4251 clingArgsC.push_back(
"-ffast-math");
4254 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4255 llvmResourceDir.c_str()));
4256 interpPtr = owningInterpPtr.get();
4259 clingArgsC.push_back(
"-resource-dir");
4260 clingArgsC.push_back(llvmResourceDir.c_str());
4261 clingArgsC.push_back(0);
4263 extraArgs = &clingArgsC[1];
4266 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4267 interpPtr->setCallbacks(std::move(callBacks));
4270 cling::Interpreter &interp = *interpPtr;
4271 clang::CompilerInstance *CI = interp.getCI();
4273 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4274 CI->getSourceManager().setAllFilesAreTransient(
true);
4276 clang::Preprocessor &PP = CI->getPreprocessor();
4277 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4278 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4279 auto &diags = interp.getDiagnostics();
4286 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4290 auto recordingClient =
new CheckModuleBuildClient(diags.getClient(), diags.ownsClient(), moduleMap);
4291 diags.setClient(recordingClient,
true);
4297 interp.DumpIncludePath();
4302 interp.printIncludedFiles(llvm::outs());
4303 llvm::outs() <<
"\n\n";
4304 llvm::outs().flush();
4307 const clang::LangOptions& LangOpts
4308 = interp.getCI()->getASTContext().getLangOpts();
4309 #define LANGOPT(Name, Bits, Default, Description) \
4310 ROOT::TMetaUtils::Info(0, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4311 #define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4312 #include "clang/Basic/LangOptions.def"
4316 interp.getOptions().ErrorOut =
true;
4317 interp.enableRawInput(
true);
4321 if (DepMod.endswith(
"_rdict.pcm")) {
4328 cling::Interpreter::PushTransactionRAII RAII(&interp);
4329 if (!interp.loadModule(DepMod,
false)) {
4338 if (interp.declare(
"#include <assert.h>\n"
4339 "#include \"Rtypes.h\"\n"
4340 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4348 if (interp.declare(
"#include <string>\n"
4349 "#include <RtypesCore.h>\n"
4350 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4361 clingArgs.push_back(
"-D__CINT__");
4362 clingArgs.push_back(
"-D__MAKECINT__");
4368 std::string interpPragmaSource;
4369 std::string includeForSource;
4370 std::string interpreterDeclarations;
4371 std::string linkdef;
4377 if (isSelectionFile) {
4379 linkdef = optHeaderFileName;
4382 executableFileName, optHeaderFileName.c_str());
4388 std::string fullheader(optHeaderFileName);
4391 if (fullheader[fullheader.length() - 1] ==
'+') {
4392 fullheader.erase(fullheader.length() - 1);
4397 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4398 if (!isSelectionFile) {
4406 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4407 pcmArgs.push_back(header);
4409 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4414 bool hasSelectionFile = !linkdef.empty();
4415 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4426 if (!newName.empty())
4439 string incCurDir =
"-I";
4440 incCurDir += currentDirectory;
4441 pcmArgs.push_back(incCurDir);
4446 std::stringstream res;
4447 const char* delim=
"\n";
4448 std::copy(diagnosticPragmas.begin(),
4449 diagnosticPragmas.end(),
4450 std::ostream_iterator<std::string>(res, delim));
4451 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4457 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4459 IgnoringPragmaHandler(
const char* pragma):
4460 clang::PragmaNamespace(pragma) {}
4461 void HandlePragma(clang::Preprocessor &PP,
4462 clang::PragmaIntroducerKind Introducer,
4463 clang::Token &tok) {
4464 PP.DiscardUntilEndOfDirective();
4470 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4471 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4472 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4473 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4475 if (!interpreterDeclarations.empty() &&
4476 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4488 pcmArgs.push_back(linkdef);
4496 interp.AddIncludePath(inclPath);
4498 std::stringstream definesUndefinesStr;
4501 if (!definesUndefinesStr.str().empty()) {
4502 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4503 ROOT::TMetaUtils::Error(0,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4514 if (linkdef.empty()) {
4520 std::ofstream fileout;
4522 std::ostream *splitDictStream =
nullptr;
4523 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4525 tempFileNamesCatalog tmpCatalog;
4544 splitDeleter.reset(splitDictStream);
4546 splitDictStream = &dictStream;
4549 size_t dh = main_dictname.rfind(
'.');
4550 if (dh != std::string::npos) {
4551 main_dictname.erase(dh);
4554 std::string main_dictname_copy(main_dictname);
4573 string linkdefFilename;
4574 if (linkdef.empty()) {
4575 linkdefFilename =
"in memory";
4577 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4585 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4591 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4593 std::string extraIncludes;
4598 const unsigned int selRulesInitialSize = selectionRules.
Size();
4602 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4606 int rootclingRetCode(0);
4608 if (linkdef.empty()) {
4613 clingArgs.push_back(
"-Ietc/cling/cint");
4615 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4616 llvmResourceDir.c_str())) {
4618 rootclingRetCode += 1;
4628 }
else if (isSelXML) {
4632 std::ifstream
file(linkdefFilename.c_str());
4633 if (
file.is_open()) {
4637 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4650 std::ifstream
file(linkdefFilename.c_str());
4651 if (
file.is_open()) {
4661 clingArgs.push_back(
"-Ietc/cling/cint");
4663 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4664 llvmResourceDir.c_str())) {
4666 rootclingRetCode += 1;
4701 dictStream <<
"#include \"TBuffer.h\"\n"
4702 <<
"#include \"TVirtualObject.h\"\n"
4703 <<
"#include <vector>\n"
4704 <<
"#include \"TSchemaHelper.h\"\n\n";
4706 std::list<std::string> includes;
4708 for (
auto & incFile : includes) {
4709 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4711 dictStream << std::endl;
4716 int scannerVerbLevel = 0;
4744 scan.
Scan(CI->getASTContext());
4746 bool has_input_error =
false;
4753 !dictSelRulesPresent &&
4760 if (rootclingRetCode)
return rootclingRetCode;
4767 if (annRcd.RequestNoInputOperator()) {
4779 if (has_input_error) {
4789 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4790 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4809 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4810 constructorTypes.emplace_back(
"__void__", interp);
4811 constructorTypes.emplace_back(
"", interp);
4841 if (rootclingRetCode != 0) {
4842 return rootclingRetCode;
4861 std::string detectedUmbrella;
4862 for (
auto & arg : pcmArgs) {
4864 detectedUmbrella = arg;
4870 headersDeclsMap.clear();
4874 std::string headersClassesMapString =
"\"\"";
4875 std::string fwdDeclsString =
"\"\"";
4891 if (modGen.
IsPCH()) {
4894 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
4904 ofstream outputfile(liblist_filename.c_str(), ios::out);
4907 executableFileName, liblist_filename.c_str());
4909 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4910 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4912 outputfile <<
"# Now the list of classes\n";
4917 outputfile << annRcd.GetNormalizedName() << endl;
4924 if (0 != rootclingRetCode)
return rootclingRetCode;
4930 [](
const std::string &
a,
const std::string &
b) -> std::string {
4931 if (a.empty()) return b;
4932 else return a +
" " + b;
4937 std::list<std::string> classesNames;
4938 std::list<std::string> classesNamesForRootmap;
4939 std::list<std::string> classesDefsList;
4943 classesNamesForRootmap,
4947 std::list<std::string> enumNames;
4952 std::list<std::string> varNames;
4957 if (0 != rootclingRetCode)
return rootclingRetCode;
4960 if (rootMapNeeded) {
4962 std::list<std::string> nsNames;
4971 rootmapLibName.c_str());
4974 std::unordered_set<std::string> headersToIgnore;
4977 headersToIgnore.insert(optHeaderFileName.c_str());
4979 std::list<std::string> typedefsRootmapLines;
4987 classesNamesForRootmap,
4989 typedefsRootmapLines,
4995 if (0 != rootclingRetCode)
return 1;
5005 cling::Interpreter::PushTransactionRAII RAII(&interp);
5006 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5017 if(rootclingRetCode == 0) {
5018 rootclingRetCode += tmpCatalog.commit();
5023 return rootclingRetCode;
5034 unsigned int numberOfHeaders = 0;
5035 for (std::vector<std::string>::iterator it = headersNames.begin();
5036 it != headersNames.end(); ++it) {
5037 const std::string headername(*it);
5042 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5043 headername.c_str());
5046 return numberOfHeaders;
5052 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5055 unsigned int argvCounter = 0;
5056 for (
int i = 1; i < argc; ++i) {
5059 args.push_back(argv[i]);
5061 }
else if (argvCounter) {
5062 argv[i - argvCounter] = argv[i];
5069 std::cout <<
"Args: \n";
5070 for (std::vector<std::string>::iterator it = args.begin();
5071 it < args.end(); ++it) {
5072 std::cout << i <<
") " << *it << std::endl;
5085 size_t result = filename.find_last_of(
'.');
5086 if (std::string::npos != result) {
5087 filename.erase(result);
5088 filename.append(newExtension);
5098 const unsigned int size(str.size());
5099 char *
a =
new char[size + 1];
5101 memcpy(
a, str.c_str(), size);
5117 std::vector<std::string> &ofilesnames)
5119 ofilesnames.reserve(headersNames.size());
5121 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5122 it != headersNames.end(); ++it) {
5123 std::string ofilename(*it);
5125 ofilesnames.push_back(ofilename);
5132 const std::vector<std::string> &argsToBeAdded,
5133 const std::string &optName =
"")
5135 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5136 it != argsToBeAdded.end(); ++it) {
5144 const std::vector<std::string> &argsToBeAdded,
5145 const std::string &optName =
"")
5147 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5148 it != argsToBeAdded.end(); ++it) {
5149 if (optName.length()) {
5159 const std::string &selectionFileName,
5160 const std::string &targetLibName,
5162 const std::vector<std::string> &pcmsNames,
5163 const std::vector<std::string> &includes,
5164 const std::vector<std::string> &preprocDefines,
5165 const std::vector<std::string> &preprocUndefines,
5166 const std::vector<std::string> &warnings,
5167 const std::string &rootmapFileName,
5168 const std::string &rootmapLibName,
5169 bool interpreteronly,
5172 bool writeEmptyRootPCM,
5174 bool noIncludePaths,
5175 bool noGlobalUsingStd,
5176 const std::vector<std::string> &headersNames,
5177 bool failOnWarnings,
5178 const std::string &ofilename)
5182 std::vector<char *> argvVector;
5193 std::string dictLocation;
5199 std::string newRootmapLibName(rootmapLibName);
5200 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5201 if (headersNames.size() != 1) {
5203 "*** genreflex: No rootmap lib and several header specified!\n");
5206 newRootmapLibName =
"lib";
5207 newRootmapLibName += cleanHeaderName;
5213 std::string newRootmapFileName(rootmapFileName);
5214 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5215 newRootmapFileName = dictLocation + newRootmapFileName;
5220 if (!newRootmapFileName.empty()) {
5226 if (!newRootmapLibName.empty()) {
5232 if (interpreteronly)
5240 if (!targetLibName.empty()) {
5250 if (noGlobalUsingStd)
5260 if (writeEmptyRootPCM)
5283 if (!selectionFileName.empty()) {
5287 const int argc = argvVector.size();
5291 std::cout <<
"Rootcling commandline:\n";
5292 for (
int i = 0; i < argc; i++)
5293 std::cout << i <<
") " << argvVector[i] << std::endl;
5296 char **argv = & (argvVector[0]);
5301 for (
int i = 0; i < argc; i++)
5302 delete [] argvVector[i];
5304 return rootclingReturnCode;
5313 const std::string &selectionFileName,
5314 const std::string &targetLibName,
5316 const std::vector<std::string> &pcmsNames,
5317 const std::vector<std::string> &includes,
5318 const std::vector<std::string> &preprocDefines,
5319 const std::vector<std::string> &preprocUndefines,
5320 const std::vector<std::string> &warnings,
5321 const std::string &rootmapFileName,
5322 const std::string &rootmapLibName,
5323 bool interpreteronly,
5326 bool writeEmptyRootPCM,
5328 bool noIncludePaths,
5329 bool noGlobalUsingStd,
5330 const std::vector<std::string> &headersNames,
5331 bool failOnWarnings,
5332 const std::string &outputDirName_const =
"")
5334 std::string outputDirName(outputDirName_const);
5336 std::vector<std::string> ofilesNames;
5343 std::vector<std::string> namesSingleton(1);
5344 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5345 namesSingleton[0] = headersNames[i];
5346 std::string ofilenameFullPath(ofilesNames[i]);
5347 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5348 ofilenameFullPath = outputDirName + ofilenameFullPath;
5370 if (returnCode != 0)
5385 std::vector<std::string> &values)
5388 if (options[oIndex]) {
5389 const int nVals = options[oIndex].count();
5390 values.reserve(nVals);
5391 int optionIndex = 0;
5394 << optionIndex <<
"/" << nVals <<
" "
5395 << opt->arg << std::endl;
5397 values.push_back(opt->arg);
5408 const char *descriptor)
5410 if (options[optionIndex]) {
5412 "*** genereflex: %s is not supported anymore.\n",
5500 enum optionTypes { NOTYPE, STRING } ;
5503 const char *genreflexUsage =
5504 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5505 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5508 const char *selectionFilenameUsage =
5509 "-s, --selection_file\tSelection filename\n"
5510 " Class selection file to specify for which classes the dictionary\n"
5511 " will be generated. The final set can be crafted with exclusion and\n"
5512 " exclusion rules.\n"
5513 " Properties can be specified. Some have special meaning:\n"
5514 " - name [string] name of the entity to select with an exact matching\n"
5515 " - pattern [string] name with wildcards (*) to select entities\n"
5516 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5517 " file where the C++ entities reside and not to C++ entities themselves.\n"
5518 " - transient/persistent [string: true/false] The fields to which they are\n"
5519 " applied will not be persistified if requested.\n"
5520 " - comment [string]: what you could write in code after an inline comment\n"
5521 " without \"//\". For example comment=\"!\" or \"||\".\n"
5522 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5523 " Default value is 'false'\n"
5524 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5525 " to 'true'. Default value is 'false'\n"
5529 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5530 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5531 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5532 " [noInputOperator=\"true/false\"] />\n"
5533 " <class name=\"classname\" >\n"
5534 " <field name=\"m_transient\" transient=\"true\"/>\n"
5535 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5536 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5537 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5539 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5540 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5541 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5544 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5545 " <method name=\"unwanted\" />\n"
5550 " If no selection file is specified, the class with the filename without\n"
5551 " extension will be selected, i.e. myClass.h as argument without any\n"
5552 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5554 const char *outputFilenameUsage =
5555 "-o, --output\tOutput filename\n"
5556 " Output file name. If an existing directory is specified instead of a file,\n"
5557 " then a filename will be build using the name of the input file and will\n"
5558 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5559 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5560 " have unique names.\n";
5563 const char *targetLib =
5564 "-l, --library\tTarget library\n"
5565 " The flag -l must be followed by the name of the library that will\n"
5566 " contain the object file corresponding to the dictionary produced by\n"
5567 " this invocation of genreflex.\n"
5568 " The name takes priority over the one specified for the rootmapfile.\n"
5569 " The name influences the name of the created pcm:\n"
5570 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5571 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5572 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5573 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5574 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5576 const char *rootmapUsage =
5577 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5578 " This file lists the autoload keys. For example classes for which the\n"
5579 " reflection information is provided.\n"
5580 " The format of the rootmap is the following:\n"
5581 " - Forward declarations section\n"
5582 " - Libraries sections\n"
5583 " Rootmaps can be concatenated together, for example with the cat util.\n"
5584 " In order for ROOT to pick up the information in the rootmaps, they\n"
5585 " have to be located in the library path and have the .rootmap extension.\n"
5586 " An example rootmap file could be:\n"
5588 " template <class T> class A;\n"
5589 " [ libMyLib.so ]\n"
5590 " class A<double>\n"
5595 const char *rootmapLibUsage =
5596 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5629 "--multiDict\tSupport for many dictionaries in one library\n"
5630 " Form correct pcm names if multiple dictionaries will be in the same\n"
5631 " library (needs target library switch. See its documentation).\n"
5638 "" ,
"noGlobalUsingStd" ,
5640 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5641 " All header files must have sumbols from std:: namespace fully qualified\n"
5647 "s" ,
"selection_file" ,
5649 selectionFilenameUsage
5663 "" ,
"rootmap-lib" ,
5671 "" ,
"interpreteronly",
5673 "--interpreteronly\tDo not generate I/O related information.\n"
5674 " Generate minimal dictionary required for interactivity.\n"
5682 "--split\tSplit the dictionary\n"
5683 " Split in two the dictionary, isolating the part with\n"
5684 " ClassDef related functions in a separate file.\n"
5692 "-m \tPcm file loaded before any header (option can be repeated).\n"
5700 "-v, --verbose\tPrint some debug information.\n"
5708 "--debug\tPrint all debug information.\n"
5716 "--quiet\tPrint only warnings and errors (default).\n"
5724 "--silent\tPrint no information at all.\n"
5730 "" ,
"writeEmptyPCM",
5732 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5740 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5749 "--help\tPrint usage and exit.\n"
5755 "",
"fail_on_warnings",
5757 "--fail_on_warnings\tFail on warnings and errors.\n"
5763 "",
"selSyntaxOnly",
5765 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5771 "" ,
"noIncludePaths",
5773 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5812 "" ,
"no_membertypedefs" ,
5820 "" ,
"no_templatetypedefs" ,
5828 std::vector<std::string> headersNames;
5829 const int originalArgc = argc;
5831 const int extractedArgs =
extractArgs(argc, argv, headersNames);
5833 const int offset = 1;
5834 argc -= offset + extractedArgs;
5839 std::vector<ROOT::option::Option> options(stats.
options_max);
5840 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5846 if (parse.
error()) {
5852 if (options[HELP] || originalArgc == 1) {
5858 if (0 == numberOfHeaders) {
5869 std::string verbosityOption(
"-v2");
5870 if (options[SILENT]) verbosityOption =
"-v0";
5871 if (options[
VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5872 if (options[
DEBUG]) verbosityOption =
"-v4";
5877 std::string selectionFileName;
5878 if (options[SELECTIONFILENAME]) {
5879 selectionFileName = options[SELECTIONFILENAME].arg;
5882 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
5883 selectionFileName.c_str());
5898 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
5899 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");