12 "Usage: rootcling [-v][-v0-4] [-f] [out.cxx] [opts] "
13 "file1.h[+][-][!] file2.h[+][-][!] ...[LinkDef.h]\n";
18#include "rootclingCommandLineOptionsHelp.h"
20#include "RConfigure.h"
39#include <unordered_map>
40#include <unordered_set>
52#define PATH_MAX _MAX_PATH
60#include <mach-o/dyld.h>
69#include "cling/Interpreter/Interpreter.h"
70#include "cling/Interpreter/InterpreterCallbacks.h"
71#include "cling/Interpreter/LookupHelper.h"
72#include "cling/Interpreter/Value.h"
73#include "clang/AST/CXXInheritance.h"
74#include "clang/Basic/Diagnostic.h"
75#include "clang/Basic/MemoryBufferCache.h"
76#include "clang/Frontend/CompilerInstance.h"
77#include "clang/Frontend/FrontendActions.h"
78#include "clang/Frontend/FrontendDiagnostic.h"
79#include "clang/Lex/HeaderSearch.h"
80#include "clang/Lex/Preprocessor.h"
81#include "clang/Lex/ModuleMap.h"
82#include "clang/Lex/Pragma.h"
83#include "clang/Sema/Sema.h"
84#include "clang/Serialization/ASTWriter.h"
85#include "cling/Utils/AST.h"
87#include "llvm/Bitcode/BitstreamWriter.h"
88#include "llvm/Support/CommandLine.h"
89#include "llvm/Support/Path.h"
90#include "llvm/Support/PrettyStackTrace.h"
91#include "llvm/Support/Signals.h"
96#include "TClingUtils.h"
115#include <mach-o/dyld.h>
120#define strcasecmp _stricmp
121#define strncasecmp _strnicmp
148static llvm::cl::opt<bool>
150 llvm::cl::desc(
"Deprecated. Similar to -f but it ignores the dictionary generation. \
151When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."),
171static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
175 for (
const auto td : tdvec)
178static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
182 for (
const auto en : enumvec) {
184 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
185 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
186 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
196 static std::string exepath;
199 exepath = _dyld_get_image_name(0);
201#if defined(__linux) || defined(__linux__)
202 char linkname[PATH_MAX];
208 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
209 int ret = readlink(linkname, buf, 1024);
210 if (ret > 0 && ret < 1024) {
216 char *buf =
new char[MAX_MODULE_NAME32 + 1];
217 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
219 while ((p = strchr(p,
'\\')))
225 return exepath.c_str();
231 const cling::Interpreter &interp)
233 return ROOT::TMetaUtils::ClassInfo__HasMethod(cl,
name, interp);
239 const std::list<VariableSelectionRule> &fieldSelRules)
247 if (fieldSelRules.empty())
return;
249 clang::ASTContext &
C = decl.getASTContext();
250 clang::SourceRange commentRange;
252 const std::string declName(decl.getNameAsString());
254 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
255 it != fieldSelRules.end(); ++it) {
257 if (declName == varName) {
260 BaseSelectionRule::AttributesMap_t::iterator iter;
261 std::string userDefinedProperty;
262 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
263 const std::string &
name = iter->first;
264 const std::string &value = iter->second;
271 if (
name == propNames::iotype &&
272 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
273 const char *msg =
"Data member \"%s\" is an array or a pointer. "
274 "It is not possible to assign to it the iotype \"%s\". "
275 "This transformation is possible only with data members "
276 "which are not pointers or arrays.\n";
278 msg, varName.c_str(), value.c_str());
286 if (
name == propNames::comment) {
287 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, value, 0));
291 if ((
name == propNames::transient && value ==
"true") ||
292 (
name == propNames::persistent && value ==
"false")) {
293 userDefinedProperty = propNames::comment + propNames::separator +
"!";
297 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C,
"!", 0));
302 userDefinedProperty =
name + propNames::separator + value;
305 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
316 cling::Interpreter &interpreter,
324 using namespace clang;
325 SourceLocation commentSLoc;
326 llvm::StringRef comment;
328 ASTContext &
C = CXXRD.getASTContext();
329 Sema &
S = interpreter.getCI()->getSema();
331 SourceRange commentRange;
334 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
335 auto declSelRulePair = declSelRulesMap.
find(declBaseClassPtr->getCanonicalDecl());
336 if (declSelRulePair == declSelRulesMap.end()){
337 const std::string thisClassName(CXXRD.getName());
338 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
343 if (thisClassBaseSelectionRule) {
346 BaseSelectionRule::AttributesMap_t::iterator iter;
347 std::string userDefinedProperty;
348 for (
auto const & attr : thisClassBaseSelectionRule->
GetAttributes()) {
349 const std::string &
name = attr.first;
351 const std::string &value = attr.second;
352 userDefinedProperty =
name + ROOT::TMetaUtils::propNames::separator + value;
354 CXXRD.addAttr(
new(
C) AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
361 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
362 E = CXXRD.decls_end();
I !=
E; ++
I) {
366 if (!(*I)->isImplicit()
367 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
371 SourceLocation maybeMacroLoc = (*I)->getLocation();
372 bool isClassDefMacro = maybeMacroLoc.isMacroID() &&
S.findMacroSpelling(maybeMacroLoc,
"ClassDef");
373 if (isClassDefMacro) {
374 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
379 comment = ROOT::TMetaUtils::GetComment(**
I, &commentSLoc);
380 if (comment.size()) {
383 commentRange = SourceRange(commentSLoc, commentSLoc.getLocWithOffset(comment.size()));
385 if (isClassDefMacro) {
386 CXXRD.addAttr(
new(
C) AnnotateAttr(commentRange,
C, comment.str(), 0));
387 }
else if (!isGenreflex) {
393 (*I)->addAttr(
new(
C) AnnotateAttr(commentRange,
C, comment.str(), 0));
398 if (isGenreflex && thisClassSelectionRule != 0) {
402 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
414 llvm::APInt len = arrayType->getSize();
415 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
416 len *= subArrayType->getSize();
417 arrayType = subArrayType;
419 return len.getLimitedValue();
425 const cling::Interpreter &interp)
427 static const clang::CXXRecordDecl *TObject_decl
428 = ROOT::TMetaUtils::ScopeSearch(
"TObject", interp,
true , 0);
430 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
431 return ROOT::TMetaUtils::IsBase(clxx, TObject_decl,
nullptr, interp);
437 const cling::Interpreter &interp)
439 static const clang::CXXRecordDecl *TObject_decl
440 = ROOT::TMetaUtils::ScopeSearch(
"TSelector", interp,
false , 0);
442 return ROOT::TMetaUtils::IsBase(llvm::dyn_cast<clang::CXXRecordDecl>(cl), TObject_decl,
nullptr, interp);
449 size_t len = strlen(filename);
451 if (strlen(filename) >= xmllen) {
452 return (0 == strcasecmp(filename + (len - xmllen),
".xml"));
478 if (exepath && *exepath) {
480 char *ep =
new char[PATH_MAX];
481 if (!realpath(exepath, ep)) {
482 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
483 strlcpy(ep, exepath, PATH_MAX);
486 int nche = strlen(exepath) + 1;
487 char *ep =
new char[nche];
488 strlcpy(ep, exepath, nche);
492 if ((
s = strrchr(ep,
'/'))) {
494 int removesubdirs = 2;
495 if (!strncmp(
s + 1,
"rootcling_stage1.exe", 20)) {
499 }
else if (!strncmp(
s + 1,
"rootcling_stage1", 16)) {
504 for (
int i = 1;
s && i < removesubdirs; ++i) {
506 s = strrchr(ep,
'/');
517 int ncha = strlen(ep) + 10;
518 char *env =
new char[ncha];
519 snprintf(env, ncha,
"ROOTSYS=%s", ep);
539 const char *expectedTokens[],
543 if (
line[0] !=
'#')
return false;
545 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
546 while (isspace(
line[pos])) ++pos;
547 size_t lenToken = strlen(*iToken);
548 if (
line.compare(pos, lenToken, *iToken)) {
567 if (recordDecl->hasOwningModule()) {
568 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
571 std::string qual_name;
577 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
586 if (classname.find(
':') == std::string::npos)
return;
589 int slen = classname.size();
590 for (
int k = 0; k < slen; ++k) {
591 if (classname[k] ==
':') {
592 if (k + 1 >= slen || classname[k + 1] !=
':') {
597 string base = classname.substr(0, k);
602 autoloads[base] =
"";
606 }
else if (classname[k] ==
'<') {
618 std::string classname;
622 if (
line.find(
"Library.") != 0)
continue;
624 int pos =
line.find(
":", 8);
625 classname =
line.substr(8, pos - 8);
627 ROOT::TMetaUtils::ReplaceAll(classname,
"@@",
"::");
628 ROOT::TMetaUtils::ReplaceAll(classname,
"-",
" ");
631 while (
line[0] ==
' ')
line.replace(0, 1,
"");
635 if (classname ==
"ROOT::TImpProxy") {
639 autoloads[classname] =
line;
654 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
657 if (
line ==
"{ decls }") {
659 if (
line[0] ==
'[')
break;
662 const char firstChar =
line[0];
663 if (firstChar ==
'[') {
665 libs =
line.substr(1,
line.find(
']') - 1);
666 while (libs[0] ==
' ') libs.replace(0, 1,
"");
667 }
else if (0 != keyLenMap.count(firstChar)) {
668 unsigned int keyLen = keyLenMap.at(firstChar);
669 keyname =
line.substr(keyLen,
line.length() - keyLen);
671 autoloads[keyname] = libs;
681void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
683 std::ifstream filelist(fileListName.c_str());
685 std::string filename;
688 while (filelist >> filename) {
690 if (llvm::sys::fs::is_directory(filename))
continue;
692 ifstream
file(filename.c_str());
696 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
698 file.seekg(0, std::ios::beg);
719 const string &fullname,
720 const clang::RecordDecl *cl,
721 cling::Interpreter &interp)
724 const clang::FunctionDecl *method
725 = ROOT::TMetaUtils::GetFuncWithProto(llvm::dyn_cast<clang::Decl>(cl->getDeclContext()), what,
proto, interp,
729 clang::TranslationUnitDecl *TU =
730 cl->getASTContext().getTranslationUnitDecl();
731 method = ROOT::TMetaUtils::GetFuncWithProto(TU, what,
proto, interp,
734 bool has_input_error =
false;
735 if (method != 0 && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
736 std::string filename = ROOT::TMetaUtils::GetFileName(*method, interp);
737 if (strstr(filename.c_str(),
"TBuffer.h") != 0 ||
738 strstr(filename.c_str(),
"Rtypes.h") != 0) {
740 has_input_error =
true;
743 has_input_error =
true;
745 if (has_input_error) {
747 const char *maybeconst =
"";
748 const char *mayberef =
"&";
749 if (what[strlen(what) - 1] ==
'<') {
750 maybeconst =
"const ";
754 "in this version of ROOT, the option '!' used in a linkdef file\n"
755 " implies the actual existence of customized operators.\n"
756 " The following declaration is now required:\n"
757 " TBuffer &%s(TBuffer &,%s%s *%s);\n", what, maybeconst, fullname.c_str(), mayberef);
759 return has_input_error;
770 ROOT::TMetaUtils::GetQualifiedName(fullname, *cl);
771 int ncha = fullname.length() + 13;
772 char *
proto =
new char[ncha];
784 return has_input_error;
790bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
794 bool hasClassDef = ROOT::TMetaUtils::ClassInfo__HasMethod(&cl,
"Class_Version", interp);
796 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
800 bool isAbstract = clxx->isAbstract();
803 std::string qualName;
804 ROOT::TMetaUtils::GetQualifiedName(qualName, cl);
805 const char *qualName_c = qualName.c_str();
807 "because it inherits from TObject but does not "
808 "have its own ClassDef.\n",
821 if (
m.getType().isConstQualified()) {
822 string ret =
"const_cast< ";
824 ROOT::TMetaUtils::GetQualifiedName(type_name,
m.getType(),
m);
825 if (type_name.substr(0,6)==
"const ") {
826 ret += type_name.c_str()+6;
832 ret +=
m.getName().str();
836 return prefix +
m.getName().str();
846 const cling::Interpreter &interp,
847 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
848 std::ostream &dictStream)
851 std::string mTypename;
852 ROOT::TMetaUtils::GetQualifiedName(mTypename,
m.getType(),
m);
854 const clang::CXXRecordDecl *clxx = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(ROOT::TMetaUtils::GetUnderlyingRecordDecl(
m.getType()));
861 clang::QualType utype(ROOT::TMetaUtils::GetUnderlyingType(
m.getType()), 0);
862 Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
864 if (clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
866 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
867 if (!tmplt_specialization)
return 0;
870 string stlType(ROOT::TMetaUtils::ShortTypeName(mTypename.c_str()));
872 stlName = ROOT::TMetaUtils::ShortTypeName(
m.getName().str().c_str());
874 string fulName1, fulName2;
875 const char *tcl1 = 0, *tcl2 = 0;
876 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
877 clang::QualType ti = arg0.getAsType();
879 if (ROOT::TMetaUtils::ElementStreamer(dictStream,
m, ti, 0, rwmode, interp)) {
881 fulName1 = ti.getAsString();
884 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
885 clang::QualType tmplti = arg1.getAsType();
886 if (ROOT::TMetaUtils::ElementStreamer(dictStream,
m, tmplti, 0, rwmode, interp)) {
888 fulName2 = tmplti.getAsString();
895 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
901 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
905 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
907 }
else if (
m.getType()->isPointerType()) {
912 dictStream <<
" {" << std::endl;
914 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
919 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
922 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
925 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
926 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
927 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
930 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
931 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
932 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
936 dictStream <<
" R__stl.clear();" << std::endl;
939 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
940 <<
" if (R__tcl1==0) {" << std::endl
941 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
942 << fulName1.c_str() <<
"!\");" << std::endl
943 <<
" return;" << std::endl
944 <<
" }" << std::endl;
947 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
948 <<
" if (R__tcl2==0) {" << std::endl
949 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
950 << fulName2.c_str() <<
"!\");" << std::endl
951 <<
" return;" << std::endl
952 <<
" }" << std::endl;
955 dictStream <<
" int R__i, R__n;" << std::endl
956 <<
" R__b >> R__n;" << std::endl;
959 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
961 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
963 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, arg0.getAsType(),
"R__t", rwmode, interp, tcl1);
965 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
966 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, arg1.getAsType(),
"R__t2", rwmode, interp, tcl2);
985 std::string keyName(ti.getAsString());
986 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
987 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
988 <<
" R__stl.insert(R__t3);" << std::endl;
996 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1001 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1004 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1009 dictStream <<
" }" << std::endl
1010 <<
" }" << std::endl;
1011 if (isArr) dictStream <<
" }" << std::endl;
1017 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
1019 dictStream <<
" {" << std::endl;
1022 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1025 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1028 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1031 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1035 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1036 <<
" R__b << R__n;" << std::endl
1037 <<
" if(R__n) {" << std::endl;
1040 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1041 <<
" if (R__tcl1==0) {" << std::endl
1042 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1043 << fulName1.c_str() <<
"!\");" << std::endl
1044 <<
" return;" << std::endl
1045 <<
" }" << std::endl;
1048 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1049 <<
" if (R__tcl2==0) {" << std::endl
1050 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1051 <<
" return;" << std::endl
1052 <<
" }" << std::endl;
1055 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1056 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1058 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1059 clang::QualType tmplti = arg1.getAsType();
1060 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, ti,
"((*R__k).first )", rwmode, interp, tcl1);
1061 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, tmplti,
"((*R__k).second)", rwmode, interp, tcl2);
1063 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, ti,
"(*R__k)" , rwmode, interp, tcl1);
1066 dictStream <<
" }" << std::endl
1067 <<
" }" << std::endl
1068 <<
" }" << std::endl;
1069 if (isArr) dictStream <<
" }" << std::endl;
1081 std::string mTypenameStr;
1082 ROOT::TMetaUtils::GetQualifiedName(mTypenameStr,
m.getType(),
m);
1084 const char *mTypeName = ROOT::TMetaUtils::ShortTypeName(mTypenameStr.c_str());
1085 if (!strcmp(mTypeName,
"string")) {
1087 std::string fieldname =
m.getName().str();
1090 if (
m.getType()->isConstantArrayType()) {
1091 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1092 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1094 std::stringstream fullIdx;
1095 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1098 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1099 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1100 fullIdx <<
"[R__i" << dim <<
"]";
1101 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1104 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1105 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1108 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1109 if (
m.getType()->isPointerType())
1110 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1111 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1113 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1117 if (
m.getType()->isPointerType())
1118 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1119 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1120 else if (
m.getType()->isConstantArrayType()) {
1121 std::stringstream fullIdx;
1122 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1125 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1126 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1127 fullIdx <<
"[R__i" << dim <<
"]";
1128 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1131 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1133 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1144 if (
m.getType()->isPointerType()) {
1145 if (
m.getType()->getPointeeType()->isPointerType()) {
1157 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1159 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1161 dictStream <<
"[0]";
1162 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1172 bool add_template_keyword = ROOT::TMetaUtils::NeedTemplateKeyword(cl);
1177 int enclSpaceNesting = 0;
1179 if (ROOT::TMetaUtils::GetNameWithinNamespace(fullname, clsname, nsname, cl)) {
1180 enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl);
1184 dictStream <<
"#include \"TInterpreter.h\"\n";
1186 dictStream <<
"//_______________________________________"
1187 <<
"_______________________________________" << std::endl;
1188 if (add_template_keyword) dictStream <<
"template <> ";
1189 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(0); // static to hold class pointer" << std::endl
1192 <<
"//_______________________________________"
1193 <<
"_______________________________________" << std::endl;
1194 if (add_template_keyword) dictStream <<
"template <> ";
1195 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1196 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1198 dictStream <<
"//_______________________________________"
1199 <<
"_______________________________________" << std::endl;
1200 if (add_template_keyword) dictStream <<
"template <> ";
1201 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1202 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1203 <<
"*)0x0)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1205 <<
"//_______________________________________"
1206 <<
"_______________________________________" << std::endl;
1207 if (add_template_keyword) dictStream <<
"template <> ";
1208 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1209 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1210 <<
"*)0x0)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1212 <<
"//_______________________________________"
1213 <<
"_______________________________________" << std::endl;
1214 if (add_template_keyword) dictStream <<
"template <> ";
1215 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1219 dictStream <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1220 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1221 <<
"*)0x0)->GetClass();" << std::endl
1222 <<
" return fgIsA;\n"
1223 <<
"}" << std::endl << std::endl
1225 <<
"//_______________________________________"
1226 <<
"_______________________________________" << std::endl;
1227 if (add_template_keyword) dictStream <<
"template <> ";
1228 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1230 dictStream <<
" Dictionary();\n";
1232 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1233 dictStream << fullname <<
"*)0x0)->GetClass(); }" << std::endl;
1235 dictStream <<
" return fgIsA;" << std::endl
1236 <<
"}" << std::endl << std::endl;
1238 while (enclSpaceNesting) {
1239 dictStream <<
"} // namespace " << nsname << std::endl;
1248 cling::Interpreter &interp,
1249 std::ostream &dictStream)
1251 if (cl->isAnonymousNamespace()) {
1257 string classname = ROOT::TMetaUtils::GetQualifiedName(*cl).c_str();
1259 TMetaUtils::GetCppName(mappedname, classname.c_str());
1263 if (classname !=
"ROOT") {
1264 nesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream,cl);
1267 dictStream <<
" namespace ROOT {" << std::endl;
1270 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1274 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1275 dictStream << std::endl
1277 <<
" // Function generating the singleton type initializer" << std::endl
1280 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1281 <<
" {" << std::endl
1283 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1284 <<
" {" << std::endl
1287 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1289 <<
" instance(\"" << classname.c_str() <<
"\", ";
1292 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1294 dictStream <<
"0 /*version*/, ";
1297 std::string filename = ROOT::TMetaUtils::GetFileName(*cl, interp);
1298 for (
unsigned int i = 0; i < filename.length(); i++) {
1299 if (filename[i] ==
'\\') filename[i] =
'/';
1301 dictStream <<
"\"" << filename <<
"\", " << ROOT::TMetaUtils::GetLineNumber(cl) <<
"," << std::endl
1302 <<
" ::ROOT::Internal::DefineBehavior((void*)0,(void*)0)," << std::endl
1306 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1308 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1311 dictStream << 0 <<
");" << std::endl
1313 <<
" return &instance;" << std::endl
1314 <<
" }" << std::endl
1315 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1316 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1317 <<
" // Static variable to force the class initialization" << std::endl
1319 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1320 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1323 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1324 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1325 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1326 <<
" }" << std::endl << std::endl;
1329 dictStream <<
" }" << std::endl;
1331 dictStream <<
"}" << std::endl;
1333 dictStream << std::endl;
1342llvm::StringRef
GrabIndex(
const clang::FieldDecl &member,
int printError)
1345 llvm::StringRef where;
1347 llvm::StringRef index = ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(member, &error, &where);
1348 if (index.size() == 0 && printError) {
1349 const char *errorstring;
1351 case TMetaUtils::NOT_INT:
1352 errorstring =
"is not an integer";
1354 case TMetaUtils::NOT_DEF:
1355 errorstring =
"has not been defined before the array";
1357 case TMetaUtils::IS_PRIVATE:
1358 errorstring =
"is a private member of a parent class";
1360 case TMetaUtils::UNKNOWN:
1361 errorstring =
"is not known";
1364 errorstring =
"UNKNOWN ERROR!!!!";
1367 if (where.size() == 0) {
1369 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1372 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1381 const cling::Interpreter &interp,
1382 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
1383 std::ostream &dictStream)
1385 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
1386 if (clxx == 0)
return;
1388 bool add_template_keyword = ROOT::TMetaUtils::NeedTemplateKeyword(clxx);
1393 int enclSpaceNesting = 0;
1395 if (ROOT::TMetaUtils::GetNameWithinNamespace(fullname, clsname, nsname, clxx)) {
1396 enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl);
1399 dictStream <<
"//_______________________________________"
1400 <<
"_______________________________________" << std::endl;
1401 if (add_template_keyword) dictStream <<
"template <> ";
1402 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1403 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1408 int version = ROOT::TMetaUtils::GetClassVersion(clxx, interp);
1411 int basestreamer = 0;
1412 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1415 if (ROOT::TMetaUtils::ClassInfo__HasMethod(iter->getType()->getAsCXXRecordDecl(),
"Streamer", interp)) {
1416 string base_fullname;
1417 ROOT::TMetaUtils::GetQualifiedName(base_fullname, * iter->getType()->getAsCXXRecordDecl());
1419 if (strstr(base_fullname.c_str(),
"::")) {
1421 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1422 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1423 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1425 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1430 if (!basestreamer) {
1431 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1432 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1434 dictStream <<
"}" << std::endl << std::endl;
1435 while (enclSpaceNesting) {
1436 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1443 string classname = fullname;
1444 if (strstr(fullname.c_str(),
"::")) {
1446 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1447 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1448 classname =
"thisClass";
1450 for (
int i = 0; i < 2; i++) {
1455 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1456 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1457 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1459 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1460 dictStream <<
" } else {" << std::endl;
1461 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1466 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1469 if (ROOT::TMetaUtils::ClassInfo__HasMethod(iter->getType()->getAsCXXRecordDecl(),
"Streamer", interp)) {
1470 string base_fullname;
1471 ROOT::TMetaUtils::GetQualifiedName(base_fullname, * iter->getType()->getAsCXXRecordDecl());
1473 if (strstr(base_fullname.c_str(),
"::")) {
1475 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1476 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1477 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1480 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1486 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1489 const char *comment = ROOT::TMetaUtils::GetComment(**field_iter).data();
1491 clang::QualType
type = field_iter->getType();
1492 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1494 const clang::Type *underling_type = ROOT::TMetaUtils::GetUnderlyingType(
type);
1502 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1506 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1509 if (strncmp(comment,
"!", 1)) {
1512 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1513 if (
type.getTypePtr()->isConstantArrayType() &&
1514 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1515 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1519 dictStream <<
" int R__i;" << std::endl;
1522 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1524 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());
1525 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1527 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1529 }
else if (
type.getTypePtr()->isPointerType()) {
1530 llvm::StringRef indexvar =
GrabIndex(**field_iter, i == 0);
1531 if (indexvar.size() == 0) {
1533 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1534 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1536 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1540 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1542 << ROOT::TMetaUtils::ShortTypeName(**field_iter) <<
"[" << indexvar.str() <<
"];" << std::endl;
1545 <<
"," << indexvar.str() <<
");" << std::endl;
1546 }
else if (isDouble32) {
1548 <<
"," << indexvar.str() <<
");" << std::endl;
1551 <<
"," << indexvar.str() <<
");" << std::endl;
1555 dictStream <<
" R__b.WriteFastArrayFloat16("
1556 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1557 }
else if (isDouble32) {
1558 dictStream <<
" R__b.WriteFastArrayDouble32("
1559 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1561 dictStream <<
" R__b.WriteFastArray("
1562 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1566 }
else if (
type.getTypePtr()->isArrayType()) {
1568 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1569 if (underling_type->isEnumeralType())
1570 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1573 dictStream <<
" R__b.ReadStaticArrayFloat16((" << ROOT::TMetaUtils::TrueName(**field_iter)
1574 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1575 }
else if (isDouble32) {
1576 dictStream <<
" R__b.ReadStaticArrayDouble32((" << ROOT::TMetaUtils::TrueName(**field_iter)
1577 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1579 dictStream <<
" R__b.ReadStaticArray((" << ROOT::TMetaUtils::TrueName(**field_iter)
1580 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1584 if (underling_type->isEnumeralType()) {
1585 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1588 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1589 }
else if (isDouble32) {
1590 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1592 dictStream <<
" R__b.ReadStaticArray((" << ROOT::TMetaUtils::TrueName(**field_iter)
1593 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1598 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1601 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1602 if (underling_type->isEnumeralType())
1603 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1604 <<
s <<
");" << std::endl;
1605 else if (isFloat16) {
1606 dictStream <<
" R__b.WriteArrayFloat16((" << ROOT::TMetaUtils::TrueName(**field_iter)
1607 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1608 }
else if (isDouble32) {
1609 dictStream <<
" R__b.WriteArrayDouble32((" << ROOT::TMetaUtils::TrueName(**field_iter)
1610 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1612 dictStream <<
" R__b.WriteArray((" << ROOT::TMetaUtils::TrueName(**field_iter)
1613 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1616 if (underling_type->isEnumeralType())
1617 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1618 else if (isFloat16) {
1619 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1620 }
else if (isDouble32) {
1621 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1623 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1627 }
else if (underling_type->isEnumeralType()) {
1629 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1630 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1632 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1637 <<
"=Float16_t(R_Dummy);}" << std::endl;
1640 }
else if (isDouble32) {
1643 <<
"=Double32_t(R_Dummy);}" << std::endl;
1665 if (
type.getTypePtr()->isConstantArrayType() &&
1666 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1667 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1671 dictStream <<
" int R__i;" << std::endl;
1674 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1678 if (ROOT::TMetaUtils::IsBase(**field_iter,
"TObject", interp) && ROOT::TMetaUtils::IsBase(**field_iter,
"TArray", interp))
1679 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1684 dictStream <<
"[R__i];" << std::endl;
1685 }
else if (
type.getTypePtr()->isPointerType()) {
1693 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1694 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1696 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1699 if (ROOT::TMetaUtils::GetQualifiedName(*ROOT::TMetaUtils::GetUnderlyingType(field_iter->getType()), **field_iter) ==
"TClonesArray") {
1700 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1713 if (ROOT::TMetaUtils::IsBase(**field_iter,
"TObject", interp) && ROOT::TMetaUtils::IsBase(**field_iter,
"TArray", interp))
1714 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1720 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1724 dictStream <<
" int R__i;" << std::endl;
1727 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1728 std::string mTypeNameStr;
1729 ROOT::TMetaUtils::GetQualifiedName(mTypeNameStr, field_iter->getType(), **field_iter);
1730 const char *mTypeName = mTypeNameStr.c_str();
1731 const char *constwd =
"const ";
1732 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1733 mTypeName += strlen(constwd);
1734 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1736 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1740 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1743 if (ROOT::TMetaUtils::ClassInfo__HasMethod(ROOT::TMetaUtils::GetUnderlyingRecordDecl(field_iter->getType()),
"Streamer", interp))
1746 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1747 << field_iter->getName().str() <<
"));" << std::endl;
1758 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1759 <<
" }" << std::endl
1760 <<
"}" << std::endl << std::endl;
1762 while (enclSpaceNesting) {
1763 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1771 const cling::Interpreter &interp,
1772 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
1773 std::ostream &dictStream)
1777 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
1778 if (clxx == 0)
return;
1780 bool add_template_keyword = ROOT::TMetaUtils::NeedTemplateKeyword(clxx);
1783 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1786 int k = ROOT::TMetaUtils::IsSTLContainer(*iter);
1788 Internal::RStl::Instance().GenerateTClassFor(iter->getType(), interp, normCtxt);
1795 int enclSpaceNesting = 0;
1797 if (ROOT::TMetaUtils::GetNameWithinNamespace(fullname, clsname, nsname, clxx)) {
1798 enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl);
1801 dictStream <<
"//_______________________________________"
1802 <<
"_______________________________________" << std::endl;
1803 if (add_template_keyword) dictStream <<
"template <> ";
1804 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1806 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1807 <<
" if (R__b.IsReading()) {" << std::endl
1808 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1809 <<
" } else {" << std::endl
1810 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1811 <<
" }" << std::endl
1812 <<
"}" << std::endl << std::endl;
1814 while (enclSpaceNesting) {
1815 dictStream <<
"} // namespace " << nsname << std::endl;
1823 const cling::Interpreter &interp,
1824 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
1825 std::ostream &dictStream,
1826 bool isAutoStreamer)
1828 if (isAutoStreamer) {
1838 std::string &code_for_parser)
1840 code_for_parser +=
"#ifdef __CINT__\n\n";
1841 code_for_parser +=
"#pragma link off all globals;\n";
1842 code_for_parser +=
"#pragma link off all classes;\n";
1843 code_for_parser +=
"#pragma link off all functions;\n\n";
1845 for (std::string& arg : InputFiles) {
1847 int nostr = 0, noinp = 0, bcnt = 0,
l = arg.length() - 1;
1848 for (
int j = 0; j < 3; j++) {
1849 if (arg[
l] ==
'-') {
1854 if (arg[
l] ==
'!') {
1859 if (arg[
l] ==
'+') {
1865 if (nostr || noinp) {
1867 if (nostr) strlcat(trail,
"-", 3);
1868 if (noinp) strlcat(trail,
"!", 3);
1871 strlcpy(trail,
"+", 3);
1875 llvm::SmallString<256> filestem = llvm::sys::path::filename(arg);
1876 llvm::sys::path::replace_extension(filestem,
"");
1878 code_for_parser +=
"#pragma link C++ class ";
1879 code_for_parser += filestem.str().str();
1880 if (nostr || noinp || bcnt)
1881 code_for_parser += trail;
1882 code_for_parser +=
";\n";
1885 code_for_parser +=
"\n#endif\n";
1893bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1898 static const char *fopenopts =
"rb";
1900 static const char *fopenopts =
"r";
1904 fp = fopen(pname.c_str(), fopenopts);
1910 llvm::SmallVector<std::string, 10> includePaths;
1912 interp.GetIncludePaths(includePaths,
false,
false);
1914 const size_t nPaths = includePaths.size();
1915 for (
size_t i = 0; i < nPaths; i += 1 ) {
1919 fp = fopen(pname.c_str(), fopenopts);
1941 const char *inc = strstr(original,
"\\inc\\");
1943 inc = strstr(original,
"/inc/");
1944 if (inc && strlen(inc) > 5)
1964 cling::Interpreter &interp,
1967 std::ostringstream out;
1975 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
1976 const std::string &hdrName
1991static bool WriteAST(StringRef fileName, clang::CompilerInstance *compilerInstance, StringRef iSysRoot,
1992 clang::Module *module =
nullptr)
1995 llvm::SmallVector<char, 128> buffer;
1996 llvm::BitstreamWriter stream(buffer);
1997 clang::ASTWriter
writer(stream, buffer, compilerInstance->getPCMCache(), {});
1998 std::unique_ptr<llvm::raw_ostream> out =
1999 compilerInstance->createOutputFile(fileName,
true,
2008 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2010 writer.WriteAST(compilerInstance->getSema(), fileName, module, iSysRoot);
2013 out->write(&buffer.front(), buffer.size());
2025 const std::string ¤tDirectory)
2027 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2029 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2037static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2040 if (headers.empty())
2044 std::stringstream includes;
2045 for (
const std::string &header : headers) {
2046 includes <<
"#include \"" << header <<
"\"\n";
2048 std::string includeListStr = includes.str();
2049 auto result = interpreter.declare(includeListStr);
2050 return result == cling::Interpreter::CompilationResult::kSuccess;
2058 char platformDefines[64] = {0};
2059#ifdef __INTEL_COMPILER
2060 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2061 clingArgs.push_back(platformDefines);
2064 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2065 clingArgs.push_back(platformDefines);
2068 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2069 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2070 clingArgs.push_back(platformDefines);
2072#ifdef __GNUC_MINOR__
2073 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2074 clingArgs.push_back(platformDefines);
2077 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2078 clingArgs.push_back(platformDefines);
2081 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2082 clingArgs.push_back(platformDefines);
2085 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2086 clingArgs.push_back(platformDefines);
2088#ifdef _STLPORT_VERSION
2090 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2091 clingArgs.push_back(platformDefines);
2094 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2095 clingArgs.push_back(platformDefines);
2098 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2099 clingArgs.push_back(platformDefines);
2102 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2103 clingArgs.push_back(platformDefines);
2106 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2107 clingArgs.push_back(platformDefines);
2110 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2111 clingArgs.push_back(platformDefines);
2114 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2115 clingArgs.push_back(platformDefines);
2119 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2120 clingArgs.push_back(platformDefines);
2121 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2122 clingArgs.push_back(platformDefines);
2131 return llvm::sys::path::filename(path);
2141 if (std::string::npos != pos) {
2142 dirname.assign(path.begin(), path.begin() + pos + 1);
2153 std::string dictLocation;
2155 return !dictLocation.empty();
2161 std::string &rootmapLibName)
2165 if (rootmapFileName.empty()) {
2167 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2168 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2169 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2171 rootmapLibName.c_str(),
2172 rootmapFileName.c_str());
2181 std::string &ctxtName,
2182 const cling::Interpreter &interpreter,
2183 bool treatParent =
true)
2185 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2187 if (!outerCtxt)
return;
2189 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2199 std::string &ctxtName,
2200 const cling::Interpreter &interpreter)
2202 const clang::DeclContext *theContext = theDecl.getDeclContext();
2210 const cling::Interpreter &interp)
2212 if (!decls.empty()) {
2213 std::string autoLoadKey;
2214 for (
auto &
d : decls) {
2218 if (autoLoadKey.empty()) {
2219 names.push_back(
d->getQualifiedNameAsString());
2237 const std::string &rootmapLibName,
2238 const std::list<std::string> &classesDefsList,
2239 const std::list<std::string> &classesNames,
2240 const std::list<std::string> &nsNames,
2241 const std::list<std::string> &tdNames,
2242 const std::list<std::string> &enNames,
2243 const std::list<std::string> &varNames,
2245 const std::unordered_set<std::string> headersToIgnore)
2248 std::ofstream rootmapFile(rootmapFileName.c_str());
2256 std::unordered_set<std::string> classesKeys;
2260 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2261 !enNames.empty() || !varNames.empty()) {
2264 if (!classesDefsList.empty()) {
2265 rootmapFile <<
"{ decls }\n";
2266 for (
auto & classDef : classesDefsList) {
2267 rootmapFile << classDef << std::endl;
2269 rootmapFile <<
"\n";
2271 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2274 if (!classesNames.empty()) {
2275 rootmapFile <<
"# List of selected classes\n";
2276 for (
auto & className : classesNames) {
2277 rootmapFile <<
"class " << className << std::endl;
2278 classesKeys.insert(className);
2281 std::unordered_set<std::string> treatedHeaders;
2282 for (
auto & className : classesNames) {
2284 if (className.find(
"<") != std::string::npos)
continue;
2285 if (headersClassesMap.count(className)) {
2286 auto &headers = headersClassesMap.at(className);
2287 if (!headers.empty()){
2288 auto &header = headers.front();
2289 if (treatedHeaders.insert(header).second &&
2290 headersToIgnore.find(header) == headersToIgnore.end() &&
2291 ROOT::TMetaUtils::IsHeaderName(header)){
2292 rootmapFile <<
"header " << header << std::endl;
2300 if (!nsNames.empty()) {
2301 rootmapFile <<
"# List of selected namespaces\n";
2302 for (
auto & nsName : nsNames) {
2303 rootmapFile <<
"namespace " << nsName << std::endl;
2308 if (!tdNames.empty()) {
2309 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2310 for (
const auto & autoloadKey : tdNames)
2311 if (classesKeys.insert(autoloadKey).second)
2312 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2317 if (!enNames.empty()){
2318 rootmapFile <<
"# List of selected enums and outer classes\n";
2319 for (
const auto & autoloadKey : enNames)
2320 if (classesKeys.insert(autoloadKey).second)
2321 rootmapFile <<
"enum " << autoloadKey << std::endl;
2325 if (!varNames.empty()){
2326 rootmapFile <<
"# List of selected vars\n";
2327 for (
const auto & autoloadKey : varNames)
2328 if (classesKeys.insert(autoloadKey).second)
2329 rootmapFile <<
"var " << autoloadKey << std::endl;
2343 auto nsPattern =
'{';
auto nsPatternLength = 1;
2344 auto foundNsPos =
line.find_last_of(nsPattern);
2345 if (foundNsPos == std::string::npos)
return {
"",
""};
2346 foundNsPos+=nsPatternLength;
2347 auto extNs =
line.substr(0,foundNsPos);
2349 auto nsEndPattern =
'}';
2350 auto foundEndNsPos =
line.find(nsEndPattern);
2351 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2353 return {extNs, contained};
2369 std::map<std::string, std::string> nsEntitiesMap;
2370 std::list<std::string> optFwdDeclList;
2371 for (
auto const & fwdDecl : fwdDeclarationsList){
2374 if (extNsAndEntities.first.empty()) {
2376 optFwdDeclList.push_front(fwdDecl);
2378 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2379 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2383 std::string optFwdDecl;
2384 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2385 optFwdDecl = extNsAndEntities.first;
2386 optFwdDecl += extNsAndEntities.second;
2387 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2390 optFwdDeclList.push_front(optFwdDecl);
2393 return optFwdDeclList;
2401 std::list<std::string> &el_list,
2402 std::unordered_set<std::string> &el_set)
2404 std::stringstream elStream(el);
2407 while (getline(elStream, tmp,
'\n')) {
2409 if (el_set.insert(tmp).second && !tmp.empty()) {
2410 el_list.push_back(tmp);
2421 std::list<std::string> &classesList,
2422 std::list<std::string> &classesListForRootmap,
2423 std::list<std::string> &fwdDeclarationsList,
2424 const cling::Interpreter &interpreter)
2432 std::unordered_set<std::string> classesSet;
2433 std::unordered_set<std::string> outerMostClassesSet;
2435 std::string attrName, attrValue;
2436 bool isClassSelected;
2437 std::unordered_set<std::string> availableFwdDecls;
2438 std::string fwdDeclaration;
2440 fwdDeclaration =
"";
2441 int retCode = ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces(*selVar, fwdDeclaration);
2446 fwdDeclaration =
"";
2447 int retCode = ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces(*selEnum, fwdDeclaration);
2453 isClassSelected =
true;
2454 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2455 std::string normalizedName;
2456 normalizedName = selClass.GetNormalizedName();
2457 if (!normalizedName.empty() &&
2458 !classesSet.insert(normalizedName).second &&
2459 outerMostClassesSet.count(normalizedName) == 0) {
2460 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2461 <<
" was already selected. This means that two different instances of"
2462 <<
" clang::RecordDecl had the same name, which is not possible."
2463 <<
" This can be a hint of a serious problem in the class selection."
2464 <<
" In addition, the generated dictionary would not even compile.\n";
2467 classesList.push_back(normalizedName);
2470 const char *reqName(selClass.GetRequestedName());
2473 fwdDeclaration =
"";
2474 int retCode = ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces(*rDecl, fwdDeclaration);
2478 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2479 fwdDeclaration =
"";
2480 retCode = ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromRcdDecl(*rDecl, interpreter, fwdDeclaration);
2486 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2487 if (0 == ROOT::TMetaUtils::extractPropertyNameVal(*ait, attrName, attrValue) &&
2488 attrName ==
"rootmap" &&
2489 attrValue ==
"false") {
2490 attrName = attrValue =
"";
2491 isClassSelected =
false;
2495 if (isClassSelected) {
2511 std::string outerMostClassName;
2513 if (!outerMostClassName.empty() &&
2514 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2515 classesSet.insert(outerMostClassName).second &&
2516 outerMostClassesSet.insert(outerMostClassName).second) {
2517 classesListForRootmap.push_back(outerMostClassName);
2519 classesListForRootmap.push_back(normalizedName);
2520 if (reqName !=
nullptr && 0 != strcmp(reqName,
"") && reqName != normalizedName) {
2521 classesListForRootmap.push_back(reqName);
2526 std::string demangledName = selClass.GetDemangledTypeInfo();
2527 if (!demangledName.empty()) {
2532 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2534 classesListForRootmap.push_back(demangledName);
2540 classesListForRootmap.sort();
2553 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2555 nsList.push_back(ROOT::TMetaUtils::GetQualifiedName(* selNsIter->GetNamespaceDecl()));
2568 if (clang::CXXRecordDecl *CXXRD =
2569 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2581 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2584 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2585 if (cxxdecl && ROOT::TMetaUtils::ClassInfo__HasMethod(selClass,
"Class_Name", interp)) {
2587 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2603 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2604 "#include \"TFile.h\"\n"
2605 "#include \"TObjArray.h\"\n"
2606 "#include \"TVirtualArray.h\"\n"
2607 "#include \"TStreamerElement.h\"\n"
2608 "#include \"TProtoClass.h\"\n"
2609 "#include \"TBaseClass.h\"\n"
2610 "#include \"TListOfDataMembers.h\"\n"
2611 "#include \"TListOfEnums.h\"\n"
2612 "#include \"TListOfEnumsWithLock.h\"\n"
2613 "#include \"TDataMember.h\"\n"
2614 "#include \"TEnum.h\"\n"
2615 "#include \"TEnumConstant.h\"\n"
2616 "#include \"TDictAttributeMap.h\"\n"
2617 "#include \"TMessageHandler.h\"\n"
2618 "#include \"TArray.h\"\n"
2619 "#include \"TRefArray.h\"\n"
2620 "#include \"root_std_complex.h\"\n")
2621 != cling::Interpreter::kSuccess)
2632 cling::Interpreter &interp,
2634 const ROOT::TMetaUtils::RConstructorTypes &ctorTypes,
2637 bool writeEmptyRootPCM)
2639 ROOT::TMetaUtils::TNormalizedCtxt normCtxt(interp.getLookupHelper());
2641 bool needsCollectionProxy =
false;
2663 auto nsName =
ns.GetNamespaceDecl()->getQualifiedNameAsString();
2664 if (nsName.find(
"(anonymous)") == std::string::npos)
2669 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2670 ROOT::TMetaUtils::Error(0,
"A dictionary has been requested for %s but there is no declaration!\n", ROOT::TMetaUtils::GetQualifiedName(selClass).c_str());
2673 if (selClass.RequestOnlyTClass()) {
2681 if (clang::CXXRecordDecl *CXXRD =
2682 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2686 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2693 Internal::RStl::Instance().GenerateTClassFor(selClass.GetNormalizedName(), CRD, interp, normCtxt);
2696 ROOT::TMetaUtils::WriteClassInit(dictStream, selClass, CRD, interp, normCtxt, ctorTypes,
2697 needsCollectionProxy);
2712 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2716 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2717 if (cxxdecl && ROOT::TMetaUtils::ClassInfo__HasMethod(selClass,
"Class_Name", interp) && !
gOptIgnoreExistingDict) {
2728 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2732 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2734 if (!ROOT::TMetaUtils::IsSTLContainer(selClass)) {
2736 ROOT::TMetaUtils::WriteClassInit(dictStream, selClass, CRD, interp, normCtxt, ctorTypes,
2737 needsCollectionProxy);
2756 ROOT::Internal::RStl::Instance().WriteClassInit(dictStream, interp, normCtxt, ctorTypes, needsCollectionProxy,
2766 if (finRetCode != 0)
return finRetCode;
2776 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2777 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2780 <<
"#define R__NO_DEPRECATION" << std::endl
2785 <<
"\n/*******************************************************************/\n"
2786 <<
"#include <stddef.h>\n"
2787 <<
"#include <stdio.h>\n"
2788 <<
"#include <stdlib.h>\n"
2789 <<
"#include <string.h>\n"
2790 <<
"#include <assert.h>\n"
2791 <<
"#define G__DICTIONARY\n"
2792 <<
"#include \"RConfig.h\"\n"
2793 <<
"#include \"TClass.h\"\n"
2794 <<
"#include \"TDictAttributeMap.h\"\n"
2795 <<
"#include \"TInterpreter.h\"\n"
2796 <<
"#include \"TROOT.h\"\n"
2797 <<
"#include \"TBuffer.h\"\n"
2798 <<
"#include \"TMemberInspector.h\"\n"
2799 <<
"#include \"TInterpreter.h\"\n"
2800 <<
"#include \"TVirtualMutex.h\"\n"
2801 <<
"#include \"TError.h\"\n\n"
2802 <<
"#ifndef G__ROOT\n"
2803 <<
"#define G__ROOT\n"
2805 <<
"#include \"RtypesImp.h\"\n"
2806 <<
"#include \"TIsAProxy.h\"\n"
2807 <<
"#include \"TFileMergeInfo.h\"\n"
2808 <<
"#include <algorithm>\n"
2809 <<
"#include \"TCollectionProxyInfo.h\"\n"
2810 <<
"/*******************************************************************/\n\n"
2811 <<
"#include \"TDataMember.h\"\n\n";
2818 dictStream <<
"// The generated code does not explicitly qualifies STL entities\n"
2819 <<
"namespace std {} using namespace std;\n\n";
2825 const std::string &includeForSource,
2826 const std::string &extraIncludes)
2828 dictStream <<
"// Header files passed as explicit arguments\n"
2829 << includeForSource << std::endl
2830 <<
"// Header files passed via #pragma extra_include\n"
2831 << extraIncludes << std::endl;
2837#if defined(R__IOSSIM) || defined(R__IOS)
2856class tempFileNamesCatalog {
2859 tempFileNamesCatalog(): m_size(0), m_emptyString(
"") {};
2861 std::string getTmpFileName(
const std::string &filename) {
2862 return filename +
"_tmp_" + std::to_string(getpid());
2868 void addFileName(std::string &nameStr) {
2869 if (nameStr.empty())
return;
2871 std::string tmpNameStr(getTmpFileName(nameStr));
2874 const char *
name(nameStr.c_str());
2875 const char *tmpName(tmpNameStr.c_str());
2877 m_names.push_back(nameStr);
2878 m_tempNames.push_back(tmpNameStr);
2882 if (0 == std::rename(
name , tmpName)) {
2887 nameStr = tmpNameStr;
2898 for (
unsigned int i = 0; i < m_size; ++i) {
2899 const char *tmpName = m_tempNames[i].c_str();
2901 std::ifstream ifile(tmpName);
2905 if (0 != std::remove(tmpName)) {
2918 for (
unsigned int i = 0; i < m_size; ++i) {
2919 const char *tmpName = m_tempNames[i].c_str();
2920 const char *
name = m_names[i].c_str();
2922 std::ifstream ifile(tmpName);
2929 if (ifile.is_open())
2931 if (0 != std::rename(tmpName ,
name)) {
2932 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
2933 llvm::sys::fs::remove(tmpName);
2937 if (0 != std::rename(tmpName ,
name)) {
2948 const std::string &getFileName(
const std::string &tmpFileName) {
2949 size_t i = std::distance(m_tempNames.begin(),
2950 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
2951 if (i == m_tempNames.size())
return m_emptyString;
2958 std::cout <<
"Restoring files in temporary file catalog:\n";
2959 for (
unsigned int i = 0; i < m_size; ++i) {
2960 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
2965 unsigned int m_size;
2966 const std::string m_emptyString;
2967 std::vector<std::string> m_names;
2968 std::vector<std::string> m_tempNames;
2975 tempFileNamesCatalog &tmpCatalog)
2977 std::string splitDictName(tmpCatalog.getFileName(dictpathname));
2978 const size_t dotPos = splitDictName.find_last_of(
".");
2979 splitDictName.insert(dotPos,
"_classdef");
2980 tmpCatalog.addFileName(splitDictName);
2981 return new std::ofstream(splitDictName.c_str());
2990 std::list<std::string> &diagnosticPragmas)
2992 static const std::string pattern(
"-Wno-");
2994 if (arg.find(pattern) != 0)
2996 if (arg ==
"-Wno-noexcept-type") {
3001 ROOT::TMetaUtils::ReplaceAll(arg, pattern,
"#pragma clang diagnostic ignored \"-W");
3003 diagnosticPragmas.push_back(arg);
3009 cling::Interpreter &interp)
3011 using namespace ROOT::TMetaUtils::AST2SourceTools;
3012 std::string fwdDecl;
3013 std::string initStr(
"{");
3014 auto &fwdDeclnArgsToSkipColl = normCtxt.GetTemplNargsToKeepMap();
3015 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3016 auto &clTemplDecl = *strigNargsToKeepPair.first;
3017 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3020 + std::to_string(strigNargsToKeepPair.second)
3023 if (!fwdDeclnArgsToSkipColl.empty())
3034 if (qt.isNull())
return qt;
3035 clang::QualType thisQt(qt);
3036 while (thisQt->isPointerType() ||
3037 thisQt->isReferenceType()) {
3038 thisQt = thisQt->getPointeeType();
3048 const cling::Interpreter &interp,
3049 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3051 std::list<std::string> headers;
3054 cling::Interpreter::PushTransactionRAII RAII(&interp);
3057 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3061 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3064 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3067 if (tArgQualType.isNull())
continue;
3068 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3069 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3076 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3078 if (baseQualType.isNull())
continue;
3079 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3080 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3085 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3086 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3088 if (fieldQualType.isNull()) continue ;
3089 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3090 if (fieldCxxRcd->hasDefinition())
3091 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3097 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3099 for (
auto & fPar : methodIt->parameters()) {
3101 if (fParQualType.isNull())
continue;
3102 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3103 if (fParCxxRcd->hasDefinition())
3104 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3109 if (retQualType.isNull())
continue;
3110 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3111 if (retCxxRcd->hasDefinition())
3119 std::string header = ROOT::TMetaUtils::GetFileName(rcd, interp);
3120 headers.emplace_back(header);
3133 if (
auto dclCtxt= rcd.getDeclContext()){
3134 if (! dclCtxt->isStdNamespace()){
3143 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3144 if (!clAsTmplSpecDecl)
return false;
3149 auto& astCtxt = rcd.getASTContext();
3150 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3151 for (
auto&& arg : templInstArgs.asArray()){
3153 auto argKind = arg.getKind();
3155 if (argKind == clang::TemplateArgument::Integral)
continue;
3159 auto argQualType = arg.getAsType();
3160 auto isPOD = argQualType.isPODType(astCtxt);
3162 if (isPOD)
continue;
3164 auto argType = argQualType.getTypePtr();
3165 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3168 if (isArgGoodForAutoParseMap)
continue;
3187 const cling::Interpreter &interp)
3189 std::set<const clang::CXXRecordDecl *> visitedDecls;
3190 std::unordered_set<std::string> buffer;
3191 std::string autoParseKey;
3194 for (
auto & annotatedRcd : annotatedRcds) {
3195 if (
const clang::CXXRecordDecl *cxxRcd =
3196 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3198 visitedDecls.clear();
3202 headers.remove_if([&buffer](
const std::string &
s) {
3203 return !buffer.insert(
s).
second;
3206 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3208 headersDeclsMap[autoParseKey] = headers;
3209 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3211 ROOT::TMetaUtils::Info(0,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3216 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3217 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3218 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3224 for (
auto & tDef : tDefDecls) {
3225 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3227 visitedDecls.clear();
3229 headers.push_back(ROOT::TMetaUtils::GetFileName(*tDef, interp));
3232 headers.remove_if([&buffer](
const std::string &
s) {
3233 return !buffer.insert(
s).
second;
3236 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3237 headersDeclsMap[autoParseKey] = headers;
3242 for (
auto & func : funcDecls) {
3243 std::list<std::string> headers = {ROOT::TMetaUtils::GetFileName(*func, interp)};
3244 headersDeclsMap[ROOT::TMetaUtils::GetQualifiedName(*func)] = headers;
3248 for (
auto & var : varDecls) {
3249 std::list<std::string> headers = {ROOT::TMetaUtils::GetFileName(*var, interp)};
3250 headersDeclsMap[ROOT::TMetaUtils::GetQualifiedName(*var)] = headers;
3254 for (
auto & en : enumDecls) {
3255 std::list<std::string> headers = {ROOT::TMetaUtils::GetFileName(*en, interp)};
3256 headersDeclsMap[ROOT::TMetaUtils::GetQualifiedName(*en)] = headers;
3264 const cling::Interpreter &interp)
3266 std::string newFwdDeclString;
3268 using namespace ROOT::TMetaUtils::AST2SourceTools;
3270 std::string fwdDeclString;
3272 std::unordered_set<std::string> fwdDecls;
3293 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3298 selectedDecls.begin(),
3299 [](
const ROOT::TMetaUtils::AnnotatedRecordDecl& rcd){return rcd.GetRecordDecl();});
3302 selectedDecls.push_back(TD);
3310 fwdDeclString += Decls2FwdDecls(selectedDecls,
IsLinkdefFile,interp);
3326 if (fwdDeclString.empty()) fwdDeclString =
"";
3327 return fwdDeclString;
3334 const std::string &detectedUmbrella,
3335 bool payLoadOnly =
false)
3337 std::string headerName;
3340 std::cout <<
"Class-headers Mapping:\n";
3341 std::string headersClassesMapString =
"";
3342 for (
auto const & classHeaders : headersClassesMap) {
3344 std::cout <<
" o " << classHeaders.first <<
" --> ";
3345 headersClassesMapString +=
"\"";
3346 headersClassesMapString += classHeaders.first +
"\"";
3347 for (
auto const & header : classHeaders.second) {
3348 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3349 headersClassesMapString +=
", " + headerName;
3351 std::cout <<
", " << headerName;
3356 std::cout << std::endl;
3357 headersClassesMapString +=
", \"@\",\n";
3359 headersClassesMapString +=
"nullptr";
3360 return headersClassesMapString;
3367 return !ROOT::TMetaUtils::IsHeaderName(filename);
3376 if (ROOT::TMetaUtils::BeginsWith(argument,
"--") && !ROOT::TMetaUtils::BeginsWith(argument,
"--param"))
return false;
3383 static const std::vector<std::string> namePrfxes {
3386 auto pos = find_if(namePrfxes.begin(),
3388 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3389 return namePrfxes.end() == pos;
3396 static const std::vector<std::string> uclNamePrfxes {
3400 static const std::set<std::string> unsupportedClassesNormNames{
3403 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3404 auto pos = find_if(uclNamePrfxes.begin(),
3405 uclNamePrfxes.end(),
3406 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3407 return uclNamePrfxes.end() == pos;
3417 for (
auto&& aRcd : annotatedRcds){
3418 auto clName = aRcd.GetNormalizedName();
3420 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3421 <<
"currently the support for its I/O is not yet available. Note that "
3422 << clName <<
", even if not selected, will be available for "
3423 <<
"interpreted code.\n";
3427 std::cerr <<
"Error: It is not necessary to explicitly select class "
3428 << clName <<
". I/O is supported for it transparently.\n";
3437class TRootClingCallbacks :
public cling::InterpreterCallbacks {
3439 std::list<std::string>& fFilesIncludedByLinkdef;
3440 bool isLocked =
false;
3442 TRootClingCallbacks(cling::Interpreter* interp, std::list<std::string>& filesIncludedByLinkdef):
3443 InterpreterCallbacks(interp),
3444 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3446 ~TRootClingCallbacks(){};
3448 virtual void InclusionDirective(clang::SourceLocation ,
const clang::Token & ,
3449 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3450 const clang::FileEntry * , llvm::StringRef ,
3451 llvm::StringRef ,
const clang::Module * )
3453 if (isLocked)
return;
3454 if (IsAngled)
return;
3455 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3456 auto curLexer = PP.getCurrentFileLexer();
3457 if (!curLexer)
return;
3458 auto fileEntry = curLexer->getFileEntry();
3459 if (!fileEntry)
return;
3460 auto thisFileName = fileEntry->getName();
3461 auto fileNameAsString = FileName.str();
3463 if (isThisLinkdef) {
3465 if (isTheIncludedLinkdef) {
3466 fFilesIncludedByLinkdef.clear();
3469 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3482 virtual void EnteredSubmodule(clang::Module* M,
3483 clang::SourceLocation ImportLoc,
3486 using namespace clang;
3487 if (llvm::StringRef(M->Name).endswith(
"ACLiC_dict")) {
3488 Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
3489 HeaderSearch& HS = PP.getHeaderSearchInfo();
3491 Module* CoreModule = HS.lookupModule(
"Core",
false);
3492 assert(M &&
"Must have module Core");
3493 PP.makeModuleVisible(CoreModule, ImportLoc);
3508class CheckModuleBuildClient :
public clang::DiagnosticConsumer {
3509 clang::DiagnosticConsumer *fChild;
3511 clang::ModuleMap &fMap;
3514 CheckModuleBuildClient(clang::DiagnosticConsumer *Child,
bool OwnsChild, clang::ModuleMap &
Map)
3515 : fChild(Child), fOwnsChild(OwnsChild), fMap(
Map)
3519 ~CheckModuleBuildClient()
3525 virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &
Info)
override
3527 using namespace clang::diag;
3533 std::string moduleName;
3534 const clang::Module *module =
nullptr;
3537 const auto &ID =
Info.getID();
3538 if (ID == remark_module_build || ID == remark_module_build_done) {
3539 moduleName =
Info.getArgStdStr(0);
3540 module = fMap.findModule(moduleName);
3546 "Couldn't find module %s in the available modulemaps. This"
3547 "prevents us from correctly diagnosing wrongly built modules.\n",
3548 moduleName.c_str());
3555 bool isROOTSystemModuleDiag = module && llvm::StringRef(moduleName).startswith(
"ROOT_");
3556 bool isSystemModuleDiag = module && module->IsSystem;
3557 if (!isROOTSystemModuleDiag && !isSystemModuleDiag)
3558 fChild->HandleDiagnostic(DiagLevel,
Info);
3560 if (ID == remark_module_build && !isROOTSystemModuleDiag && !isSystemModuleDiag) {
3562 "Had to build non-system module %s implicitly. You first need to\n"
3563 "generate the dictionary for %s or mark the C++ module as a system\n"
3564 "module if you provided your own system modulemap file:\n"
3565 "%s [system] { ... }\n",
3566 moduleName.c_str(), moduleName.c_str(), moduleName.c_str());
3571 virtual void clear()
override
3574 DiagnosticConsumer::clear();
3577 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3579 fChild->BeginSourceFile(LangOpts, PP);
3580 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3583 virtual void EndSourceFile()
override
3585 fChild->EndSourceFile();
3586 DiagnosticConsumer::EndSourceFile();
3589 virtual void finish()
override
3592 DiagnosticConsumer::finish();
3595 virtual bool IncludeInDiagnosticCounts()
const override {
return fChild->IncludeInDiagnosticCounts(); }
3599#if defined(_WIN32) && defined(_MSC_VER)
3603 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3604 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3605 ::_set_error_mode(_OUT_TO_STDERR);
3606 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3607 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3608 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3609 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3610 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3611 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3616static llvm::cl::opt<bool>
gOptForce(
"f", llvm::cl::desc(
"Overwrite <file>s."),
3618static llvm::cl::opt<bool>
gOptRootBuild(
"rootbuild", llvm::cl::desc(
"If we are building ROOT."),
3622 v = ROOT::TMetaUtils::kError,
3623 v0 = ROOT::TMetaUtils::kFatal,
3625 v2 = ROOT::TMetaUtils::kWarning,
3626 v3 = ROOT::TMetaUtils::kNote,
3627 v4 = ROOT::TMetaUtils::kInfo
3629static llvm::cl::opt<VerboseLevel>
3631 llvm::cl::values(clEnumVal(
v,
"Show errors."),
3632 clEnumVal(
v0,
"Show only fatal errors."),
3633 clEnumVal(
v1,
"Show errors (the same as -v)."),
3634 clEnumVal(
v2,
"Show warnings (default)."),
3635 clEnumVal(
v3,
"Show notes."),
3636 clEnumVal(
v4,
"Show information.")),
3640static llvm::cl::opt<bool>
3641gOptCint(
"cint", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3644static llvm::cl::opt<bool>
3645gOptReflex(
"reflex", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3648static llvm::cl::opt<bool>
3649gOptGccXml(
"gccxml", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3652static llvm::cl::opt<std::string>
3654 llvm::cl::desc(
"An ACLiC feature which exports the list of dependent libraries."),
3657static llvm::cl::opt<bool>
3659 llvm::cl::desc(
"Generates a pch file from a predefined set of headers. See makepch.py."),
3662static llvm::cl::opt<std::string>
3664 llvm::cl::desc(
"<output dictionary file>"),
3666static llvm::cl::opt<bool>
3667gOptC(
"c", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3669static llvm::cl::opt<bool>
3670gOptP(
"p", llvm::cl::desc(
"Deprecated, legacy flag which is ignored."),
3672static llvm::cl::list<std::string>
3674 llvm::cl::desc(
"Generate rootmap file."),
3676static llvm::cl::opt<std::string>
3678 llvm::cl::desc(
"Generate a rootmap file with the specified name."),
3680static llvm::cl::opt<bool>
3682 llvm::cl::desc(
"Generate a C++ module."),
3684static llvm::cl::list<std::string>
3686 llvm::cl::desc(
"Specify a C++ modulemap file."),
3689static llvm::cl::opt<bool>
3691 llvm::cl::desc(
"A single header including all headers instead of specifying them on the command line."),
3693static llvm::cl::opt<bool>
3695 llvm::cl::desc(
"If this library has multiple separate LinkDef files."),
3697static llvm::cl::opt<bool>
3699 llvm::cl::desc(
"Do not declare {using namespace std} in dictionary global scope."),
3701static llvm::cl::opt<bool>
3703 llvm::cl::desc(
"Generate minimal dictionary for interactivity (without IO information)."),
3705static llvm::cl::opt<bool>
3707 llvm::cl::desc(
"Split the dictionary into two parts: one containing the IO (ClassDef)\
3708information and another the interactivity support."),
3710static llvm::cl::opt<bool>
3713 llvm::cl::desc(
"Do not run the selection rules. Useful when in -onepcm mode."),
3715static llvm::cl::opt<std::string>
3717 llvm::cl::desc(
"The path to the library of the built dictionary."),
3719static llvm::cl::list<std::string>
3721 llvm::cl::desc(
"The list of dependent modules of the dictionary."),
3723static llvm::cl::list<std::string>
3725 llvm::cl::desc(
"Do not store the <path> in the dictionary."),
3729static llvm::cl::opt<bool>
3731 llvm::cl::desc(
"Does not generate #include <header> but expands the header content."),
3739static llvm::cl::opt<bool>
3742 llvm::cl::desc(
"Does not include the header files as it assumes they exist in the pch."),
3744static llvm::cl::opt<bool>
3746 llvm::cl::desc(
"Check the selection syntax only."),
3748static llvm::cl::opt<bool>
3750 llvm::cl::desc(
"Fail if there are warnings."),
3752static llvm::cl::opt<bool>
3754 llvm::cl::desc(
"Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."),
3756static llvm::cl::opt<std::string>
3758 llvm::cl::desc(
"Specify an isysroot."),
3761static llvm::cl::list<std::string>
3763 llvm::cl::desc(
"Specify an include path."),
3765static llvm::cl::list<std::string>
3767 llvm::cl::desc(
"Specify defined macros."),
3769static llvm::cl::list<std::string>
3771 llvm::cl::desc(
"Specify undefined macros."),
3773static llvm::cl::list<std::string>
3775 llvm::cl::desc(
"Specify compiler diagnostics options."),
3777static llvm::cl::list<std::string>
3779 llvm::cl::desc(
"<list of dictionary header files> <LinkDef file>"),
3781static llvm::cl::list<std::string>
3783 llvm::cl::desc(
"Consumes all unrecognized options."),
3786static llvm::cl::SubCommand
3789static llvm::cl::list<std::string>
3791 llvm::cl::desc(
"Consumes options and sends them to cling."),
3801 std::vector<std::string> &missingHeaders)
3804 std::vector<clang::Module::Header> moduleHeaders;
3805 ROOT::TMetaUtils::foreachHeaderInModule(*module,
3806 [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.push_back(
h); });
3808 bool foundAllHeaders =
true;
3813 for (
const std::string &header : modGen.
GetHeaders()) {
3814 bool headerFound =
false;
3815 for (
const clang::Module::Header &moduleHeader : moduleHeaders) {
3816 if (header == moduleHeader.NameAsWritten) {
3822 missingHeaders.push_back(header);
3823 foundAllHeaders =
false;
3826 return foundAllHeaders;
3832 StringRef LinkdefPath,
const std::string &moduleName)
3836 if (moduleName ==
"Krb5Auth" || moduleName ==
"GCocoa" || moduleName ==
"GQuartz")
3840 clang::CompilerInstance *CI = interpreter.getCI();
3841 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
3842 headerSearch.loadTopLevelSystemModules();
3845 clang::Module *module = headerSearch.lookupModule(StringRef(moduleName));
3850 moduleName.c_str());
3857 std::vector<std::string> missingHeaders;
3860 std::stringstream msgStream;
3861 msgStream <<
"warning: Couldn't find in "
3862 << module->PresumedModuleMapFile
3863 <<
" the following specified headers in "
3864 <<
"the module " << module->Name <<
":\n";
3865 for (
auto &
H : missingHeaders) {
3866 msgStream <<
" " <<
H <<
"\n";
3868 std::string warningMessage = msgStream.str();
3870 bool maybeUmbrella = modGen.
GetHeaders().size() == 1;
3881 ROOT::TMetaUtils::Info(
"CheckModuleValid, %s. You can silence this message by adding %s to the invocation.",
3882 warningMessage.c_str(),
3891 module->Name.c_str());
3901 llvm::StringRef moduleName = llvm::sys::path::filename(rdictName);
3902 moduleName.consume_front(
"lib");
3903 moduleName.consume_back(
".pcm");
3904 moduleName.consume_back(
"_rdict");
3912 bool isGenreflex =
false)
3915 auto &opts = llvm::cl::getRegisteredOptions();
3916 auto &optHelp = *opts[
"help"];
3917 llvm::cl::alias optHelpAlias1(
"h",
3918 llvm::cl::desc(
"Alias for -help"),
3919 llvm::cl::aliasopt(optHelp));
3920 llvm::cl::alias optHelpAlias2(
"?",
3921 llvm::cl::desc(
"Alias for -help"),
3922 llvm::cl::aliasopt(optHelp));
3928 const char *executableFileName = argv[0];
3930 llvm::sys::PrintStackTraceOnErrorSignal(executableFileName);
3931 llvm::PrettyStackTraceProgram X(argc, argv);
3934#if defined(R__WIN32) && !defined(R__WINGCC)
3939 for (
int iic = 1 ; iic < argc; ++iic) {
3940 std::string iiarg(argv[iic]);
3942 size_t len = iiarg.length();
3944 char *argviic =
new char[len + 1];
3945 strlcpy(argviic, iiarg.c_str(), len + 1);
3946 argv[iic] = argviic;
3954 llvm::cl::ParseCommandLineOptions(argc, argv,
"rootcling");
3958 std::vector<const char *> clingArgsC;
3959 clingArgsC.push_back(executableFileName);
3961 clingArgsC.push_back(
"-I");
3968 clingArgsC.push_back(Opt.c_str());
3970 auto interp = llvm::make_unique<cling::Interpreter>(clingArgsC.size(),
3972 llvmResourceDir.c_str());
3975 return interp->getDiagnostics().hasFatalErrorOccurred();
3978 std::string dictname;
3992 llvm::cl::PrintHelpMessage();
4004#if ROOT_VERSION_CODE < ROOT_VERSION(6,21,00)
4006 fprintf(stderr,
"warning: Please remove the deprecated flag -cint.\n");
4008 fprintf(stderr,
"warning: Please remove the deprecated flag -gccxml.\n");
4010 fprintf(stderr,
"warning: Please remove the deprecated flag -c.\n");
4012 fprintf(stderr,
"warning: Please remove the deprecated flag -p.\n");
4014 fprintf(stderr,
"warning: Please remove the deprecated flag -r.\n");
4017 if ((*
I)[0] ==
'+') {
4019 fprintf(stderr,
"warning: Please remove the deprecated flag %s\n",
I->c_str());
4025 for (
const std::string& Opt :
gOptSink)
4026 fprintf(stderr,
"warning: Please remove the deprecated flag %s\n", Opt.c_str());
4028# error "Remove this deprecated code"
4034 if ((fp = fopen(filein.c_str(),
"r")) == 0) {
4035 ROOT::TMetaUtils::Error(0,
"%s: The input list file %s does not exist\n", executableFileName, filein.c_str());
4062 ROOT::TMetaUtils::Error(0,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
4067 std::vector<std::string> clingArgs;
4068 clingArgs.push_back(executableFileName);
4069 clingArgs.push_back(
"-iquote.");
4075 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4081 if (GetErrorIgnoreLevel() >
kWarning)
4083 GetWarningsAreErrors() =
true;
4097 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4102 clingArgs.push_back(std::string(
"-D") + PPDefine);
4105 clingArgs.push_back(std::string(
"-U") + PPUndefine);
4108 clingArgs.push_back(std::string(
"-I") + llvm::sys::path::convert_to_slash(IncludePath));
4110 for (
const std::string &WDiag :
gOptWDiags) {
4111 const std::string FullWDiag = std::string(
"-W") + WDiag;
4115 clingArgs.push_back(FullWDiag);
4119 clingArgs.push_back(std::string(
"-I") + includeDir);
4121 std::vector<std::string> pcmArgs;
4122 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4123 auto thisArg = clingArgs[parg];
4124 auto isInclude = ROOT::TMetaUtils::BeginsWith(thisArg,
"-I");
4125 if (thisArg ==
"-c" ||
4129 unsigned int offset = 2;
4130 char c = thisArg[offset];
4131 while (
c ==
' ')
c = thisArg[++offset];
4135 [&](
const std::string& path){
4136 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4137 if (excludePathsEnd != excludePathPos)
continue;
4139 pcmArgs.push_back(thisArg);
4146 clingArgs.push_back(
"-D__ROOTCLING__");
4149 clingArgs.push_back(
"-DSYSTEM_TYPE_macosx");
4150#elif defined(R__WIN32)
4151 clingArgs.push_back(
"-DSYSTEM_TYPE_winnt");
4154 clingArgs.push_back(
"-D_XKEYCHECK_H");
4156 clingArgs.push_back(
"-DNOMINMAX");
4158 clingArgs.push_back(
"-DSYSTEM_TYPE_unix");
4161 clingArgs.push_back(
"-fsyntax-only");
4163 clingArgs.push_back(
"-fPIC");
4165 clingArgs.push_back(
"-Xclang");
4166 clingArgs.push_back(
"-fmodules-embed-all-files");
4167 clingArgs.push_back(
"-Xclang");
4168 clingArgs.push_back(
"-main-file-name");
4169 clingArgs.push_back(
"-Xclang");
4170 clingArgs.push_back((dictname +
".h").c_str());
4172 ROOT::TMetaUtils::SetPathsForRelocatability(clingArgs);
4178 std::string outputFile;
4180 StringRef moduleName;
4185 auto clingArgsInterpreter = clingArgs;
4194 clingArgsInterpreter.push_back(
"-fmodules");
4195 clingArgsInterpreter.push_back(
"-fno-implicit-module-maps");
4198 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + modulemap);
4200 clingArgsInterpreter.push_back(
"-fmodule-map-file=" +
4202 "/module.modulemap");
4204 if (llvm::sys::fs::exists(ModuleMapCWD))
4205 clingArgsInterpreter.push_back(
"-fmodule-map-file=" + ModuleMapCWD);
4212 clingArgsInterpreter.push_back(
"-fmodule-name");
4213 clingArgsInterpreter.push_back(moduleName.str());
4223 if (moduleName ==
"Core") {
4225 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_intrinsics.pcm").str().c_str());
4226 remove((moduleCachePath + llvm::sys::path::get_separator() +
"_Builtin_stddef_max_align_t.pcm").str().c_str());
4227 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime.pcm").str().c_str());
4228 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Cling_Runtime_Extra.pcm").str().c_str());
4230 remove((moduleCachePath + llvm::sys::path::get_separator() +
"Darwin.pcm").str().c_str());
4232 remove((moduleCachePath + llvm::sys::path::get_separator() +
"libc.pcm").str().c_str());
4234 remove((moduleCachePath + llvm::sys::path::get_separator() +
"std.pcm").str().c_str());
4235 remove((moduleCachePath + llvm::sys::path::get_separator() +
"cuda.pcm").str().c_str());
4236 remove((moduleCachePath + llvm::sys::path::get_separator() +
"boost.pcm").str().c_str());
4237 remove((moduleCachePath + llvm::sys::path::get_separator() +
"tinyxml2.pcm").str().c_str());
4238 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Config.pcm").str().c_str());
4239 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Rtypes.pcm").str().c_str());
4240 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_C.pcm").str().c_str());
4241 remove((moduleCachePath + llvm::sys::path::get_separator() +
"ROOT_Foundation_Stage1_NoRTTI.pcm").str().c_str());
4246 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" + moduleCachePath);
4250 clingArgsInterpreter.push_back(
"-v");
4253 std::vector<const char *> clingArgsC;
4254 for (
auto const &clingArg : clingArgsInterpreter) {
4256 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4257 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4260 clingArgsC.push_back(clingArg.c_str());
4264 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4265 cling::Interpreter* interpPtr =
nullptr;
4267 std::list<std::string> filesIncludedByLinkdef;
4270 clingArgsC.push_back(
"-resource-dir");
4271 clingArgsC.push_back(llvmResourceDir.c_str());
4272 clingArgsC.push_back(0);
4274 extraArgs = &clingArgsC[1];
4277 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4278 interpPtr->setCallbacks(std::move(callBacks));
4283 clingArgsC.push_back(
"-ffast-math");
4286 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4287 llvmResourceDir.c_str()));
4288 interpPtr = owningInterpPtr.get();
4295 interpPtr->loadModule(
"_Builtin_intrinsics",
true);
4297 cling::Interpreter &interp = *interpPtr;
4298 clang::CompilerInstance *CI = interp.getCI();
4300 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4301 CI->getSourceManager().setAllFilesAreTransient(
true);
4303 clang::Preprocessor &PP = CI->getPreprocessor();
4304 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4305 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4306 auto &diags = interp.getDiagnostics();
4313 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4317 auto recordingClient =
new CheckModuleBuildClient(diags.getClient(), diags.ownsClient(), moduleMap);
4318 diags.setClient(recordingClient,
true);
4320 if (ROOT::TMetaUtils::GetErrorIgnoreLevel() == ROOT::TMetaUtils::kInfo) {
4324 interp.DumpIncludePath();
4329 interp.printIncludedFiles(llvm::outs());
4330 llvm::outs() <<
"\n\n";
4331 llvm::outs().flush();
4334 const clang::LangOptions& LangOpts
4335 = interp.getCI()->getASTContext().getLangOpts();
4336#define LANGOPT(Name, Bits, Default, Description) \
4337 ROOT::TMetaUtils::Info(0, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4338#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4339#include "clang/Basic/LangOptions.def"
4343 interp.getOptions().ErrorOut =
true;
4344 interp.enableRawInput(
true);
4347 if (DepMod.endswith(
"_rdict.pcm")) {
4353 if (!interp.loadModule(DepMod,
false)) {
4360 if (interp.declare(
"namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4367 if (interp.declare(
"namespace std {} using namespace std;") != cling::Interpreter::kSuccess
4369 || interp.declare(
"#include <assert.h>\n"
4370 "#include <stdlib.h>\n"
4371 "#include <stddef.h>\n"
4372 "#include <string.h>\n"
4373 ) != cling::Interpreter::kSuccess
4374 || interp.declare(
"#include \"Rtypes.h\"\n"
4375 "#include \"TClingRuntime.h\"\n"
4376 "#include \"TObject.h\""
4377 ) != cling::Interpreter::kSuccess
4386 interp.declare(
"#include <string>");
4389 ROOT::TMetaUtils::TNormalizedCtxt normCtxt(interp.getLookupHelper());
4390 ROOT::TMetaUtils::TClingLookupHelper helper(interp, normCtxt, 0, 0,
nullptr);
4394 clingArgs.push_back(
"-D__CINT__");
4395 clingArgs.push_back(
"-D__MAKECINT__");
4401 std::string interpPragmaSource;
4402 std::string includeForSource;
4403 std::string interpreterDeclarations;
4404 std::string linkdef;
4410 if (isSelectionFile) {
4412 linkdef = optHeaderFileName;
4415 executableFileName, optHeaderFileName.c_str());
4421 std::string fullheader(optHeaderFileName);
4424 if (fullheader[fullheader.length() - 1] ==
'+') {
4425 fullheader.erase(fullheader.length() - 1);
4430 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4431 if (!isSelectionFile) {
4439 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4440 pcmArgs.push_back(header);
4442 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4447 bool hasSelectionFile = !linkdef.empty();
4448 unsigned expectedHeaderFilesSize = 1 + hasSelectionFile;
4465 if (!newName.empty())
4478 string incCurDir =
"-I";
4479 incCurDir += currentDirectory;
4480 pcmArgs.push_back(incCurDir);
4485 std::stringstream res;
4486 const char* delim=
"\n";
4487 std::copy(diagnosticPragmas.begin(),
4488 diagnosticPragmas.end(),
4489 std::ostream_iterator<std::string>(res, delim));
4490 interp.declare(res.str());
4493 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4495 IgnoringPragmaHandler(
const char* pragma):
4496 clang::PragmaNamespace(pragma) {}
4497 void HandlePragma(clang::Preprocessor &PP,
4498 clang::PragmaIntroducerKind Introducer,
4499 clang::Token &tok) {
4500 PP.DiscardUntilEndOfDirective();
4506 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4507 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4508 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4509 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4511 if (!interpreterDeclarations.empty() &&
4512 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4524 pcmArgs.push_back(linkdef);
4532 interp.AddIncludePath(inclPath);
4534 std::stringstream definesUndefinesStr;
4537 if (!definesUndefinesStr.str().empty())
4538 interp.declare(definesUndefinesStr.str());
4546 if (linkdef.empty()) {
4552 std::ofstream fileout;
4554 std::ostream *dictStreamPtr = NULL;
4555 std::ostream *dictStream =
nullptr;
4556 std::ostream *splitDictStream =
nullptr;
4557 std::ostream *splitDictStreamPtr =
nullptr;
4558 std::unique_ptr<std::ostream> splitDeleter(
nullptr);
4560 tempFileNamesCatalog tmpCatalog;
4565 dictStreamPtr = &fileout;
4566 if (!(*dictStreamPtr)) {
4572 dictStreamPtr = &std::cout;
4578 splitDeleter.reset(splitDictStreamPtr);
4580 splitDictStreamPtr = dictStreamPtr;
4583 dictStream = dictStreamPtr;
4584 splitDictStream = splitDictStreamPtr;
4586 size_t dh = main_dictname.rfind(
'.');
4587 if (dh != std::string::npos) {
4588 main_dictname.erase(dh);
4591 std::string main_dictname_copy(main_dictname);
4592 TMetaUtils::GetCppName(main_dictname, main_dictname_copy.c_str());
4610 string linkdefFilename;
4611 if (linkdef.empty()) {
4612 linkdefFilename =
"in memory";
4614 bool found =
Which(interp, linkdef.c_str(), linkdefFilename);
4622 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4625 namesForExclusion.push_back(std::make_pair(ROOT::TMetaUtils::propNames::pattern,
"ROOT::Meta::Selection*"));
4628 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4630 std::string extraIncludes;
4632 ROOT::TMetaUtils::RConstructorTypes constructorTypes;
4635 const unsigned int selRulesInitialSize = selectionRules.
Size();
4637 ROOT::Internal::DictSelectionReader dictSelReader(interp, selectionRules, CI->getASTContext(), normCtxt);
4639 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4643 int rootclingRetCode(0);
4645 if (linkdef.empty()) {
4650 clingArgs.push_back(
"-Ietc/cling/cint");
4652 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4653 llvmResourceDir.c_str())) {
4655 rootclingRetCode += 1;
4665 }
else if (isSelXML) {
4669 std::ifstream
file(linkdefFilename.c_str());
4670 if (
file.is_open()) {
4674 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4687 std::ifstream
file(linkdefFilename.c_str());
4688 if (
file.is_open()) {
4698 clingArgs.push_back(
"-Ietc/cling/cint");
4700 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4701 llvmResourceDir.c_str())) {
4703 rootclingRetCode += 1;
4738 *dictStream <<
"#include \"TBuffer.h\"\n"
4739 <<
"#include \"TVirtualObject.h\"\n"
4740 <<
"#include <vector>\n"
4741 <<
"#include \"TSchemaHelper.h\"\n\n";
4743 std::list<std::string> includes;
4745 for (
auto & incFile : includes) {
4746 *dictStream <<
"#include <" << incFile <<
">" << std::endl;
4748 *dictStream << std::endl;
4753 int scannerVerbLevel = 0;
4756 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4758 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4781 scan.
Scan(CI->getASTContext());
4783 bool has_input_error =
false;
4788 if (ROOT::TMetaUtils::GetErrorIgnoreLevel() != ROOT::TMetaUtils::kFatal &&
4790 !dictSelRulesPresent &&
4797 if (rootclingRetCode)
return rootclingRetCode;
4803 if (ROOT::TMetaUtils::ClassInfo__HasMethod(annRcd,
"Streamer", interp)) {
4804 if (annRcd.RequestNoInputOperator()) {
4805 int version = ROOT::TMetaUtils::GetClassVersion(annRcd, interp);
4816 if (has_input_error) {
4826 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4827 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4846 constructorTypes.push_back(ROOT::TMetaUtils::RConstructorType(
"TRootIOCtor", interp));
4847 constructorTypes.push_back(ROOT::TMetaUtils::RConstructorType(
"__void__", interp));
4848 constructorTypes.push_back(ROOT::TMetaUtils::RConstructorType(
"", interp));
4879 if (rootclingRetCode != 0) {
4880 return rootclingRetCode;
4899 std::string detectedUmbrella;
4900 for (
auto & arg : pcmArgs) {
4902 detectedUmbrella = arg;
4908 headersDeclsMap.clear();
4912 std::string headersClassesMapString =
"\"\"";
4913 std::string fwdDeclsString =
"\"\"";
4923 modGen.
WriteRegistrationSource(*dictStream, fwdDeclnArgsToKeepString, headersClassesMapString, fwdDeclsString,
4929 if (modGen.
IsPCH()) {
4932 if (!
CheckModuleValid(modGen, llvmResourceDir, interp, linkdefFilename, moduleName.str()))
4942 ofstream outputfile(liblist_filename.c_str(), ios::out);
4945 executableFileName, liblist_filename.c_str());
4947 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4948 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4950 outputfile <<
"# Now the list of classes\n";
4955 outputfile << annRcd.GetNormalizedName() << endl;
4962 if (0 != rootclingRetCode)
return rootclingRetCode;
4968 [](
const std::string &
a,
const std::string &
b) -> std::string {
4969 if (a.empty()) return b;
4970 else return a +
" " + b;
4975 std::list<std::string> classesNames;
4976 std::list<std::string> classesNamesForRootmap;
4977 std::list<std::string> classesDefsList;
4981 classesNamesForRootmap,
4985 std::list<std::string> enumNames;
4990 std::list<std::string> varNames;
4995 if (0 != rootclingRetCode)
return rootclingRetCode;
4998 if (rootMapNeeded) {
5000 std::list<std::string> nsNames;
5009 rootmapLibName.c_str());
5012 std::unordered_set<std::string> headersToIgnore;
5015 headersToIgnore.insert(optHeaderFileName.c_str());
5017 std::list<std::string> typedefsRootmapLines;
5025 classesNamesForRootmap,
5027 typedefsRootmapLines,
5033 if (0 != rootclingRetCode)
return 1;
5043 cling::Interpreter::PushTransactionRAII RAII(&interp);
5044 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5048 rootclingRetCode += ROOT::TMetaUtils::GetNumberOfErrors();
5055 if(rootclingRetCode == 0) {
5056 rootclingRetCode += tmpCatalog.commit();
5061 return rootclingRetCode;
5072 unsigned int numberOfHeaders = 0;
5073 for (std::vector<std::string>::iterator it = headersNames.begin();
5074 it != headersNames.end(); ++it) {
5075 const std::string headername(*it);
5076 if (ROOT::TMetaUtils::IsHeaderName(headername)) {
5080 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5081 headername.c_str());
5084 return numberOfHeaders;
5090 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5093 unsigned int argvCounter = 0;
5094 for (
int i = 1; i < argc; ++i) {
5095 if (!ROOT::TMetaUtils::BeginsWith(argv[i - 1],
"-") &&
5096 !ROOT::TMetaUtils::BeginsWith(argv[i],
"-")) {
5097 args.push_back(argv[i]);
5099 }
else if (argvCounter) {
5100 argv[i - argvCounter] = argv[i];
5107 std::cout <<
"Args: \n";
5108 for (std::vector<std::string>::iterator it = args.begin();
5109 it < args.end(); ++it) {
5110 std::cout << i <<
") " << *it << std::endl;
5123 size_t result = filename.find_last_of(
'.');
5124 if (std::string::npos != result) {
5125 filename.erase(result);
5126 filename.append(newExtension);
5136 const unsigned int size(str.size());
5137 char *
a =
new char[size + 1];
5139 memcpy(
a, str.c_str(), size);
5155 std::vector<std::string> &ofilesnames)
5157 ofilesnames.reserve(headersNames.size());
5159 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5160 it != headersNames.end(); ++it) {
5161 std::string ofilename(*it);
5163 ofilesnames.push_back(ofilename);
5170 const std::vector<std::string> &argsToBeAdded,
5171 const std::string &optName =
"")
5173 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5174 it != argsToBeAdded.end(); ++it) {
5182 const std::vector<std::string> &argsToBeAdded,
5183 const std::string &optName =
"")
5185 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5186 it != argsToBeAdded.end(); ++it) {
5187 if (optName.length()) {
5197 const std::string &selectionFileName,
5198 const std::string &targetLibName,
5200 const std::vector<std::string> &pcmsNames,
5201 const std::vector<std::string> &includes,
5202 const std::vector<std::string> &preprocDefines,
5203 const std::vector<std::string> &preprocUndefines,
5204 const std::vector<std::string> &warnings,
5205 const std::string &rootmapFileName,
5206 const std::string &rootmapLibName,
5207 bool interpreteronly,
5210 bool writeEmptyRootPCM,
5212 bool noIncludePaths,
5213 bool noGlobalUsingStd,
5214 const std::vector<std::string> &headersNames,
5215 bool failOnWarnings,
5216 const std::string &ofilename)
5220 std::vector<char *> argvVector;
5231 std::string dictLocation;
5237 std::string newRootmapLibName(rootmapLibName);
5238 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5239 if (headersNames.size() != 1) {
5241 "*** genreflex: No rootmap lib and several header specified!\n");
5244 newRootmapLibName =
"lib";
5245 newRootmapLibName += cleanHeaderName;
5251 std::string newRootmapFileName(rootmapFileName);
5252 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5253 newRootmapFileName = dictLocation + newRootmapFileName;
5258 if (!newRootmapFileName.empty()) {
5264 if (!newRootmapLibName.empty()) {
5270 if (interpreteronly)
5278 if (!targetLibName.empty()) {
5288 if (noGlobalUsingStd)
5298 if (writeEmptyRootPCM)
5321 if (!selectionFileName.empty()) {
5325 const int argc = argvVector.size();
5329 std::cout <<
"Rootcling commandline:\n";
5330 for (
int i = 0; i < argc; i++)
5331 std::cout << i <<
") " << argvVector[i] << std::endl;
5334 char **argv = & (argvVector[0]);
5339 for (
int i = 0; i < argc; i++)
5340 delete [] argvVector[i];
5342 return rootclingReturnCode;
5351 const std::string &selectionFileName,
5352 const std::string &targetLibName,
5354 const std::vector<std::string> &pcmsNames,
5355 const std::vector<std::string> &includes,
5356 const std::vector<std::string> &preprocDefines,
5357 const std::vector<std::string> &preprocUndefines,
5358 const std::vector<std::string> &warnings,
5359 const std::string &rootmapFileName,
5360 const std::string &rootmapLibName,
5361 bool interpreteronly,
5364 bool writeEmptyRootPCM,
5366 bool noIncludePaths,
5367 bool noGlobalUsingStd,
5368 const std::vector<std::string> &headersNames,
5369 bool failOnWarnings,
5370 const std::string &outputDirName_const =
"")
5372 std::string outputDirName(outputDirName_const);
5374 std::vector<std::string> ofilesNames;
5377 if (!outputDirName.empty() && !ROOT::TMetaUtils::EndsWith(outputDirName,
gPathSeparator)) {
5381 std::vector<std::string> namesSingleton(1);
5382 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5383 namesSingleton[0] = headersNames[i];
5384 std::string ofilenameFullPath(ofilesNames[i]);
5385 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5386 ofilenameFullPath = outputDirName + ofilenameFullPath;
5408 if (returnCode != 0)
5423 std::vector<std::string> &values)
5426 if (options[oIndex]) {
5427 const int nVals = options[oIndex].count();
5428 values.reserve(nVals);
5429 int optionIndex = 0;
5432 << optionIndex <<
"/" << nVals <<
" "
5433 << opt->arg << std::endl;
5435 values.push_back(opt->arg);
5446 const char *descriptor)
5448 if (options[optionIndex]) {
5450 "*** genereflex: %s is not supported anymore.\n",
5463 isGood |= ROOT::TMetaUtils::EndsWith(
name,
".dylib");
5507 enum optionIndex { UNKNOWN,
5538 enum optionTypes { NOTYPE, STRING } ;
5541 const char *genreflexUsage =
5542 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5543 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5546 const char *selectionFilenameUsage =
5547 "-s, --selection_file\tSelection filename\n"
5548 " Class selection file to specify for which classes the dictionary\n"
5549 " will be generated. The final set can be crafted with exclusion and\n"
5550 " exclusion rules.\n"
5551 " Properties can be specified. Some have special meaning:\n"
5552 " - name [string] name of the entity to select with an exact matching\n"
5553 " - pattern [string] name with wildcards (*) to select entities\n"
5554 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5555 " file where the C++ entities reside and not to C++ entities themselves.\n"
5556 " - transient/persistent [string: true/false] The fields to which they are\n"
5557 " applied will not be persistified if requested.\n"
5558 " - comment [string]: what you could write in code after an inline comment\n"
5559 " without \"//\". For example comment=\"!\" or \"||\".\n"
5560 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5561 " Default value is 'false'\n"
5562 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5563 " to 'true'. Default value is 'false'\n"
5567 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5568 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5569 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5570 " [noInputOperator=\"true/false\"] />\n"
5571 " <class name=\"classname\" >\n"
5572 " <field name=\"m_transient\" transient=\"true\"/>\n"
5573 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5574 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5575 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5577 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5578 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5579 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5582 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5583 " <method name=\"unwanted\" />\n"
5588 " If no selection file is specified, the class with the filename without\n"
5589 " extension will be selected, i.e. myClass.h as argument without any\n"
5590 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5592 const char *outputFilenameUsage =
5593 "-o, --output\tOutput filename\n"
5594 " Output file name. If an existing directory is specified instead of a file,\n"
5595 " then a filename will be build using the name of the input file and will\n"
5596 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5597 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5598 " have unique names.\n";
5601 const char *targetLib =
5602 "-l, --library\tTarget library\n"
5603 " The flag -l must be followed by the name of the library that will\n"
5604 " contain the object file corresponding to the dictionary produced by\n"
5605 " this invocation of genreflex.\n"
5606 " The name takes priority over the one specified for the rootmapfile.\n"
5607 " The name influences the name of the created pcm:\n"
5608 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5609 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5610 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5611 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5612 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5614 const char *rootmapUsage =
5615 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5616 " This file lists the autoload keys. For example classes for which the\n"
5617 " reflection information is provided.\n"
5618 " The format of the rootmap is the following:\n"
5619 " - Forward declarations section\n"
5620 " - Libraries sections\n"
5621 " Rootmaps can be concatenated together, for example with the cat util.\n"
5622 " In order for ROOT to pick up the information in the rootmaps, they\n"
5623 " have to be located in the library path and have the .rootmap extension.\n"
5624 " An example rootmap file could be:\n"
5626 " template <class T> class A;\n"
5627 " [ libMyLib.so ]\n"
5628 " class A<double>\n"
5633 const char *rootmapLibUsage =
5634 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5667 "--multiDict\tSupport for many dictionaries in one library\n"
5668 " Form correct pcm names if multiple dictionaries will be in the same\n"
5669 " library (needs target library switch. See its documentation).\n"
5676 "" ,
"noGlobalUsingStd" ,
5678 "--noGlobalUsingStd\tDo not declare {using namespace std} in the dictionary global scope\n"
5679 " All header files must have sumbols from std:: namespace fully qualified\n"
5685 "s" ,
"selection_file" ,
5687 selectionFilenameUsage
5701 "" ,
"rootmap-lib" ,