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>
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/Frontend/CompilerInstance.h"
70#include "clang/Frontend/FrontendActions.h"
71#include "clang/Frontend/FrontendDiagnostic.h"
72#include "clang/Lex/HeaderSearch.h"
73#include "clang/Lex/Preprocessor.h"
74#include "clang/Lex/ModuleMap.h"
75#include "clang/Lex/Pragma.h"
76#include "clang/Sema/Sema.h"
77#include "clang/Serialization/ASTWriter.h"
78#include "cling/Utils/AST.h"
80#include "llvm/ADT/StringRef.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>
114#define strcasecmp _stricmp
115#define strncasecmp _strnicmp
141static llvm::cl::opt<bool>
143 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
144When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
164static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
168 for (
const auto td : tdvec)
171static 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];
210 ::GetModuleFileName(NULL, buf, 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) {
249 if (! it->GetAttributeValue(propNames::name, varName))
continue;
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;
259 if (
name == propNames::name)
continue;
264 if (
name == propNames::iotype &&
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());
279 if (
name == propNames::comment) {
280 decl.addAttr(
new(C) clang::AnnotateAttr(commentRange, C, value, 0));
284 if ((
name == propNames::transient && value ==
"true") ||
285 (
name == propNames::persistent && value ==
"false")) {
286 userDefinedProperty = propNames::comment + propNames::separator +
"!";
290 decl.addAttr(
new(C) clang::AnnotateAttr(commentRange, C,
"!", 0));
295 userDefinedProperty =
name + propNames::separator + value;
298 decl.addAttr(
new(C) clang::AnnotateAttr(commentRange, C, userDefinedProperty, 0));
309 cling::Interpreter &interpreter,
317 using namespace clang;
318 SourceLocation commentSLoc;
319 llvm::StringRef comment;
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") {
373 if (comment.size()) {
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;
678void 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;
787bool 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 ROOTDict {" << std::endl;
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
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;
1339llvm::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";
1890bool 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
1988static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance,
1989 llvm::StringRef iSysRoot,
1990 clang::Module *module =
nullptr)
1993 llvm::SmallVector<char, 128> buffer;
1994 llvm::BitstreamWriter stream(buffer);
1995 clang::ASTWriter
writer(stream, buffer, compilerInstance->getModuleCache(), {});
1996 std::unique_ptr<llvm::raw_ostream> out =
1997 compilerInstance->createOutputFile(fileName,
true,
2006 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2008 writer.WriteAST(compilerInstance->getSema(), fileName, module, iSysRoot);
2011 out->write(&buffer.front(), buffer.size());
2023 const std::string ¤tDirectory)
2025 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2027 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2035static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2038 if (headers.empty())
2042 std::stringstream includes;
2043 for (
const std::string &header : headers) {
2044 includes <<
"#include \"" << header <<
"\"\n";
2046 std::string includeListStr = includes.str();
2047 auto result = interpreter.declare(includeListStr);
2048 return result == cling::Interpreter::CompilationResult::kSuccess;
2056 char platformDefines[64] = {0};
2057#ifdef __INTEL_COMPILER
2058 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2059 clingArgs.push_back(platformDefines);
2062 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2063 clingArgs.push_back(platformDefines);
2066 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2067 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2068 clingArgs.push_back(platformDefines);
2070#ifdef __GNUC_MINOR__
2071 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2072 clingArgs.push_back(platformDefines);
2075 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2076 clingArgs.push_back(platformDefines);
2079 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2080 clingArgs.push_back(platformDefines);
2083 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2084 clingArgs.push_back(platformDefines);
2086#ifdef _STLPORT_VERSION
2088 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2089 clingArgs.push_back(platformDefines);
2092 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2093 clingArgs.push_back(platformDefines);
2096 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2097 clingArgs.push_back(platformDefines);
2100 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2101 clingArgs.push_back(platformDefines);
2104 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2105 clingArgs.push_back(platformDefines);
2108 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2109 clingArgs.push_back(platformDefines);
2112 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2113 clingArgs.push_back(platformDefines);
2117 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2118 clingArgs.push_back(platformDefines);
2119 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2120 clingArgs.push_back(platformDefines);
2129 return llvm::sys::path::filename(path);
2139 if (std::string::npos != pos) {
2140 dirname.assign(path.begin(), path.begin() + pos + 1);
2151 std::string dictLocation;
2153 return !dictLocation.empty();
2159 std::string &rootmapLibName)
2163 if (rootmapFileName.empty()) {
2165 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2166 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2167 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2169 rootmapLibName.c_str(),
2170 rootmapFileName.c_str());
2179 std::string &ctxtName,
2180 const cling::Interpreter &interpreter,
2181 bool treatParent =
true)
2183 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2185 if (!outerCtxt)
return;
2187 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2197 std::string &ctxtName,
2198 const cling::Interpreter &interpreter)
2200 const clang::DeclContext *theContext = theDecl.getDeclContext();
2208 const cling::Interpreter &interp)
2210 if (!decls.empty()) {
2211 std::string autoLoadKey;
2212 for (
auto &
d : decls) {
2216 if (autoLoadKey.empty()) {
2217 names.push_back(
d->getQualifiedNameAsString());
2235 const std::string &rootmapLibName,
2236 const std::list<std::string> &classesDefsList,
2237 const std::list<std::string> &classesNames,
2238 const std::list<std::string> &nsNames,
2239 const std::list<std::string> &tdNames,
2240 const std::list<std::string> &enNames,
2241 const std::list<std::string> &varNames,
2243 const std::unordered_set<std::string> headersToIgnore)
2246 std::ofstream rootmapFile(rootmapFileName.c_str());
2254 std::unordered_set<std::string> classesKeys;
2258 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2259 !enNames.empty() || !varNames.empty()) {
2262 if (!classesDefsList.empty()) {
2263 rootmapFile <<
"{ decls }\n";
2264 for (
auto & classDef : classesDefsList) {
2265 rootmapFile << classDef << std::endl;
2267 rootmapFile <<
"\n";
2269 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2272 if (!classesNames.empty()) {
2273 rootmapFile <<
"# List of selected classes\n";
2274 for (
auto & className : classesNames) {
2275 rootmapFile <<
"class " << className << std::endl;
2276 classesKeys.insert(className);
2279 std::unordered_set<std::string> treatedHeaders;
2280 for (
auto & className : classesNames) {
2282 if (className.find(
"<") != std::string::npos)
continue;
2283 if (headersClassesMap.count(className)) {
2284 auto &headers = headersClassesMap.at(className);
2285 if (!headers.empty()){
2286 auto &header = headers.front();
2287 if (treatedHeaders.insert(header).second &&
2288 headersToIgnore.find(header) == headersToIgnore.end() &&
2290 rootmapFile <<
"header " << header << std::endl;
2298 if (!nsNames.empty()) {
2299 rootmapFile <<
"# List of selected namespaces\n";
2300 for (
auto & nsName : nsNames) {
2301 rootmapFile <<
"namespace " << nsName << std::endl;
2306 if (!tdNames.empty()) {
2307 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2308 for (
const auto & autoloadKey : tdNames)
2309 if (classesKeys.insert(autoloadKey).second)
2310 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2315 if (!enNames.empty()){
2316 rootmapFile <<
"# List of selected enums and outer classes\n";
2317 for (
const auto & autoloadKey : enNames)
2318 if (classesKeys.insert(autoloadKey).second)
2319 rootmapFile <<
"enum " << autoloadKey << std::endl;
2323 if (!varNames.empty()){
2324 rootmapFile <<
"# List of selected vars\n";
2325 for (
const auto & autoloadKey : varNames)
2326 if (classesKeys.insert(autoloadKey).second)
2327 rootmapFile <<
"var " << autoloadKey << std::endl;
2341 auto nsPattern =
'{';
auto nsPatternLength = 1;
2342 auto foundNsPos =
line.find_last_of(nsPattern);
2343 if (foundNsPos == std::string::npos)
return {
"",
""};
2344 foundNsPos+=nsPatternLength;
2345 auto extNs =
line.substr(0,foundNsPos);
2347 auto nsEndPattern =
'}';
2348 auto foundEndNsPos =
line.find(nsEndPattern);
2349 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2351 return {extNs, contained};
2367 std::map<std::string, std::string> nsEntitiesMap;
2368 std::list<std::string> optFwdDeclList;
2369 for (
auto const & fwdDecl : fwdDeclarationsList){
2372 if (extNsAndEntities.first.empty()) {
2374 optFwdDeclList.push_front(fwdDecl);
2376 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2377 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2381 std::string optFwdDecl;
2382 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2383 optFwdDecl = extNsAndEntities.first;
2384 optFwdDecl += extNsAndEntities.second;
2385 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2388 optFwdDeclList.push_front(optFwdDecl);
2391 return optFwdDeclList;
2399 std::list<std::string> &el_list,
2400 std::unordered_set<std::string> &el_set)
2402 std::stringstream elStream(el);
2405 while (getline(elStream, tmp,
'\n')) {
2407 if (el_set.insert(tmp).second && !tmp.empty()) {
2408 el_list.push_back(tmp);
2419 std::list<std::string> &classesList,
2420 std::list<std::string> &classesListForRootmap,
2421 std::list<std::string> &fwdDeclarationsList,
2422 const cling::Interpreter &interpreter)
2430 std::unordered_set<std::string> classesSet;
2431 std::unordered_set<std::string> outerMostClassesSet;
2433 std::string attrName, attrValue;
2434 bool isClassSelected;
2435 std::unordered_set<std::string> availableFwdDecls;
2436 std::string fwdDeclaration;
2438 fwdDeclaration =
"";
2444 fwdDeclaration =
"";
2451 isClassSelected =
true;
2452 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2453 std::string normalizedName;
2454 normalizedName = selClass.GetNormalizedName();
2455 if (!normalizedName.empty() &&
2456 !classesSet.insert(normalizedName).second &&
2457 outerMostClassesSet.count(normalizedName) == 0) {
2458 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2459 <<
" was already selected. This means that two different instances of"
2460 <<
" clang::RecordDecl had the same name, which is not possible."
2461 <<
" This can be a hint of a serious problem in the class selection."
2462 <<
" In addition, the generated dictionary would not even compile.\n";
2465 classesList.push_back(normalizedName);
2468 const char *reqName(selClass.GetRequestedName());
2471 fwdDeclaration =
"";
2476 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2477 fwdDeclaration =
"";
2480 std::string fwdDeclarationTemplateSpec;
2482 fwdDeclaration +=
'\n' + fwdDeclarationTemplateSpec;
2490 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2492 attrName ==
"rootmap" &&
2493 attrValue ==
"false") {
2494 attrName = attrValue =
"";
2495 isClassSelected =
false;
2499 if (isClassSelected) {
2515 std::string outerMostClassName;
2517 if (!outerMostClassName.empty() &&
2518 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2519 classesSet.insert(outerMostClassName).second &&
2520 outerMostClassesSet.insert(outerMostClassName).second) {
2521 classesListForRootmap.push_back(outerMostClassName);
2523 classesListForRootmap.push_back(normalizedName);
2524 if (reqName && reqName[0] && reqName != normalizedName) {
2525 classesListForRootmap.push_back(reqName);
2530 std::string demangledName = selClass.GetDemangledTypeInfo();
2531 if (!demangledName.empty()) {
2536 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2538 classesListForRootmap.push_back(demangledName);
2544 classesListForRootmap.sort();
2557 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2572 if (clang::CXXRecordDecl *CXXRD =
2573 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2585 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2588 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2591 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2607 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2608 "#include \"TFile.h\"\n"
2609 "#include \"TObjArray.h\"\n"
2610 "#include \"TVirtualArray.h\"\n"
2611 "#include \"TStreamerElement.h\"\n"
2612 "#include \"TProtoClass.h\"\n"
2613 "#include \"TBaseClass.h\"\n"
2614 "#include \"TListOfDataMembers.h\"\n"
2615 "#include \"TListOfEnums.h\"\n"
2616 "#include \"TListOfEnumsWithLock.h\"\n"
2617 "#include \"TDataMember.h\"\n"
2618 "#include \"TEnum.h\"\n"
2619 "#include \"TEnumConstant.h\"\n"
2620 "#include \"TDictAttributeMap.h\"\n"
2621 "#include \"TMessageHandler.h\"\n"
2622 "#include \"TArray.h\"\n"
2623 "#include \"TRefArray.h\"\n"
2624 "#include \"root_std_complex.h\"\n")
2625 != cling::Interpreter::kSuccess)
2636 cling::Interpreter &interp,
2641 bool writeEmptyRootPCM)
2645 bool needsCollectionProxy =
false;
2667 auto nsName = ns.GetNamespaceDecl()->getQualifiedNameAsString();
2668 if (nsName.find(
"(anonymous)") == std::string::npos)
2673 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2677 if (selClass.RequestOnlyTClass()) {
2685 if (clang::CXXRecordDecl *CXXRD =
2686 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2690 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2701 needsCollectionProxy);
2716 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2720 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2732 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2736 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2741 needsCollectionProxy);
2770 if (finRetCode != 0)
return finRetCode;
2780 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2781 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2784 <<
"#define R__NO_DEPRECATION" << std::endl
2789 <<
"\n/*******************************************************************/\n"
2790 <<
"#include <stddef.h>\n"
2791 <<
"#include <stdio.h>\n"
2792 <<
"#include <stdlib.h>\n"
2793 <<
"#include <string.h>\n"
2794 <<
"#include <assert.h>\n"
2795 <<
"#define G__DICTIONARY\n"
2796 <<
"#include \"RConfig.h\"\n"
2797 <<
"#include \"TClass.h\"\n"
2798 <<
"#include \"TDictAttributeMap.h\"\n"
2799 <<
"#include \"TInterpreter.h\"\n"
2800 <<
"#include \"TROOT.h\"\n"
2801 <<
"#include \"TBuffer.h\"\n"
2802 <<
"#include \"TMemberInspector.h\"\n"
2803 <<
"#include \"TInterpreter.h\"\n"
2804 <<
"#include \"TVirtualMutex.h\"\n"
2805 <<
"#include \"TError.h\"\n\n"
2806 <<
"#ifndef G__ROOT\n"
2807 <<
"#define G__ROOT\n"
2809 <<
"#include \"RtypesImp.h\"\n"
2810 <<
"#include \"TIsAProxy.h\"\n"
2811 <<
"#include \"TFileMergeInfo.h\"\n"
2812 <<
"#include <algorithm>\n"
2813 <<
"#include \"TCollectionProxyInfo.h\"\n"
2814 <<
"/*******************************************************************/\n\n"
2815 <<
"#include \"TDataMember.h\"\n\n";
2822 dictStream <<
"// The generated code does not explicitly qualify STL entities\n"
2823 <<
"namespace std {} using namespace std;\n\n";
2829 const std::string &includeForSource,
2830 const std::string &extraIncludes)
2832 dictStream <<
"// Header files passed as explicit arguments\n"
2833 << includeForSource << std::endl
2834 <<
"// Header files passed via #pragma extra_include\n"
2835 << extraIncludes << std::endl;
2841#if defined(R__IOSSIM) || defined(R__IOS)
2860class tempFileNamesCatalog {
2863 tempFileNamesCatalog(): m_size(0), m_emptyString(
"") {};
2865 std::string getTmpFileName(
const std::string &filename) {
2866 return filename +
"_tmp_" + std::to_string(getpid());
2872 void addFileName(std::string &nameStr) {
2873 if (nameStr.empty())
return;
2875 std::string tmpNameStr(getTmpFileName(nameStr));
2878 const char *
name(nameStr.c_str());
2879 const char *tmpName(tmpNameStr.c_str());
2881 m_names.push_back(nameStr);
2882 m_tempNames.push_back(tmpNameStr);
2886 if (0 == std::rename(
name , tmpName)) {
2891 nameStr = tmpNameStr;
2902 for (
unsigned int i = 0; i < m_size; ++i) {
2903 const char *tmpName = m_tempNames[i].c_str();
2905 std::ifstream ifile(tmpName);
2909 if (0 != std::remove(tmpName)) {
2922 for (
unsigned int i = 0; i < m_size; ++i) {
2923 const char *tmpName = m_tempNames[i].c_str();
2924 const char *
name = m_names[i].c_str();
2926 std::ifstream ifile(tmpName);
2933 if (ifile.is_open())
2935 if (0 != std::rename(tmpName ,
name)) {
2936 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2937 llvm::sys::fs::remove(tmpName);
2941 if (0 != std::rename(tmpName ,
name)) {
2952 const std::string &getFileName(
const std::string &tmpFileName) {
2953 size_t i = std::distance(m_tempNames.begin(),
2954 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2955 if (i == m_tempNames.size())
return m_emptyString;
2962 std::cout <<
"Restoring files in temporary file catalog:\n";
2963 for (
unsigned int i = 0; i < m_size; ++i) {
2964 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
2969 unsigned int m_size;
2970 const std::string m_emptyString;
2971 std::vector<std::string> m_names;
2972 std::vector<std::string> m_tempNames;
2979 tempFileNamesCatalog &tmpCatalog)
2981 std::string splitDictName(tmpCatalog.getFileName(dictpathname));
2982 const size_t dotPos = splitDictName.find_last_of(
".");
2983 splitDictName.insert(dotPos,
"_classdef");
2984 tmpCatalog.addFileName(splitDictName);
2985 return new std::ofstream(splitDictName.c_str());
2994 std::list<std::string> &diagnosticPragmas)
2996 static const std::string pattern(
"-Wno-");
2998 if (arg.find(pattern) != 0)
3000 if (arg ==
"-Wno-noexcept-type") {
3007 diagnosticPragmas.push_back(arg);
3013 cling::Interpreter &interp)
3016 std::string fwdDecl;
3017 std::string initStr(
"{");
3019 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3020 auto &clTemplDecl = *strigNargsToKeepPair.first;
3021 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3024 + std::to_string(strigNargsToKeepPair.second)
3027 if (!fwdDeclnArgsToSkipColl.empty())
3038 if (qt.isNull())
return qt;
3039 clang::QualType thisQt(qt);
3040 while (thisQt->isPointerType() ||
3041 thisQt->isReferenceType()) {
3042 thisQt = thisQt->getPointeeType();
3052 const cling::Interpreter &interp,
3053 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3055 std::list<std::string> headers;
3058 cling::Interpreter::PushTransactionRAII RAII(&interp);
3061 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3065 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3068 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3069 if (clang::TemplateArgument::ArgKind::Type != tArg.getKind())
continue;
3071 if (tArgQualType.isNull())
continue;
3072 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3073 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3080 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3082 if (baseQualType.isNull())
continue;
3083 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3084 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3089 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3090 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3092 if (fieldQualType.isNull()) continue ;
3093 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3094 if (fieldCxxRcd->hasDefinition())
3095 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3101 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3103 for (
auto & fPar : methodIt->parameters()) {
3105 if (fParQualType.isNull())
continue;
3106 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3107 if (fParCxxRcd->hasDefinition())
3108 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3113 if (retQualType.isNull())
continue;
3114 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3115 if (retCxxRcd->hasDefinition())
3124 headers.emplace_back(header);
3137 if (
auto dclCtxt= rcd.getDeclContext()){
3138 if (! dclCtxt->isStdNamespace()){
3147 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3148 if (!clAsTmplSpecDecl)
return false;
3153 auto& astCtxt = rcd.getASTContext();
3154 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3155 for (
auto&& arg : templInstArgs.asArray()){
3157 auto argKind = arg.getKind();
3158 if (argKind != clang::TemplateArgument::Type){
3159 if (argKind == clang::TemplateArgument::Integral)
continue;
3163 auto argQualType = arg.getAsType();
3164 auto isPOD = argQualType.isPODType(astCtxt);
3166 if (isPOD)
continue;
3168 auto argType = argQualType.getTypePtr();
3169 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3172 if (isArgGoodForAutoParseMap)
continue;
3191 const cling::Interpreter &interp)
3193 std::set<const clang::CXXRecordDecl *> visitedDecls;
3194 std::unordered_set<std::string> buffer;
3195 std::string autoParseKey;
3198 for (
auto & annotatedRcd : annotatedRcds) {
3199 if (
const clang::CXXRecordDecl *cxxRcd =
3200 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3202 visitedDecls.clear();
3206 headers.remove_if([&buffer](
const std::string & s) {
3207 return !buffer.insert(s).second;
3210 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3212 headersDeclsMap[autoParseKey] = headers;
3213 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3215 ROOT::TMetaUtils::Info(0,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3220 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3221 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3222 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3228 for (
auto & tDef : tDefDecls) {
3229 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3231 visitedDecls.clear();
3236 headers.remove_if([&buffer](
const std::string & s) {
3237 return !buffer.insert(s).second;
3240 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3241 headersDeclsMap[autoParseKey] = headers;
3246 for (
auto & func : funcDecls) {
3252 for (
auto & var : varDecls) {
3258 for (
auto & en : enumDecls) {
3268 const cling::Interpreter &interp)
3270 std::string newFwdDeclString;
3274 std::string fwdDeclString;
3276 std::unordered_set<std::string> fwdDecls;
3297 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3302 selectedDecls.begin(),
3306 selectedDecls.push_back(TD);
3311 std::string fwdDeclLogs;
3319 std::cout <<
"Logs from forward decl printer: \n"
3336 if (fwdDeclString.empty()) fwdDeclString =
"";
3337 return fwdDeclString;
3344 const std::string &detectedUmbrella,
3345 bool payLoadOnly =
false)
3347 std::string headerName;
3350 std::cout <<
"Class-headers Mapping:\n";
3351 std::string headersClassesMapString =
"";
3352 for (
auto const & classHeaders : headersClassesMap) {
3354 std::cout <<
" o " << classHeaders.first <<
" --> ";
3355 headersClassesMapString +=
"\"";
3356 headersClassesMapString += classHeaders.first +
"\"";
3357 for (
auto const & header : classHeaders.second) {
3358 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3359 headersClassesMapString +=
", " + headerName;
3361 std::cout <<
", " << headerName;
3366 std::cout << std::endl;
3367 headersClassesMapString +=
", \"@\",\n";
3369 headersClassesMapString +=
"nullptr";
3370 return headersClassesMapString;
3393 static const std::vector<std::string> namePrfxes {
3396 auto pos = find_if(namePrfxes.begin(),
3398 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3399 return namePrfxes.end() == pos;
3406 static const std::vector<std::string> uclNamePrfxes {
3410 static const std::set<std::string> unsupportedClassesNormNames{
3413 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3414 auto pos = find_if(uclNamePrfxes.begin(),
3415 uclNamePrfxes.end(),
3416 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3417 return uclNamePrfxes.end() == pos;
3427 for (
auto&& aRcd : annotatedRcds){
3428 auto clName = aRcd.GetNormalizedName();
3430 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3431 <<
"currently the support for its I/O is not yet available. Note that "
3432 << clName <<
", even if not selected, will be available for "
3433 <<
"interpreted code.\n";
3437 std::cerr <<
"Error: It is not necessary to explicitly select class "
3438 << clName <<
". I/O is supported for it transparently.\n";
3447class TRootClingCallbacks :
public cling::InterpreterCallbacks {
3449 std::list<std::string>& fFilesIncludedByLinkdef;
3450 bool isLocked =
false;
3452 TRootClingCallbacks(cling::Interpreter* interp, std::list<std::string>& filesIncludedByLinkdef):
3453 InterpreterCallbacks(interp),
3454 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3456 ~TRootClingCallbacks(){};
3458 virtual void InclusionDirective(clang::SourceLocation ,
const clang::Token & ,
3459 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3460 const clang::FileEntry * , llvm::StringRef ,
3461 llvm::StringRef ,
const clang::Module * ,
3462 clang::SrcMgr::CharacteristicKind )
3464 if (isLocked)
return;
3465 if (IsAngled)
return;
3466 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3467 auto curLexer = PP.getCurrentFileLexer();
3468 if (!curLexer)
return;
3469 auto fileEntry = curLexer->getFileEntry();
3470 if (!fileEntry)
return;
3471 auto thisFileName = fileEntry->getName();
3472 auto fileNameAsString = FileName.str();
3474 if (isThisLinkdef) {
3476 if (isTheIncludedLinkdef) {
3477 fFilesIncludedByLinkdef.clear();
3480 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3493 virtual void EnteredSubmodule(clang::Module* M,
3494 clang::SourceLocation ImportLoc,
3497 using namespace clang;
3498 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3499 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3500 HeaderSearch& HS = PP.getHeaderSearchInfo();
3502 Module* CoreModule = HS.lookupModule(
"Core",
false);
3503 assert(M &&
"Must have module Core");
3504 PP.makeModuleVisible(CoreModule, ImportLoc);
3509static llvm::cl::list<std::string>
3512 llvm::cl::desc(
"The list of the expected implicit modules build as part of building the current module."),
3514static llvm::cl::opt<std::string>
3516 llvm::cl::desc(
"<output dictionary file>"),
3529class CheckModuleBuildClient :
public clang::DiagnosticConsumer {
3530 clang::DiagnosticConsumer *fChild;
3532 clang::ModuleMap &fMap;
3535 CheckModuleBuildClient(clang::DiagnosticConsumer *Child,
bool OwnsChild, clang::ModuleMap &Map)
3536 : fChild(Child), fOwnsChild(OwnsChild), fMap(Map)
3540 ~CheckModuleBuildClient()
3546 virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &
Info)
override
3548 using namespace clang::diag;
3554 std::string moduleName;
3555 const clang::Module *
module =
nullptr;
3558 const auto &ID =
Info.getID();
3559 if (ID == remark_module_build || ID == remark_module_build_done) {
3560 moduleName =
Info.getArgStdStr(0);
3561 module = fMap.findModule(moduleName);
3567 "Couldn't find module %s in the available modulemaps. This"
3568 "prevents us from correctly diagnosing wrongly built modules.\n",
3569 moduleName.c_str());
3582 bool isByproductModule
3584 if (!isByproductModule)
3585 fChild->HandleDiagnostic(DiagLevel,
Info);
3587 if (ID == remark_module_build && !isByproductModule) {
3589 "Building module '%s' implicitly. If '%s' requires a \n"
3590 "dictionary please specify build dependency: '%s' depends on '%s'.\n"
3591 "Otherwise, specify '-mByproduct %s' to disable this diagnostic.\n",
3593 moduleName.c_str(), moduleName.c_str());
3598 virtual void clear()
override
3601 DiagnosticConsumer::clear();
3604 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3606 fChild->BeginSourceFile(LangOpts, PP);
3607 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3610 virtual void EndSourceFile()
override
3612 fChild->EndSourceFile();
3613 DiagnosticConsumer::EndSourceFile();
3616 virtual void finish()
override
3619 DiagnosticConsumer::finish();
3622 virtual bool IncludeInDiagnosticCounts()
const override {
return fChild->IncludeInDiagnosticCounts(); }
3626#if defined(_WIN32) && defined(_MSC_VER)
3630 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3631 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3632 ::_set_error_mode(_OUT_TO_STDERR);
3633 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3634 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3635 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3636 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3637 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3638 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3643static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3645static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3656static llvm::cl::opt<VerboseLevel>
3658 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3659 clEnumVal(
v0,
"Show only fatal errors."),
3660 clEnumVal(
v1,
"Show errors (the same as -v)."),
3661 clEnumVal(
v2,
"Show warnings (default)."),
3662 clEnumVal(
v3,
"Show notes."),
3663 clEnumVal(
v4,
"Show information.")),
3667static llvm::cl::opt<bool>
3668gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3671static llvm::cl::opt<bool>
3672gOptReflex(
"reflex", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3675static llvm::cl::opt<bool>
3676gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3679static llvm::cl::opt<std::string>
3681 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3684static llvm::cl::opt<bool>
3686 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3689static llvm::cl::opt<bool>
3690gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3692static llvm::cl::opt<bool>
3693gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3695static llvm::cl::list<std::string>
3697 llvm::cl::desc(
"Generate rootmap file."),
3699static llvm::cl::opt<std::string>
3701 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3703static llvm::cl::opt<bool>
3705 llvm::cl::desc(
"Generate a C++ module."),
3707static llvm::cl::list<std::string>
3709 llvm::cl::desc(
"Specify a C++ modulemap file."),
3712static llvm::cl::opt<bool>
3714 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3716static llvm::cl::opt<bool>
3718 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3720static llvm::cl::opt<bool>
3722 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3724static llvm::cl::opt<bool>
3726 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3728static llvm::cl::opt<bool>
3730 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3731information and another the interactivity support."),
3733static llvm::cl::opt<bool>
3736 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3738static llvm::cl::opt<std::string>
3740 llvm::cl::desc(
"The path to the library of the built dictionary."),
3742static llvm::cl::list<std::string>
3744 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3746static llvm::cl::list<std::string>
3748 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3752static llvm::cl::opt<bool>
3754 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3762static llvm::cl::opt<bool>
3765 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3767static llvm::cl::opt<bool>
3769 llvm::cl::desc(
"Check the selection syntax only."),
3771static llvm::cl::opt<bool>
3773 llvm::cl::desc(
"Fail if there are warnings."),
3775static llvm::cl::opt<bool>
3777 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3779static llvm::cl::opt<std::string>
3781 llvm::cl::desc(
"Specify an isysroot."),
3783 llvm::cl::init(
"-"));
3784static llvm::cl::list<std::string>
3786 llvm::cl::desc(
"Specify an include path."),
3788static llvm::cl::list<std::string>
3790 llvm::cl::desc(
"Specify defined macros."),
3792static llvm::cl::list<std::string>
3794 llvm::cl::desc(
"Specify undefined macros."),
3796static llvm::cl::list<std::string>
3798 llvm::cl::desc(
"Specify compiler diagnostics options."),
3800static llvm::cl::list<std::string>
3802 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file>"),
3804static llvm::cl::list<std::string>
3806 llvm::cl::desc(
"Consumes all unrecognized options."),
3809static llvm::cl::SubCommand
3812static llvm::cl::list<std::string>
3814 llvm::cl::desc(
"Consumes options and sends them to cling."),
3824 std::vector<std::string> &missingHeaders)
3827 std::vector<clang::Module::Header> moduleHeaders;
3829 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3831 bool foundAllHeaders =
true;
3836 for (
const std::string &header : modGen.
GetHeaders()) {
3837 bool headerFound =
false;
3838 for (
const clang::Module::Header &moduleHeader : moduleHeaders) {
3839 if (header == moduleHeader.NameAsWritten) {
3845 missingHeaders.push_back(header);
3846 foundAllHeaders =
false;
3849 return foundAllHeaders;
3855 llvm::StringRef LinkdefPath,
const std::string &moduleName)
3857 clang::CompilerInstance *CI = interpreter.getCI();
3858 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3859 headerSearch.loadTopLevelSystemModules();
3862 clang::Module *module = headerSearch.lookupModule(llvm::StringRef(moduleName));
3867 moduleName.c_str());
3874 std::vector<std::string> missingHeaders;
3877 std::stringstream msgStream;
3878 msgStream <<
"warning: Couldn't find in "
3879 << module->PresumedModuleMapFile
3880 <<
" the following specified headers in "
3881 <<
"the module " << module->Name <<
":\n";
3882 for (
auto &
H : missingHeaders) {
3883 msgStream <<
" " <<
H <<
"\n";
3885 std::string warningMessage = msgStream.str();
3887 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3898 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3899 warningMessage.c_str(),
3908 module->Name.c_str());
3918 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
3919 moduleName.consume_front(
"lib");
3920 moduleName.consume_back(
".pcm");
3921 moduleName.consume_back(
"_rdict");
3929 bool isGenreflex =
false)
3932 auto &opts = llvm::cl::getRegisteredOptions();
3933 auto &optHelp = *opts[
"help"];
3934 llvm::cl::alias optHelpAlias1(
"h",
3935 llvm::cl::desc(
"Alias for -help"),
3936 llvm::cl::aliasopt(optHelp));
3937 llvm::cl::alias optHelpAlias2(
"?",
3938 llvm::cl::desc(
"Alias for -help"),
3939 llvm::cl::aliasopt(optHelp));
3945 const char *executableFileName = argv[0];
3947 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
3948 llvm::PrettyStackTraceProgram X(argc, argv);
3951#if defined(R__WIN32) && !defined(R__WINGCC)
3956 for (
int iic = 1 ; iic < argc; ++iic) {
3957 std::string iiarg(argv[iic]);
3959 size_t len = iiarg.length();
3961 char *argviic =
new char[len + 1];
3962 strlcpy(argviic, iiarg.c_str(), len + 1);
3963 argv[iic] = argviic;
3971 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
3975 std::vector<const char *> clingArgsC;
3976 clingArgsC.push_back(executableFileName);
3978 clingArgsC.push_back(
"-I");
3985 clingArgsC.push_back(Opt.c_str());
3987 auto interp = llvm::make_unique<cling::Interpreter>(clingArgsC.size(),
3989 llvmResourceDir.c_str());
3992 return interp->getDiagnostics().hasFatalErrorOccurred();
3995 std::string dictname;
4009 llvm::cl::PrintHelpMessage();
4024 if ((fp = fopen(filein.c_str(),
"r")) == 0) {
4025 ROOT::TMetaUtils::Error(0,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4052 ROOT::TMetaUtils::Error(0,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4053 llvm::cl::PrintHelpMessage();
4057 std::vector<std::string> clingArgs;
4058 clingArgs.push_back(executableFileName);
4059 clingArgs.push_back(
"-iquote.");
4065 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4071 if (GetErrorIgnoreLevel() >
kWarning)
4073 GetWarningsAreErrors() =
true;
4087 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4092 clingArgs.push_back(std::string(
"-D") + PPDefine);
4095 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4098 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4100 for (
const std::string &WDiag :
gOptWDiags) {
4101 const std::string FullWDiag = std::string(
"-W") + WDiag;
4105 clingArgs.push_back(FullWDiag);
4109 clingArgs.push_back(std::string(
"-I") + includeDir);
4111 std::vector<std::string> pcmArgs;
4112 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4113 auto thisArg = clingArgs[parg];
4115 if (thisArg ==
"-c" ||
4119 unsigned int offset = 2;
4120 char c = thisArg[offset];
4121 while (
c ==
' ')
c = thisArg[++offset];
4125 [&](
const std::string& path){
4126 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4127 if (excludePathsEnd != excludePathPos)
continue;
4129 pcmArgs.push_back(thisArg);
4136 clingArgs.push_back(
"-D__ROOTCLING__");
4139 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4140#elif defined(R__WIN32)
4141 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4144 clingArgs.push_back(
"-D_XKEYCHECK_H");
4146 clingArgs.push_back(
"-DNOMINMAX");
4148 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4151 clingArgs.push_back(
"-fsyntax-only");
4153 clingArgs.push_back(
"-fPIC");
4155 clingArgs.push_back(
"-Xclang");
4156 clingArgs.push_back(
"-fmodules-embed-all-files");
4157 clingArgs.push_back(
"-Xclang");
4158 clingArgs.push_back(
"-main-file-name");
4159 clingArgs.push_back(
"-Xclang");
4160 clingArgs.push_back((dictname +
".h").c_str());
4168 std::string outputFile;
4170 llvm::StringRef moduleName;
4175 auto clingArgsInterpreter = clingArgs;
4184 clingArgsInterpreter.push_back(
"-fmodules");
4185 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4188 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4190 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4192 "/module.modulemap");
4194 if (llvm::sys::fs::exists(ModuleMapCWD))
4195 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4202 clingArgsInterpreter.push_back(
"-fmodule-name");
4203 clingArgsInterpreter.push_back(moduleName.str());
4213 if (moduleName ==
"Core") {
4215 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4216 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4217 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4218 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4220 remove((moduleCachePath + llvm::sys::path::get_separator() +
"vcruntime.pcm").str().c_str());
4221 remove((moduleCachePath + llvm::sys::path::get_separator() +
"services.pcm").str().c_str());
4225 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4227 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4229 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4230 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4231 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4232 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4233 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4234 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4235 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4236 }
else if (moduleName ==
"MathCore") {
4237 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Vc.pcm").str().c_str());
4242 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4246 clingArgsInterpreter.push_back(
"-v");
4249 std::vector<const char *> clingArgsC;
4250 for (
auto const &clingArg : clingArgsInterpreter) {
4252 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4253 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4256 clingArgsC.push_back(clingArg.c_str());
4260 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4261 cling::Interpreter* interpPtr =
nullptr;
4263 std::list<std::string> filesIncludedByLinkdef;
4267 clingArgsC.push_back(
"-ffast-math");
4270 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4271 llvmResourceDir.c_str()));
4272 interpPtr = owningInterpPtr.get();
4275 clingArgsC.push_back(
"-resource-dir");
4276 clingArgsC.push_back(llvmResourceDir.c_str());
4277 clingArgsC.push_back(0);
4279 extraArgs = &clingArgsC[1];
4282 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4283 interpPtr->setCallbacks(std::move(callBacks));
4286 cling::Interpreter &interp = *interpPtr;
4287 clang::CompilerInstance *CI = interp.getCI();
4289 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4290 CI->getSourceManager().setAllFilesAreTransient(
true);
4292 clang::Preprocessor &PP = CI->getPreprocessor();
4293 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4294 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4295 auto &diags = interp.getDiagnostics();
4302 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4306 auto recordingClient =
new CheckModuleBuildClient(diags.getClient(), diags.ownsClient(), moduleMap);
4307 diags.setClient(recordingClient,
true);
4313 interp.DumpIncludePath();
4318 interp.printIncludedFiles(llvm::outs());
4319 llvm::outs() <<
"\n\n";
4320 llvm::outs().flush();
4323 const clang::LangOptions& LangOpts
4324 = interp.getCI()->getASTContext().getLangOpts();
4325#define LANGOPT(Name, Bits, Default, Description) \
4326 ROOT::TMetaUtils::Info(0, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4327#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4328#include "clang/Basic/LangOptions.def"
4332 interp.getOptions().ErrorOut =
true;
4333 interp.enableRawInput(
true);
4337 if (DepMod.endswith(
"_rdict.pcm")) {
4344 cling::Interpreter::PushTransactionRAII RAII(&interp);
4345 if (!interp.loadModule(DepMod,
false)) {
4354 if (interp.declare(
"#include <assert.h>\n"
4355 "#include \"Rtypes.h\"\n"
4356 "#include \"TObject.h\"") != cling::Interpreter::kSuccess
4364 if (interp.declare(
"#include <string>\n"
4365 "#include <RtypesCore.h>\n"
4366 "namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4377 clingArgs.push_back(
"-D__CINT__");
4378 clingArgs.push_back(
"-D__MAKECINT__");
4384 std::string interpPragmaSource;
4385 std::string includeForSource;
4386 std::string interpreterDeclarations;
4387 std::string linkdef;
4393 if (isSelectionFile) {
4395 linkdef = optHeaderFileName;
4398 executableFileName, optHeaderFileName.c_str());
4404 std::string fullheader(optHeaderFileName);
4407 if (fullheader[fullheader.length() - 1] ==
'+') {
4408 fullheader.erase(fullheader.length() - 1);
4413 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4414 if (!isSelectionFile) {
4422 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4423 pcmArgs.push_back(header);
4425 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4430 bool hasSelectionFile = !linkdef.empty();
4431 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4442 if (!newName.empty())
4455 string incCurDir =
"-I";
4456 incCurDir += currentDirectory;
4457 pcmArgs.push_back(incCurDir);
4462 std::stringstream res;
4463 const char* delim=
"\n";
4464 std::copy(diagnosticPragmas.begin(),
4465 diagnosticPragmas.end(),
4466 std::ostream_iterator<std::string>(res, delim));
4467 if (interp.declare(res.str()) != cling::Interpreter::kSuccess) {
4473 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4475 IgnoringPragmaHandler(
const char* pragma):
4476 clang::PragmaNamespace(pragma) {}
4477 void HandlePragma(clang::Preprocessor &PP,
4478 clang::PragmaIntroducer Introducer,
4479 clang::Token &tok) {
4480 PP.DiscardUntilEndOfDirective();
4486 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4487 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4488 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4489 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4491 if (!interpreterDeclarations.empty() &&
4492 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4504 pcmArgs.push_back(linkdef);
4512 interp.AddIncludePath(inclPath);
4514 std::stringstream definesUndefinesStr;
4517 if (!definesUndefinesStr.str().empty()) {
4518 if (interp.declare(definesUndefinesStr.str()) != cling::Interpreter::kSuccess) {
4519 ROOT::TMetaUtils::Error(0,
"Failed to parse -D, -U flags as preprocessor directives:\n%s", definesUndefinesStr.str().c_str());
4530 if (linkdef.empty()) {
4536 std::ofstream fileout;
4538 std::ostream *splitDictStream =
nullptr;
4539 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4541 tempFileNamesCatalog tmpCatalog;
4561 splitDeleter.reset(splitDictStream);
4563 splitDictStream = &dictStream;
4566 size_t dh = main_dictname.rfind(
'.');
4567 if (dh != std::string::npos) {
4568 main_dictname.erase(dh);
4571 std::string main_dictname_copy(main_dictname);
4593 string linkdefFilename;
4594 if (linkdef.empty()) {
4595 linkdefFilename =
"in memory";
4597 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4605 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4611 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4613 std::string extraIncludes;
4618 const unsigned int selRulesInitialSize = selectionRules.
Size();
4622 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4626 int rootclingRetCode(0);
4628 if (linkdef.empty()) {
4633 clingArgs.push_back(
"-Ietc/cling/cint");
4635 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4636 llvmResourceDir.c_str())) {
4638 rootclingRetCode += 1;
4648 }
else if (isSelXML) {
4652 std::ifstream
file(linkdefFilename.c_str());
4653 if (
file.is_open()) {
4657 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4670 std::ifstream
file(linkdefFilename.c_str());
4671 if (
file.is_open()) {
4681 clingArgs.push_back(
"-Ietc/cling/cint");
4683 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4684 llvmResourceDir.c_str())) {
4686 rootclingRetCode += 1;
4721 dictStream <<
"#include \"TBuffer.h\"\n"
4722 <<
"#include \"TVirtualObject.h\"\n"
4723 <<
"#include <vector>\n"
4724 <<
"#include \"TSchemaHelper.h\"\n\n";
4726 std::list<std::string> includes;
4728 for (
auto & incFile : includes) {
4729 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4731 dictStream << std::endl;
4736 int scannerVerbLevel = 0;
4739 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4741 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4764 scan.
Scan(CI->getASTContext());
4766 bool has_input_error =
false;
4773 !dictSelRulesPresent &&
4780 if (rootclingRetCode)
return rootclingRetCode;
4787 if (annRcd.RequestNoInputOperator()) {
4799 if (has_input_error) {
4809 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4810 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4838 constructorTypes.emplace_back(
"TRootIOCtor", interp);
4839 constructorTypes.emplace_back(
"__void__", interp);
4840 constructorTypes.emplace_back(
"", interp);
4870 if (rootclingRetCode != 0) {
4871 return rootclingRetCode;
4890 std::string detectedUmbrella;
4891 for (
auto & arg : pcmArgs) {
4893 detectedUmbrella = arg;
4899 headersDeclsMap.clear();
4903 std::string headersClassesMapString =
"\"\"";
4904 std::string fwdDeclsString =
"\"\"";
4920 if (modGen.
IsPCH()) {
4923 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
4933 ofstream outputfile(liblist_filename.c_str(), ios::out);
4936 executableFileName, liblist_filename.c_str());
4938 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4939 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4941 outputfile <<
"# Now the list of classes\n";
4946 outputfile << annRcd.GetNormalizedName() << endl;
4953 if (0 != rootclingRetCode)
return rootclingRetCode;
4959 [](
const std::string &
a,
const std::string &
b) -> std::string {
4960 if (a.empty()) return b;
4961 else return a +
" " + b;
4966 std::list<std::string> classesNames;
4967 std::list<std::string> classesNamesForRootmap;
4968 std::list<std::string> classesDefsList;
4972 classesNamesForRootmap,
4976 std::list<std::string> enumNames;
4981 std::list<std::string> varNames;
4986 if (0 != rootclingRetCode)
return rootclingRetCode;
4989 if (rootMapNeeded) {
4991 std::list<std::string> nsNames;
5000 rootmapLibName.c_str());
5003 std::unordered_set<std::string> headersToIgnore;
5006 headersToIgnore.insert(optHeaderFileName.c_str());
5008 std::list<std::string> typedefsRootmapLines;
5016 classesNamesForRootmap,
5018 typedefsRootmapLines,
5024 if (0 != rootclingRetCode)
return 1;
5034 cling::Interpreter::PushTransactionRAII RAII(&interp);
5035 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5046 if(rootclingRetCode == 0) {
5047 rootclingRetCode += tmpCatalog.commit();
5052 return rootclingRetCode;
5063 unsigned int numberOfHeaders = 0;
5064 for (std::vector<std::string>::iterator it = headersNames.begin();
5065 it != headersNames.end(); ++it) {
5066 const std::string headername(*it);
5071 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5072 headername.c_str());
5075 return numberOfHeaders;
5081 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5084 unsigned int argvCounter = 0;
5085 for (
int i = 1; i < argc; ++i) {
5088 args.push_back(argv[i]);
5090 }
else if (argvCounter) {
5091 argv[i - argvCounter] = argv[i];
5098 std::cout <<
"Args: \n";
5099 for (std::vector<std::string>::iterator it = args.begin();
5100 it < args.end(); ++it) {
5101 std::cout << i <<
") " << *it << std::endl;
5114 size_t result = filename.find_last_of(
'.');
5115 if (std::string::npos != result) {
5116 filename.erase(result);
5117 filename.append(newExtension);
5127 const unsigned int size(str.size());
5128 char *
a =
new char[size + 1];
5130 memcpy(
a, str.c_str(), size);
5146 std::vector<std::string> &ofilesnames)
5148 ofilesnames.reserve(headersNames.size());
5150 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5151 it != headersNames.end(); ++it) {
5152 std::string ofilename(*it);
5154 ofilesnames.push_back(ofilename);
5161 const std::vector<std::string> &argsToBeAdded,
5162 const std::string &optName =
"")
5164 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5165 it != argsToBeAdded.end(); ++it) {
5173 const std::vector<std::string> &argsToBeAdded,
5174 const std::string &optName =
"")
5176 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5177 it != argsToBeAdded.end(); ++it) {
5178 if (optName.length()) {
5188 const std::string &selectionFileName,
5189 const std::string &targetLibName,
5191 const std::vector<std::string> &pcmsNames,
5192 const std::vector<std::string> &includes,
5193 const std::vector<std::string> &preprocDefines,
5194 const std::vector<std::string> &preprocUndefines,
5195 const std::vector<std::string> &warnings,
5196 const std::string &rootmapFileName,
5197 const std::string &rootmapLibName,
5198 bool interpreteronly,
5201 bool writeEmptyRootPCM,
5203 bool noIncludePaths,
5204 bool noGlobalUsingStd,
5205 const std::vector<std::string> &headersNames,
5206 bool failOnWarnings,
5207 const std::string &ofilename)
5211 std::vector<char *> argvVector;
5222 std::string dictLocation;
5228 std::string newRootmapLibName(rootmapLibName);
5229 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5230 if (headersNames.size() != 1) {
5232 "*** genreflex: No rootmap lib and several header specified!\n");
5235 newRootmapLibName =
"lib";
5236 newRootmapLibName += cleanHeaderName;
5242 std::string newRootmapFileName(rootmapFileName);
5243 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5244 newRootmapFileName = dictLocation + newRootmapFileName;
5249 if (!newRootmapFileName.empty()) {
5255 if (!newRootmapLibName.empty()) {
5261 if (interpreteronly)
5269 if (!targetLibName.empty()) {
5279 if (noGlobalUsingStd)
5289 if (writeEmptyRootPCM)
5312 if (!selectionFileName.empty()) {
5316 const int argc = argvVector.size();
5320 std::cout <<
"Rootcling commandline:\n";
5321 for (
int i = 0; i < argc; i++)
5322 std::cout << i <<
") " << argvVector[i] << std::endl;
5325 char **argv = & (argvVector[0]);
5330 for (
int i = 0; i < argc; i++)
5331 delete [] argvVector[i];
5333 return rootclingReturnCode;
5342 const std::string &selectionFileName,
5343 const std::string &targetLibName,
5345 const std::vector<std::string> &pcmsNames,
5346 const std::vector<std::string> &includes,
5347 const std::vector<std::string> &preprocDefines,
5348 const std::vector<std::string> &preprocUndefines,
5349 const std::vector<std::string> &warnings,
5350 const std::string &rootmapFileName,
5351 const std::string &rootmapLibName,
5352 bool interpreteronly,
5355 bool writeEmptyRootPCM,
5357 bool noIncludePaths,
5358 bool noGlobalUsingStd,
5359 const std::vector<std::string> &headersNames,
5360 bool failOnWarnings,
5361 const std::string &outputDirName_const =
"")
5363 std::string outputDirName(outputDirName_const);
5365 std::vector<std::string> ofilesNames;
5372 std::vector<std::string> namesSingleton(1);
5373 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5374 namesSingleton[0] = headersNames[i];
5375 std::string ofilenameFullPath(ofilesNames[i]);
5376 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5377 ofilenameFullPath = outputDirName + ofilenameFullPath;
5399 if (returnCode != 0)
5414 std::vector<std::string> &values)
5417 if (options[oIndex]) {
5418 const int nVals = options[oIndex].count();
5419 values.reserve(nVals);
5420 int optionIndex = 0;
5423 << optionIndex <<
"/" << nVals <<
" "
5424 << opt->arg << std::endl;
5426 values.push_back(opt->arg);
5437 const char *descriptor)
5439 if (options[optionIndex]) {
5441 "*** genereflex: %s is not supported anymore.\n",
5498 enum optionIndex { UNKNOWN,
5529 enum optionTypes { NOTYPE, STRING } ;
5532 const char *genreflexUsage =
5533 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5534 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5537 const char *selectionFilenameUsage =
5538 "-s, --selection_file\tSelection filename\n"
5539 " Class selection file to specify for which classes the dictionary\n"
5540 " will be generated. The final set can be crafted with exclusion and\n"
5541 " exclusion rules.\n"
5542 " Properties can be specified. Some have special meaning:\n"
5543 " - name [string] name of the entity to select with an exact matching\n"
5544 " - pattern [string] name with wildcards (*) to select entities\n"
5545 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5546 " file where the C++ entities reside and not to C++ entities themselves.\n"
5547 " - transient/persistent [string: true/false] The fields to which they are\n"
5548 " applied will not be persistified if requested.\n"
5549 " - comment [string]: what you could write in code after an inline comment\n"
5550 " without \"//\". For example comment=\"!\" or \"||\".\n"
5551 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5552 " Default value is 'false'\n"
5553 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5554 " to 'true'. Default value is 'false'\n"
5558 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5559 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5560 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5561 " [noInputOperator=\"true/false\"] />\n"
5562 " <class name=\"classname\" >\n"
5563 " <field name=\"m_transient\" transient=\"true\"/>\n"
5564 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5565 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5566 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5568 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5569 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5570 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5573 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5574 " <method name=\"unwanted\" />\n"
5579 " If no selection file is specified, the class with the filename without\n"
5580 " extension will be selected, i.e. myClass.h as argument without any\n"
5581 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5583 const char *outputFilenameUsage =
5584 "-o, --output\tOutput filename\n"
5585 " Output file name. If an existing directory is specified instead of a file,\n"
5586 " then a filename will be build using the name of the input file and will\n"
5587 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5588 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5589 " have unique names.\n";
5592 const char *targetLib =
5593 "-l, --library\tTarget library\n"
5594 " The flag -l must be followed by the name of the library that will\n"
5595 " contain the object file corresponding to the dictionary produced by\n"
5596 " this invocation of genreflex.\n"
5597 " The name takes priority over the one specified for the rootmapfile.\n"
5598 " The name influences the name of the created pcm:\n"
5599 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5600 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5601 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5602 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5603 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5605 const char *rootmapUsage =
5606 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5607 " This file lists the autoload keys. For example classes for which the\n"
5608 " reflection information is provided.\n"
5609 " The format of the rootmap is the following:\n"
5610 " - Forward declarations section\n"
5611 " - Libraries sections\n"
5612 " Rootmaps can be concatenated together, for example with the cat util.\n"
5613 " In order for ROOT to pick up the information in the rootmaps, they\n"
5614 " have to be located in the library path and have the .rootmap extension.\n"
5615 " An example rootmap file could be:\n"
5617 " template <class T> class A;\n"
5618 " [ libMyLib.so ]\n"
5619 " class A<double>\n"
5624 const char *rootmapLibUsage =
5625 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5658 "--multiDict\tSupport for many dictionaries in one library\n"
5659 " Form correct pcm names if multiple dictionaries will be in the same\n"
5660 " library (needs target library switch. See its documentation).\n"
5667 "" ,
"noGlobalUsingStd" ,
5669 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5670 " All header files must have sumbols from std:: namespace fully qualified\n"
5676 "s" ,
"selection_file" ,
5678 selectionFilenameUsage
5692 "" ,
"rootmap-lib" ,
5700 "" ,
"interpreteronly",
5702 "--interpreteronly\tDo not generate I/O related information.\n"
5703 " Generate minimal dictionary required for interactivity.\n"
5711 "--split\tSplit the dictionary\n"
5712 " Split in two the dictionary, isolating the part with\n"
5713 " ClassDef related functions in a separate file.\n"
5721 "-m \tPcm file loaded before any header (option can be repeated).\n"
5729 "-v, --verbose\tPrint some debug information.\n"
5737 "--debug\tPrint all debug information.\n"
5745 "--quiet\tPrint only warnings and errors (default).\n"
5753 "--silent\tPrint no information at all.\n"
5759 "" ,
"writeEmptyPCM",
5761 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5769 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5778 "--help\tPrint usage and exit.\n"
5784 "",
"fail_on_warnings",
5786 "--fail_on_warnings\tFail on warnings and errors.\n"
5792 "",
"selSyntaxOnly",
5794 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5800 "" ,
"noIncludePaths",
5802 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5841 "" ,
"no_membertypedefs" ,
5849 "" ,
"no_templatetypedefs" ,
5857 std::vector<std::string> headersNames;
5858 const int originalArgc = argc;
5860 const int extractedArgs = extractArgs(argc, argv, headersNames);
5862 const int offset = 1;
5863 argc -= offset + extractedArgs;
5868 std::vector<ROOT::option::Option> options(stats.
options_max);
5869 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5875 if (parse.
error()) {
5881 if (options[HELP] || originalArgc == 1) {
5886 int numberOfHeaders = checkHeadersNames(headersNames);
5887 if (0 == numberOfHeaders) {
5898 std::string verbosityOption(
"-v2");
5899 if (options[SILENT]) verbosityOption =
"-v0";
5900 if (options[
VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5901 if (options[
DEBUG]) verbosityOption =
"-v4";
5906 std::string selectionFileName;
5907 if (options[SELECTIONFILENAME]) {
5908 selectionFileName = options[SELECTIONFILENAME].arg;
5911 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
5912 selectionFileName.c_str());
5927 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
5928 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
5931 std::string targetLibName;
5932 if (options[TARGETLIB]) {
5933 targetLibName = options[TARGETLIB].arg;
5936 "Invalid target library extension: filename is %s and extension %s is expected!\n",
5937 targetLibName.c_str(),
5941 if (options[ROOTMAP]) {
5946 bool isCxxmodule = options[CXXMODULE];
5948 bool multidict =
false;
5949 if (options[MULTIDICT]) multidict =
true;
5951 bool noGlobalUsingStd =
false;
5952 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
5954 if (multidict && targetLibName.empty()) {
5956 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
5960 bool interpreteronly =
false;
5961 if (options[INTERPRETERONLY])
5962 interpreteronly =
true;
5964 bool doSplit =
false;
5968 bool writeEmptyRootPCM =
false;
5969 if (options[WRITEEMPTYROOTPCM])
5970 writeEmptyRootPCM =
true;
5972 bool selSyntaxOnly =
false;
5973 if (options[SELSYNTAXONLY]) {
5974 selSyntaxOnly =
true;
5977 bool noIncludePaths =
false;
5978 if (options[NOINCLUDEPATHS]) {
5979 noIncludePaths =
true;
5982 bool failOnWarnings =
false;
5983 if (options[FAILONWARNINGS]) {
5984 failOnWarnings =
true;
5993 std::vector<std::string> pcmsNames;
5997 std::vector<std::string> preprocDefines;
6001 std::vector<std::string> preprocUndefines;
6005 std::vector<std::string> includes;
6009 std::vector<std::string> warnings;
6020 int returnValue = 0;
6021 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6025 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6026 returnValue = invokeRootCling(verbosityOption,
6049 returnValue = invokeManyRootCling(verbosityOption,
6082 assert(!
gDriverConfig &&
"Driver configuration already set!");
6102 if (std::string::npos != exeName.find(
"genreflex"))
Select classes and assign properties using C++ syntax.
The file contains utilities which are foundational and could be used across the core component of ROO...
This is the only file required to use The Lean Mean C++ Option Parser.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
const AttributesMap_t & GetAttributes() const
std::unordered_map< std::string, std::string > AttributesMap_t
const std::list< VariableSelectionRule > & GetFieldSelectionRules() const
bool LoadIncludes(std::string &extraInclude)
bool Parse(SelectionRules &sr, llvm::StringRef code, const std::vector< std::string > &parserArgs, const char *llvmdir)
void GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlClass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
void WriteClassInit(std::ostream &strm, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const ROOT::TMetaUtils::RConstructorTypes &, bool &needCollectionProxy, void(*emitStreamerInfo)(const char *))
void WriteUmbrellaHeader(std::ostream &out) const
Write a header file pulling in the content of this module through a series of #defined,...
const std::string & GetUmbrellaName() const
const std::vector< std::string > & GetIncludePaths() const
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes, bool hasCxxModule) const
const std::vector< std::string > & GetHeaders() const
void WriteContentHeader(std::ostream &out) const
Write a header file describing the content of this module through a series of variables inside the na...
int GetErrorCount() const
const std::string & GetModuleFileName() const
std::ostream & WritePPUndefines(std::ostream &out) const
Write #ifdef FOO.
void ParseArgs(const std::vector< std::string > &args)
Parse -I -D -U headers.h SomethingLinkdef.h.
const std::string & GetContentName() const
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO.
A parsed option from the command line together with its argument if it has one.
Option * next()
Returns a pointer to the next element of the linked list or NULL if called on last().
Checks argument vectors for validity and parses them into data structures that are easier to work wit...
bool error()
Returns true if an unrecoverable error occurred while parsing options.
void Scan(const clang::ASTContext &C)
std::vector< ROOT::TMetaUtils::AnnotatedRecordDecl > ClassColl_t
const DeclsSelRulesMap_t & GetDeclsSelRulesMap() const
FunctionColl_t fSelectedFunctions
std::vector< const clang::FunctionDecl * > FunctionColl_t
NamespaceColl_t fSelectedNamespaces
TypedefColl_t fSelectedTypedefs
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
std::map< const clang::Decl *, const BaseSelectionRule * > DeclsSelRulesMap_t
EnumColl_t fSelectedEnums
std::vector< const clang::TypedefNameDecl * > TypedefColl_t
std::vector< const clang::VarDecl * > VariableColl_t
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
VariableColl_t fSelectedVariables
std::vector< const clang::EnumDecl * > EnumColl_t
ClassColl_t fSelectedClasses
RooAbsArg * find(const char *name) const
Find object with given name in list.
The class representing the collection of selection rules.
bool AreAllSelectionRulesUsed() const
bool SearchNames(cling::Interpreter &interp)
void PrintSelectionRules() const
unsigned int Size() const
void SetSelectionFileType(ESelectionFileTypes fileType)
bool Parse(const std::string &fileName, SelectionRules &out)
static bool FromCygToNativePath(std::string &path)
std::string GetCurrentDir()
std::string MakePathRelative(const std::string &path, const std::string &base, bool isBuildingROOT=false)
void printUsage(OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN SchemaRuleClassMap_t gReadRules
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
R__EXTERN SchemaRuleClassMap_t gReadRawRules
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
void Init(TClassEdit::TInterpreterLookupHelper *helper)
void header2outputName(std::string &fileName)
Replace the extension with "_rflx.cpp".
void AddToArgVectorSplit(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
void changeExtension(std::string &filename, const std::string &newExtension)
int invokeRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &ofilename)
int invokeManyRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &outputDirName_const="")
Get the right ofilenames and invoke several times rootcling One invokation per header.
unsigned int checkHeadersNames(std::vector< std::string > &headersNames)
Loop on arguments: stop at the first which starts with -.
void headers2outputsNames(const std::vector< std::string > &headersNames, std::vector< std::string > &ofilesnames)
Get a proper name for the output file.
char * string2charptr(const std::string &str)
The caller is responsible for deleting the string!
unsigned int extractArgs(int argc, char **argv, std::vector< std::string > &args)
Extract the arguments from the command line.
void AddToArgVector(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
int FinalizeStreamerInfoWriting(cling::Interpreter &interp, bool writeEmptyRootPCM=false)
Make up for skipping RegisterModule, now that dictionary parsing is done and these headers cannot be ...
std::list< std::string > CollapseIdenticalNamespaces(const std::list< std::string > &fwdDeclarationsList)
If two identical namespaces are there, just declare one only Example: namespace A { namespace B { fwd...
bool ParsePragmaLine(const std::string &line, const char *expectedTokens[], size_t *end=0)
Check whether the #pragma line contains expectedTokens (0-terminated array).
static llvm::cl::opt< bool > gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
int RootClingMain(int argc, char **argv, bool isGenreflex=false)
static llvm::StringRef GetModuleNameFromRdictName(llvm::StringRef rdictName)
static llvm::cl::opt< bool > gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), llvm::cl::cat(gRootclingOptions), llvm::cl::init("-"))
int STLContainerStreamer(const clang::FieldDecl &m, int rwmode, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
Create Streamer code for an STL container.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static llvm::cl::opt< bool > gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
static llvm::cl::list< std::string > gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), llvm::cl::cat(gRootclingOptions))
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
static void MaybeSuppressWin32CrashDialogs()
void RecordDeclCallback(const clang::RecordDecl *recordDecl)
void CheckClassNameForRootMap(const std::string &classname, map< string, string > &autoloads)
bool Which(cling::Interpreter &interp, const char *fname, string &pname)
Find file name in path specified via -I statements to Cling.
void AdjustRootMapNames(std::string &rootmapFileName, std::string &rootmapLibName)
void AddNamespaceSTDdeclaration(std::ostream &dictStream)
static llvm::cl::list< std::string > gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptModuleByproducts("mByproduct", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("The list of the expected implicit modules build as part of building the current module."), llvm::cl::cat(gRootclingOptions))
map< string, string > gAutoloads
static llvm::cl::opt< bool > gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), llvm::cl::cat(gRootclingOptions))
static bool CheckModuleValid(TModuleGenerator &modGen, const std::string &resourceDir, cling::Interpreter &interpreter, llvm::StringRef LinkdefPath, const std::string &moduleName)
Check moduleName validity from modulemap. Check if this module is defined or not.
static void CheckForMinusW(std::string arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
static bool WriteAST(llvm::StringRef fileName, clang::CompilerInstance *compilerInstance, llvm::StringRef iSysRoot, clang::Module *module=nullptr)
Write the AST of the given CompilerInstance to the given File while respecting the given isysroot.
static llvm::cl::opt< bool > gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), llvm::cl::cat(gRootclingOptions))
void ExtractFilePath(const std::string &path, std::string &dirname)
Extract the path from a fullpath finding the last \ or / according to the content in gPathSeparator.
int STLStringStreamer(const clang::FieldDecl &m, int rwmode, std::ostream &dictStream)
Create Streamer code for a standard string object.
void CreateDictHeader(std::ostream &dictStream, const std::string &main_dictname)
const char * GetExePath()
Returns the executable path name, used e.g. by SetRootSys().
const std::string gPathSeparator(ROOT::TMetaUtils::GetPathSeparator())
static llvm::cl::list< std::string > gOptBareClingSink(llvm::cl::OneOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes options and sends them to cling."), llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gBareClingSubcommand))
bool InheritsFromTObject(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static bool InjectModuleUtilHeader(const char *argv0, TModuleGenerator &modGen, cling::Interpreter &interp, bool umbrella)
Write the extra header injected into the module: umbrella header if (umbrella) else content header.
static llvm::cl::list< std::string > gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), llvm::cl::cat(gRootclingOptions))
int ExtractClassesListAndDeclLines(RScanner &scan, std::list< std::string > &classesList, std::list< std::string > &classesListForRootmap, std::list< std::string > &fwdDeclarationsList, const cling::Interpreter &interpreter)
void ParseRootMapFileNewFormat(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map, using the new format.
static llvm::cl::OptionCategory gRootclingOptions("rootcling common options")
void ExtractHeadersForDecls(const RScanner::ClassColl_t &annotatedRcds, const RScanner::TypedefColl_t tDefDecls, const RScanner::FunctionColl_t funcDecls, const RScanner::VariableColl_t varDecls, const RScanner::EnumColl_t enumDecls, HeadersDeclsMap_t &headersClassesMap, HeadersDeclsMap_t &headersDeclsMap, const cling::Interpreter &interp)
static llvm::cl::opt< bool > gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static bool GenerateAllDict(TModuleGenerator &modGen, clang::CompilerInstance *compilerInstance, const std::string ¤tDirectory)
Generates a PCH from the given ModuleGenerator and CompilerInstance.
void LoadLibraryMap(const std::string &fileListName, map< string, string > &autoloads)
Fill the map of libraries to be loaded in presence of a class Transparently support the old and new r...
std::ostream * CreateStreamPtrForSplitDict(const std::string &dictpathname, tempFileNamesCatalog &tmpCatalog)
Transform name of dictionary.
void WriteNamespaceInit(const clang::NamespaceDecl *cl, cling::Interpreter &interp, std::ostream &dictStream)
Write the code to initialize the namespace name and the initialization object.
void AnnotateAllDeclsForPCH(cling::Interpreter &interp, RScanner &scan)
We need annotations even in the PCH: // !, // || etc.
size_t GetFullArrayLength(const clang::ConstantArrayType *arrayType)
static llvm::cl::opt< bool > gOptSplit("split", llvm::cl::desc("Split the dictionary into two parts: one containing the IO (ClassDef)\
information and another the interactivity support."), llvm::cl::cat(gRootclingOptions))
bool ProcessAndAppendIfNotThere(const std::string &el, std::list< std::string > &el_list, std::unordered_set< std::string > &el_set)
Separate multiline strings.
static llvm::cl::opt< bool > gOptNoGlobalUsingStd("noGlobalUsingStd", llvm::cl::desc("Do not declare {using namespace std} in dictionary global scope."), llvm::cl::cat(gRootclingOptions))
const ROOT::Internal::RootCling::DriverConfig * gDriverConfig
static llvm::cl::list< std::string > gOptModuleDependencies("m", llvm::cl::desc("The list of dependent modules of the dictionary."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::SubCommand gBareClingSubcommand("bare-cling", "Call directly cling and exit.")
static llvm::cl::opt< bool > gOptInterpreterOnly("interpreteronly", llvm::cl::desc("Generate minimal dictionary for interactivity (without IO information)."), llvm::cl::cat(gRootclingOptions))
void WriteArrayDimensions(const clang::QualType &type, std::ostream &dictStream)
Write "[0]" for all but the 1st dimension.
void GetMostExternalEnclosingClassName(const clang::DeclContext &theContext, std::string &ctxtName, const cling::Interpreter &interpreter, bool treatParent=true)
Extract the proper autoload key for nested classes The routine does not erase the name,...
std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, cling::Interpreter &interp)
int ExtractAutoloadKeys(std::list< std::string > &names, const COLL &decls, const cling::Interpreter &interp)
static llvm::cl::opt< std::string > gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), llvm::cl::cat(gRootclingOptions))
int GenerateFullDict(std::ostream &dictStream, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool writeEmptyRootPCM)
void WriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
void GetMostExternalEnclosingClassNameFromDecl(const clang::Decl &theDecl, std::string &ctxtName, const cling::Interpreter &interpreter)
static llvm::cl::opt< bool > gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void SetRootSys()
Set the ROOTSYS env var based on the executable location.
bool CheckInputOperator(const char *what, const char *proto, const string &fullname, const clang::RecordDecl *cl, cling::Interpreter &interp)
Check if the specified operator (what) has been properly declared if the user has requested a custom ...
void GenerateNecessaryIncludes(std::ostream &dictStream, const std::string &includeForSource, const std::string &extraIncludes)
void StrcpyArg(string &dest, const char *original)
Copy the command line argument, stripping MODULE/inc if necessary.
static llvm::cl::list< std::string > gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), llvm::cl::cat(gRootclingOptions))
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
static llvm::cl::opt< bool > gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), llvm::cl::cat(gRootclingOptions))
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
static std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
static llvm::cl::opt< bool > gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), llvm::cl::cat(gRootclingOptions))
const char * CopyArg(const char *original)
If the argument starts with MODULE/inc, strip it to make it the name we can use in #includes.
string GetNonConstMemberName(const clang::FieldDecl &m, const string &prefix="")
Return the name of the data member so that it can be used by non-const operation (so it includes a co...
static llvm::cl::list< std::string > gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), llvm::cl::cat(gRootclingOptions))
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
void ExtractSelectedNamespaces(RScanner &scan, std::list< std::string > &nsList)
Loop on selected classes and put them in a list.
static bool IncludeHeaders(const std::vector< std::string > &headers, cling::Interpreter &interpreter)
Includes all given headers in the interpreter.
clang::QualType GetPointeeTypeIfPossible(const clang::QualType &qt)
Get the pointee type if possible.
void AnnotateDecl(clang::CXXRecordDecl &CXXRD, const RScanner::DeclsSelRulesMap_t &declSelRulesMap, cling::Interpreter &interpreter, bool isGenreflex)
static llvm::cl::opt< VerboseLevel > gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), llvm::cl::values(clEnumVal(v, "Show errors."), clEnumVal(v0, "Show only fatal errors."), clEnumVal(v1, "Show errors (the same as -v)."), clEnumVal(v2, "Show warnings (default)."), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), llvm::cl::cat(gRootclingOptions))
void GenerateLinkdef(llvm::cl::list< std::string > &InputFiles, std::string &code_for_parser)
static llvm::cl::opt< std::string > gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::Required, llvm::cl::desc("<output dictionary file>"), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include <header> but expands the header content."), llvm::cl::cat(gRootclingOptions))
bool isPointerToPointer(const clang::FieldDecl &m)
int CreateNewRootMapFile(const std::string &rootmapFileName, const std::string &rootmapLibName, const std::list< std::string > &classesDefsList, const std::list< std::string > &classesNames, const std::list< std::string > &nsNames, const std::list< std::string > &tdNames, const std::list< std::string > &enNames, const std::list< std::string > &varNames, const HeadersDeclsMap_t &headersClassesMap, const std::unordered_set< std::string > headersToIgnore)
Generate a rootmap file in the new format, like { decls } namespace A { namespace B { template <typen...
bool IsSelectionXml(const char *filename)
bool IsGoodLibraryName(const std::string &name)
static llvm::cl::opt< bool > gOptReflex("reflex", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::OneOrMore, llvm::cl::desc("<list of dictionary header files> <LinkDef file>"), llvm::cl::cat(gRootclingOptions))
bool IsSelectionFile(const char *filename)
const std::string GenerateStringFromHeadersForClasses(const HeadersDeclsMap_t &headersClassesMap, const std::string &detectedUmbrella, bool payLoadOnly=false)
Generate a string for the dictionary from the headers-classes map.
bool IsSupportedClassName(const char *name)
static bool ModuleContainsHeaders(TModuleGenerator &modGen, clang::Module *module, std::vector< std::string > &missingHeaders)
Returns true iff a given module (and its submodules) contains all headers needed by the given ModuleG...
static llvm::cl::opt< bool > gOptIgnoreExistingDict("r", llvm::cl::desc("Deprecated. Similar to -f but it ignores the dictionary generation. \
When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptForce("f", llvm::cl::desc("Overwrite <file>s."), llvm::cl::cat(gRootclingOptions))
static void AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules)
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
static llvm::cl::list< std::string > gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), llvm::cl::cat(gRootclingOptions))
int CheckClassesForInterpreterOnlyDicts(cling::Interpreter &interp, RScanner &scan)
bool InheritsFromTSelector(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static void EmitTypedefs(const std::vector< const clang::TypedefNameDecl * > &tdvec)
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
bool Namespace__HasMethod(const clang::NamespaceDecl *cl, const char *name, const cling::Interpreter &interp)
static llvm::cl::list< std::string > gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), llvm::cl::cat(gRootclingOptions))
bool IsCorrectClingArgument(const std::string &argument)
Check if the argument is a sane cling argument.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)
void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream &dictStream, bool autoLoad=false)
Write the code to set the class name and the initialization object.
static llvm::cl::list< std::string > gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the <path> in the dictionary."), llvm::cl::cat(gRootclingOptions))
std::list< std::string > RecordDecl2Headers(const clang::CXXRecordDecl &rcd, const cling::Interpreter &interp, std::set< const clang::CXXRecordDecl * > &visitedDecls)
Extract the list of headers necessary for the Decl.
void EmitStreamerInfo(const char *normName)
static llvm::cl::opt< bool > gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), llvm::cl::cat(gRootclingOptions))
bool HasPath(const std::string &name)
Check if file has a path.
static llvm::cl::opt< std::string > gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), llvm::cl::cat(gRootclingOptions))
int CheckForUnsupportedClasses(const RScanner::ClassColl_t &annotatedRcds)
Check if the list of selected classes contains any class which is not supported.
llvm::StringRef GrabIndex(const clang::FieldDecl &member, int printError)
GrabIndex returns a static string (so use it or copy it immediately, do not call GrabIndex twice in t...
static void EmitEnums(const std::vector< const clang::EnumDecl * > &enumvec)
bool CheckClassDef(const clang::RecordDecl &cl, const cling::Interpreter &interp)
Return false if the class does not have ClassDef even-though it should.
bool NeedsSelection(const char *name)
int extractMultipleOptions(std::vector< ROOT::option::Option > &options, int oIndex, std::vector< std::string > &values)
Extract from options multiple values with the same option.
R__DLLEXPORT int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
cling::Interpreter *(* fTCling__GetInterpreter)()
bool(* fCloseStreamerInfoROOTFile)(bool writeEmptyRootPCM)
void(* fAddEnumToROOTFile)(const char *tdname)
void(* fInitializeStreamerInfoROOTFile)(const char *filename)
const char *(* fTROOT__GetIncludeDir)()
void(* fAddTypedefToROOTFile)(const char *tdname)
const char *(* fTROOT__GetEtcDir)()
void(* fAddStreamerInfoToROOTFile)(const char *normName)
const char ***(* fTROOT__GetExtraInterpreterArgs)()
static ArgStatus None(const Option &, bool)
For options that don't take an argument: Returns ARG_NONE.
Describes an option, its help text (usage) and how it should be parsed.
static option::ArgStatus Required(const option::Option &option, bool msg)
Determines the minimum lengths of the buffer and options arrays used for Parser.
unsigned options_max
Number of elements needed for an options[] array to be used for parsing the same argument vectors tha...
unsigned buffer_max
Number of elements needed for a buffer[] array to be used for parsing the same argument vectors that ...
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.
#define dest(otri, vertexptr)