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" ,
5709 "" ,
"interpreteronly",
5711 "--interpreteronly\tDo not generate I/O related information.\n"
5712 " Generate minimal dictionary required for interactivity.\n"
5720 "--split\tSplit the dictionary\n"
5721 " Split in two the dictionary, isolating the part with\n"
5722 " ClassDef related functions in a separate file.\n"
5730 "-m \tPcm file loaded before any header (option can be repeated).\n"
5747 "-v, --verbose\tPrint some debug information.\n"
5755 "--debug\tPrint all debug information.\n"
5763 "--quiet\tPrint only warnings and errors (default).\n"
5771 "--silent\tPrint no information at all.\n"
5777 "" ,
"writeEmptyPCM",
5779 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5787 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5796 "--help\tPrint usage and exit.\n"
5802 "",
"fail_on_warnings",
5804 "--fail_on_warnings\tFail on warnings and errors.\n"
5810 "",
"selSyntaxOnly",
5812 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5818 "" ,
"noIncludePaths",
5820 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5859 "" ,
"no_membertypedefs" ,
5867 "" ,
"no_templatetypedefs" ,
5875 std::vector<std::string> headersNames;
5876 const int originalArgc = argc;
5878 const int extractedArgs =
extractArgs(argc, argv, headersNames);
5880 const int offset = 1;
5881 argc -= offset + extractedArgs;
5886 std::vector<ROOT::option::Option> options(stats.
options_max);
5887 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5893 if (parse.
error()) {
5899 if (options[HELP] || originalArgc == 1) {
5905 if (0 == numberOfHeaders) {
5910 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kNote;
5916 std::string verbosityOption(
"-v2");
5917 if (options[SILENT]) verbosityOption =
"-v0";
5918 if (options[
VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5919 if (options[
DEBUG]) verbosityOption =
"-v4";
5924 std::string selectionFileName;
5925 if (options[SELECTIONFILENAME]) {
5926 selectionFileName = options[SELECTIONFILENAME].arg;
5927 if (!ROOT::TMetaUtils::EndsWith(selectionFileName,
".xml")) {
5929 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
5930 selectionFileName.c_str());
5945 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
5946 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
5949 std::string targetLibName;
5950 if (options[TARGETLIB]) {
5951 targetLibName = options[TARGETLIB].arg;
5954 "Invalid target library extension: filename is %s and extension %s is expected!\n",
5955 targetLibName.c_str(),
5959 if (options[ROOTMAP]) {
5964 bool isCxxmodule = options[CXXMODULE];
5966 bool multidict =
false;
5967 if (options[MULTIDICT]) multidict =
true;
5969 bool noGlobalUsingStd =
false;
5970 if (options[NOGLOBALUSINGSTD]) noGlobalUsingStd =
true;
5972 if (multidict && targetLibName.empty()) {
5974 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
5978 bool interpreteronly =
false;
5979 if (options[INTERPRETERONLY])
5980 interpreteronly =
true;
5982 bool doSplit =
false;
5986 bool writeEmptyRootPCM =
false;
5987 if (options[WRITEEMPTYROOTPCM])
5988 writeEmptyRootPCM =
true;
5990 bool selSyntaxOnly =
false;
5991 if (options[SELSYNTAXONLY]) {
5992 selSyntaxOnly =
true;
5995 bool noIncludePaths =
false;
5996 if (options[NOINCLUDEPATHS]) {
5997 noIncludePaths =
true;
6000 bool failOnWarnings =
false;
6001 if (options[FAILONWARNINGS]) {
6002 failOnWarnings =
true;
6011 std::vector<std::string> pcmsNames;
6015 std::vector<std::string> preprocDefines;
6019 std::vector<std::string> preprocUndefines;
6023 std::vector<std::string> includes;
6027 std::vector<std::string> warnings;
6038 int returnValue = 0;
6039 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6043 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6100 assert(!
gDriverConfig &&
"Driver configuration already set!");
6114 if (std::string::npos != exeName.find(
"genreflex"))
6121 if (ROOT::TMetaUtils::GetNumberOfErrors()){
Select classes and assign properties using C++ syntax.
The file contains utilities which are foundational and could be used across the core component of ROO...
This is the only file required to use The Lean Mean C++ Option Parser.
void Info(const char *location, const char *msgfmt,...)
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
const AttributesMap_t & GetAttributes() const
std::unordered_map< std::string, std::string > AttributesMap_t
const std::list< VariableSelectionRule > & GetFieldSelectionRules() const
bool LoadIncludes(std::string &extraInclude)
bool Parse(SelectionRules &sr, llvm::StringRef code, const std::vector< std::string > &parserArgs, const char *llvmdir)
void WriteUmbrellaHeader(std::ostream &out) const
Write a header file pulling in the content of this module through a series of #defined,...
const std::string & GetUmbrellaName() const
const std::vector< std::string > & GetIncludePaths() const
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes, bool hasCxxModule) const
const std::vector< std::string > & GetHeaders() const
void WriteContentHeader(std::ostream &out) const
Write a header file describing the content of this module through a series of variables inside the na...
int GetErrorCount() const
const std::string & GetModuleFileName() const
std::ostream & WritePPUndefines(std::ostream &out) const
Write #ifdef FOO.
void ParseArgs(const std::vector< std::string > &args)
Parse -I -D -U headers.h SomethingLinkdef.h.
const std::string & GetContentName() const
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO.
A parsed option from the command line together with its argument if it has one.
Option * next()
Returns a pointer to the next element of the linked list or NULL if called on last().
Checks argument vectors for validity and parses them into data structures that are easier to work wit...
bool error()
Returns true if an unrecoverable error occurred while parsing options.
void Scan(const clang::ASTContext &C)
std::vector< ROOT::TMetaUtils::AnnotatedRecordDecl > ClassColl_t
const DeclsSelRulesMap_t & GetDeclsSelRulesMap() const
FunctionColl_t fSelectedFunctions
std::vector< const clang::FunctionDecl * > FunctionColl_t
NamespaceColl_t fSelectedNamespaces
TypedefColl_t fSelectedTypedefs
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
std::map< const clang::Decl *, const BaseSelectionRule * > DeclsSelRulesMap_t
EnumColl_t fSelectedEnums
std::vector< const clang::TypedefNameDecl * > TypedefColl_t
std::vector< const clang::VarDecl * > VariableColl_t
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
VariableColl_t fSelectedVariables
std::vector< const clang::EnumDecl * > EnumColl_t
ClassColl_t fSelectedClasses
RooAbsArg * find(const char *name) const
Find object with given name in list.
The class representing the collection of selection rules.
bool AreAllSelectionRulesUsed() const
bool SearchNames(cling::Interpreter &interp)
void PrintSelectionRules() const
unsigned int Size() const
void SetSelectionFileType(ESelectionFileTypes fileType)
bool Parse(const std::string &fileName, SelectionRules &out)
static bool FromCygToNativePath(std::string &path)
Type
enumeration specifying the integration types.
EvaluateInfo init(std::vector< RooRealProxy > parameters, std::vector< ArrayWrapper * > wrappers, std::vector< double * > arrays, size_t begin, size_t batchSize)
const std::string & GetPathSeparator()
std::string GetCurrentDir()
std::string MakePathRelative(const std::string &path, const std::string &base, bool isBuildingROOT=false)
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
void printUsage(OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping.
R__EXTERN SchemaRuleClassMap_t gReadRules
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
R__EXTERN SchemaRuleClassMap_t gReadRawRules
RooArgSet S(const RooAbsArg &v1)
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
void Init(TClassEdit::TInterpreterLookupHelper *helper)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
static constexpr double s
static constexpr double ns
static constexpr double second
constexpr Double_t E()
Base of natural log:
void header2outputName(std::string &fileName)
Replace the extension with "_rflx.cpp".
void AddToArgVectorSplit(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
void changeExtension(std::string &filename, const std::string &newExtension)
int invokeRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &ofilename)
int invokeManyRootCling(const std::string &verbosity, const std::string &selectionFileName, const std::string &targetLibName, bool multiDict, const std::vector< std::string > &pcmsNames, const std::vector< std::string > &includes, const std::vector< std::string > &preprocDefines, const std::vector< std::string > &preprocUndefines, const std::vector< std::string > &warnings, const std::string &rootmapFileName, const std::string &rootmapLibName, bool interpreteronly, bool doSplit, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, bool noGlobalUsingStd, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &outputDirName_const="")
Get the right ofilenames and invoke several times rootcling One invokation per header.
unsigned int checkHeadersNames(std::vector< std::string > &headersNames)
Loop on arguments: stop at the first which starts with -.
void headers2outputsNames(const std::vector< std::string > &headersNames, std::vector< std::string > &ofilesnames)
Get a proper name for the output file.
char * string2charptr(const std::string &str)
The caller is responsible for deleting the string!
unsigned int extractArgs(int argc, char **argv, std::vector< std::string > &args)
Extract the arguments from the command line.
void AddToArgVector(std::vector< char * > &argvVector, const std::vector< std::string > &argsToBeAdded, const std::string &optName="")
int FinalizeStreamerInfoWriting(cling::Interpreter &interp, bool writeEmptyRootPCM=false)
Make up for skipping RegisterModule, now that dictionary parsing is done and these headers cannot be ...
std::list< std::string > CollapseIdenticalNamespaces(const std::list< std::string > &fwdDeclarationsList)
If two identical namespaces are there, just declare one only Example: namespace A { namespace B { fwd...
bool ParsePragmaLine(const std::string &line, const char *expectedTokens[], size_t *end=0)
Check whether the #pragma line contains expectedTokens (0-terminated array).
static llvm::cl::opt< bool > gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
int RootClingMain(int argc, char **argv, bool isGenreflex=false)
static llvm::StringRef GetModuleNameFromRdictName(llvm::StringRef rdictName)
static llvm::cl::opt< bool > gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), llvm::cl::cat(gRootclingOptions), llvm::cl::init("-"))
int STLContainerStreamer(const clang::FieldDecl &m, int rwmode, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
Create Streamer code for an STL container.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static llvm::cl::opt< bool > gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
static llvm::cl::list< std::string > gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), llvm::cl::cat(gRootclingOptions))
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
static void MaybeSuppressWin32CrashDialogs()
void RecordDeclCallback(const clang::RecordDecl *recordDecl)
void CheckClassNameForRootMap(const std::string &classname, map< string, string > &autoloads)
bool Which(cling::Interpreter &interp, const char *fname, string &pname)
Find file name in path specified via -I statements to Cling.
void AdjustRootMapNames(std::string &rootmapFileName, std::string &rootmapLibName)
void AddNamespaceSTDdeclaration(std::ostream &dictStream)
static llvm::cl::list< std::string > gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
map< string, string > gAutoloads
static llvm::cl::opt< bool > gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), llvm::cl::cat(gRootclingOptions))
static void CheckForMinusW(std::string arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
static llvm::cl::opt< bool > gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), llvm::cl::cat(gRootclingOptions))
void ExtractFilePath(const std::string &path, std::string &dirname)
Extract the path from a fullpath finding the last \ or / according to the content in gPathSeparator.
int STLStringStreamer(const clang::FieldDecl &m, int rwmode, std::ostream &dictStream)
Create Streamer code for a standard string object.
void CreateDictHeader(std::ostream &dictStream, const std::string &main_dictname)
const char * GetExePath()
Returns the executable path name, used e.g. by SetRootSys().
const std::string gPathSeparator(ROOT::TMetaUtils::GetPathSeparator())
static llvm::cl::list< std::string > gOptBareClingSink(llvm::cl::OneOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes options and sends them to cling."), llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gBareClingSubcommand))
bool InheritsFromTObject(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static bool InjectModuleUtilHeader(const char *argv0, TModuleGenerator &modGen, cling::Interpreter &interp, bool umbrella)
Write the extra header injected into the module: umbrella header if (umbrella) else content header.
static llvm::cl::list< std::string > gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), llvm::cl::cat(gRootclingOptions))
int ExtractClassesListAndDeclLines(RScanner &scan, std::list< std::string > &classesList, std::list< std::string > &classesListForRootmap, std::list< std::string > &fwdDeclarationsList, const cling::Interpreter &interpreter)
void ParseRootMapFileNewFormat(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map, using the new format.
static llvm::cl::OptionCategory gRootclingOptions("rootcling common options")
void ExtractHeadersForDecls(const RScanner::ClassColl_t &annotatedRcds, const RScanner::TypedefColl_t tDefDecls, const RScanner::FunctionColl_t funcDecls, const RScanner::VariableColl_t varDecls, const RScanner::EnumColl_t enumDecls, HeadersDeclsMap_t &headersClassesMap, HeadersDeclsMap_t &headersDeclsMap, const cling::Interpreter &interp)
static llvm::cl::opt< bool > gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static bool GenerateAllDict(TModuleGenerator &modGen, clang::CompilerInstance *compilerInstance, const std::string ¤tDirectory)
Generates a PCH from the given ModuleGenerator and CompilerInstance.
void LoadLibraryMap(const std::string &fileListName, map< string, string > &autoloads)
Fill the map of libraries to be loaded in presence of a class Transparently support the old and new r...
std::ostream * CreateStreamPtrForSplitDict(const std::string &dictpathname, tempFileNamesCatalog &tmpCatalog)
Transform name of dictionary.
void WriteNamespaceInit(const clang::NamespaceDecl *cl, cling::Interpreter &interp, std::ostream &dictStream)
Write the code to initialize the namespace name and the initialization object.
void AnnotateAllDeclsForPCH(cling::Interpreter &interp, RScanner &scan)
We need annotations even in the PCH: // !, // || etc.
size_t GetFullArrayLength(const clang::ConstantArrayType *arrayType)
static llvm::cl::opt< bool > gOptSplit("split", llvm::cl::desc("Split the dictionary into two parts: one containing the IO (ClassDef)\
information and another the interactivity support."), llvm::cl::cat(gRootclingOptions))
bool ProcessAndAppendIfNotThere(const std::string &el, std::list< std::string > &el_list, std::unordered_set< std::string > &el_set)
Separate multiline strings.
static llvm::cl::opt< bool > gOptNoGlobalUsingStd("noGlobalUsingStd", llvm::cl::desc("Do not declare {using namespace std} in dictionary global scope."), llvm::cl::cat(gRootclingOptions))
const ROOT::Internal::RootCling::DriverConfig * gDriverConfig
static llvm::cl::list< std::string > gOptModuleDependencies("m", llvm::cl::desc("The list of dependent modules of the dictionary."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::SubCommand gBareClingSubcommand("bare-cling", "Call directly cling and exit.")
static llvm::cl::opt< bool > gOptInterpreterOnly("interpreteronly", llvm::cl::desc("Generate minimal dictionary for interactivity (without IO information)."), llvm::cl::cat(gRootclingOptions))
void WriteArrayDimensions(const clang::QualType &type, std::ostream &dictStream)
Write "[0]" for all but the 1st dimension.
void GetMostExternalEnclosingClassName(const clang::DeclContext &theContext, std::string &ctxtName, const cling::Interpreter &interpreter, bool treatParent=true)
Extract the proper autoload key for nested classes The routine does not erase the name,...
std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, cling::Interpreter &interp)
int ExtractAutoloadKeys(std::list< std::string > &names, const COLL &decls, const cling::Interpreter &interp)
static llvm::cl::opt< std::string > gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), llvm::cl::cat(gRootclingOptions))
int GenerateFullDict(std::ostream &dictStream, cling::Interpreter &interp, RScanner &scan, const ROOT::TMetaUtils::RConstructorTypes &ctorTypes, bool isSplit, bool isGenreflex, bool writeEmptyRootPCM)
void WriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
int ROOT_rootcling_Driver(int argc, char **argv, const ROOT::Internal::RootCling::DriverConfig &config)
bool IsGoodForAutoParseMap(const clang::RecordDecl &rcd)
Check if the class good for being an autoparse key.
void GetMostExternalEnclosingClassNameFromDecl(const clang::Decl &theDecl, std::string &ctxtName, const cling::Interpreter &interpreter)
static llvm::cl::opt< bool > gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::cat(gRootclingOptions))
void SetRootSys()
Set the ROOTSYS env var based on the executable location.
bool CheckInputOperator(const char *what, const char *proto, const string &fullname, const clang::RecordDecl *cl, cling::Interpreter &interp)
Check if the specified operator (what) has been properly declared if the user has requested a custom ...
void GenerateNecessaryIncludes(std::ostream &dictStream, const std::string &includeForSource, const std::string &extraIncludes)
void StrcpyArg(string &dest, const char *original)
Copy the command line argument, stripping MODULE/inc if necessary.
static llvm::cl::list< std::string > gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), llvm::cl::cat(gRootclingOptions))
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
static llvm::cl::opt< bool > gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), llvm::cl::cat(gRootclingOptions))
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
static std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
static llvm::cl::opt< bool > gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), llvm::cl::cat(gRootclingOptions))
const char * CopyArg(const char *original)
If the argument starts with MODULE/inc, strip it to make it the name we can use in #includes.
string GetNonConstMemberName(const clang::FieldDecl &m, const string &prefix="")
Return the name of the data member so that it can be used by non-const operation (so it includes a co...
static llvm::cl::list< std::string > gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), llvm::cl::cat(gRootclingOptions))
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
void ExtractSelectedNamespaces(RScanner &scan, std::list< std::string > &nsList)
Loop on selected classes and put them in a list.
static bool IncludeHeaders(const std::vector< std::string > &headers, cling::Interpreter &interpreter)
Includes all given headers in the interpreter.
clang::QualType GetPointeeTypeIfPossible(const clang::QualType &qt)
Get the pointee type if possible.
void AnnotateDecl(clang::CXXRecordDecl &CXXRD, const RScanner::DeclsSelRulesMap_t &declSelRulesMap, cling::Interpreter &interpreter, bool isGenreflex)
static llvm::cl::opt< VerboseLevel > gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), llvm::cl::values(clEnumVal(v, "Show errors."), clEnumVal(v0, "Show only fatal errors."), clEnumVal(v1, "Show errors (the same as -v)."), clEnumVal(v2, "Show warnings (default)."), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), llvm::cl::cat(gRootclingOptions))
void GenerateLinkdef(llvm::cl::list< std::string > &InputFiles, std::string &code_for_parser)
static llvm::cl::opt< std::string > gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::Required, llvm::cl::desc("<output dictionary file>"), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< std::string > gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include <header> but expands the header content."), llvm::cl::cat(gRootclingOptions))
bool isPointerToPointer(const clang::FieldDecl &m)
static bool WriteAST(StringRef fileName, clang::CompilerInstance *compilerInstance, StringRef iSysRoot, clang::Module *module=nullptr)
Write the AST of the given CompilerInstance to the given File while respecting the given isysroot.
int CreateNewRootMapFile(const std::string &rootmapFileName, const std::string &rootmapLibName, const std::list< std::string > &classesDefsList, const std::list< std::string > &classesNames, const std::list< std::string > &nsNames, const std::list< std::string > &tdNames, const std::list< std::string > &enNames, const std::list< std::string > &varNames, const HeadersDeclsMap_t &headersClassesMap, const std::unordered_set< std::string > headersToIgnore)
Generate a rootmap file in the new format, like { decls } namespace A { namespace B { template <typen...
bool IsSelectionXml(const char *filename)
bool IsGoodLibraryName(const std::string &name)
static llvm::cl::opt< bool > gOptReflex("reflex", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), llvm::cl::cat(gRootclingOptions))
static llvm::cl::list< std::string > gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::OneOrMore, llvm::cl::desc("<list of dictionary header files> <LinkDef file>"), llvm::cl::cat(gRootclingOptions))
bool IsSelectionFile(const char *filename)
const std::string GenerateStringFromHeadersForClasses(const HeadersDeclsMap_t &headersClassesMap, const std::string &detectedUmbrella, bool payLoadOnly=false)
Generate a string for the dictionary from the headers-classes map.
bool IsSupportedClassName(const char *name)
static bool ModuleContainsHeaders(TModuleGenerator &modGen, clang::Module *module, std::vector< std::string > &missingHeaders)
Returns true iff a given module (and its submodules) contains all headers needed by the given ModuleG...
static llvm::cl::opt< bool > gOptIgnoreExistingDict("r", llvm::cl::desc("Deprecated. Similar to -f but it ignores the dictionary generation. \
When -r is present rootcling becomes a tool to generate rootmaps (and capability files)."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptForce("f", llvm::cl::desc("Overwrite <file>s."), llvm::cl::cat(gRootclingOptions))
static void AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules)
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
static llvm::cl::list< std::string > gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), llvm::cl::cat(gRootclingOptions))
int CheckClassesForInterpreterOnlyDicts(cling::Interpreter &interp, RScanner &scan)
bool InheritsFromTSelector(const clang::RecordDecl *cl, const cling::Interpreter &interp)
static void EmitTypedefs(const std::vector< const clang::TypedefNameDecl * > &tdvec)
std::map< std::string, std::list< std::string > > HeadersDeclsMap_t
bool Namespace__HasMethod(const clang::NamespaceDecl *cl, const char *name, const cling::Interpreter &interp)
static llvm::cl::list< std::string > gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), llvm::cl::cat(gRootclingOptions))
bool IsCorrectClingArgument(const std::string &argument)
Check if the argument is a sane cling argument.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)
void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream &dictStream, bool autoLoad=false)
Write the code to set the class name and the initialization object.
static llvm::cl::list< std::string > gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the <path> in the dictionary."), llvm::cl::cat(gRootclingOptions))
std::list< std::string > RecordDecl2Headers(const clang::CXXRecordDecl &rcd, const cling::Interpreter &interp, std::set< const clang::CXXRecordDecl * > &visitedDecls)
Extract the list of headers necessary for the Decl.
void EmitStreamerInfo(const char *normName)
static llvm::cl::opt< bool > gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), llvm::cl::cat(gRootclingOptions))
bool HasPath(const std::string &name)
Check if file has a path.
static llvm::cl::opt< std::string > gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, llvm::cl::cat(gRootclingOptions))
static llvm::cl::opt< bool > gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), llvm::cl::cat(gRootclingOptions))
int CheckForUnsupportedClasses(const RScanner::ClassColl_t &annotatedRcds)
Check if the list of selected classes contains any class which is not supported.
llvm::StringRef GrabIndex(const clang::FieldDecl &member, int printError)
GrabIndex returns a static string (so use it or copy it immediately, do not call GrabIndex twice in t...
static void EmitEnums(const std::vector< const clang::EnumDecl * > &enumvec)
static bool CheckModuleValid(TModuleGenerator &modGen, const std::string &resourceDir, cling::Interpreter &interpreter, StringRef LinkdefPath, const std::string &moduleName)
Check moduleName validity from modulemap. Check if this module is defined or not.
bool CheckClassDef(const clang::RecordDecl &cl, const cling::Interpreter &interp)
Return false if the class does not have ClassDef even-though it should.
bool NeedsSelection(const char *name)
int extractMultipleOptions(std::vector< ROOT::option::Option > &options, int oIndex, std::vector< std::string > &values)
Extract from options multiple values with the same option.
cling::Interpreter *(* fTCling__GetInterpreter)()
bool(* fCloseStreamerInfoROOTFile)(bool writeEmptyRootPCM)
void(* fAddEnumToROOTFile)(const char *tdname)
void(* fInitializeStreamerInfoROOTFile)(const char *filename)
const char *(* fTROOT__GetIncludeDir)()
void(* fAddAncestorPCMROOTFile)(const char *pcmName)
void(* fAddTypedefToROOTFile)(const char *tdname)
const char *(* fTROOT__GetEtcDir)()
void(* fAddStreamerInfoToROOTFile)(const char *normName)
const char ***(* fTROOT__GetExtraInterpreterArgs)()
static ArgStatus None(const Option &, bool)
For options that don't take an argument: Returns ARG_NONE.
Describes an option, its help text (usage) and how it should be parsed.
static option::ArgStatus Required(const option::Option &option, bool msg)
Determines the minimum lengths of the buffer and options arrays used for Parser.
unsigned options_max
Number of elements needed for an options[] array to be used for parsing the same argument vectors tha...
unsigned buffer_max
Number of elements needed for a buffer[] array to be used for parsing the same argument vectors that ...
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.
#define dest(otri, vertexptr)