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"
38#include <unordered_map>
39#include <unordered_set>
51#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/AST/Mangle.h"
75#include "clang/Basic/Diagnostic.h"
76#include "clang/Basic/MemoryBufferCache.h"
77#include "clang/Frontend/CompilerInstance.h"
78#include "clang/Frontend/FrontendActions.h"
79#include "clang/Frontend/FrontendDiagnostic.h"
80#include "clang/Lex/HeaderSearch.h"
81#include "clang/Lex/Preprocessor.h"
82#include "clang/Lex/ModuleMap.h"
83#include "clang/Lex/Pragma.h"
84#include "clang/Sema/Sema.h"
85#include "clang/Serialization/ASTWriter.h"
86#include "cling/Utils/AST.h"
88#include "llvm/Bitcode/BitstreamWriter.h"
89#include "llvm/Support/Path.h"
90#include "llvm/Support/PrettyStackTrace.h"
91#include "llvm/Support/Signals.h"
96#include "TClingUtils.h"
116#include <mach-o/dyld.h>
121#define strcasecmp _stricmp
122#define strncasecmp _strnicmp
132 template <
typename T>
struct IsPointerTClassCopy {
135 template <
typename T>
struct IsPointerTClassCopy<
T*> {
169static void EmitTypedefs(
const std::vector<const clang::TypedefNameDecl *> &tdvec)
173 for (
const auto td : tdvec)
176static void EmitEnums(
const std::vector<const clang::EnumDecl *> &enumvec)
180 for (
const auto en : enumvec) {
182 if (clang::isa<clang::TranslationUnitDecl>(en->getDeclContext())
183 || clang::isa<clang::LinkageSpecDecl>(en->getDeclContext())
184 || clang::isa<clang::NamespaceDecl>(en->getDeclContext()))
193 char fixedLength[1024];
194 char *currWorkDir = fixedLength;
196 char *result = currWorkDir;
201 if (fixedLength != currWorkDir) {
202 delete [] currWorkDir;
204 currWorkDir =
new char[len];
207 result = ::_getcwd(currWorkDir, len);
209 result = getcwd(currWorkDir, len);
211 }
while (result == 0 && errno == ERANGE);
220 if (fixedLength != currWorkDir) {
221 delete [] currWorkDir;
230 static std::string exepath;
233 exepath = _dyld_get_image_name(0);
235#if defined(__linux) || defined(__linux__)
236 char linkname[PATH_MAX];
242 snprintf(linkname, PATH_MAX,
"/proc/%i/exe", pid);
243 int ret = readlink(linkname, buf, 1024);
244 if (ret > 0 && ret < 1024) {
250 char *buf =
new char[MAX_MODULE_NAME32 + 1];
251 ::GetModuleFileName(NULL, buf, MAX_MODULE_NAME32 + 1);
253 while ((p = strchr(p,
'\\')))
259 return exepath.c_str();
271 std::string result(header);
273 const char *currWorkDir = currentDirectory.c_str();
274 size_t lenCurrWorkDir = strlen(currWorkDir);
275 if (result.substr(0, lenCurrWorkDir) == currWorkDir) {
279 result.erase(0, lenCurrWorkDir);
283 int posInc = result.find(
"/inc/");
285 result = result.substr(posInc + 5, -1);
294 const cling::Interpreter &interp)
296 return ROOT::TMetaUtils::ClassInfo__HasMethod(cl,
name, interp);
302 const std::list<VariableSelectionRule> &fieldSelRules,
311 if (fieldSelRules.empty())
return;
313 clang::ASTContext &
C = decl.getASTContext();
314 clang::SourceRange commentRange;
316 const std::string declName(decl.getNameAsString());
318 for (std::list<VariableSelectionRule>::const_iterator it = fieldSelRules.begin();
319 it != fieldSelRules.end(); ++it) {
321 if (declName == varName) {
324 BaseSelectionRule::AttributesMap_t::iterator iter;
325 std::string userDefinedProperty;
326 for (iter = attrMap.begin(); iter != attrMap.end(); ++iter) {
327 const std::string &
name = iter->first;
328 const std::string &value = iter->second;
335 if (
name == propNames::iotype &&
336 (decl.getType()->isArrayType() || decl.getType()->isPointerType())) {
337 const char *msg =
"Data member \"%s\" is an array or a pointer. "
338 "It is not possible to assign to it the iotype \"%s\". "
339 "This transformation is possible only with data members "
340 "which are not pointers or arrays.\n";
342 msg, varName.c_str(), value.c_str());
350 if (
name == propNames::comment) {
351 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, value, 0));
355 if ((
name == propNames::transient && value ==
"true") ||
356 (
name == propNames::persistent && value ==
"false")) {
357 userDefinedProperty = propNames::comment + propNames::separator +
"!";
361 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C,
"!", 0));
366 userDefinedProperty =
name + propNames::separator + value;
369 decl.addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
380 cling::Interpreter &interpreter,
388 using namespace clang;
389 SourceLocation commentSLoc;
390 llvm::StringRef comment;
392 ASTContext &
C = CXXRD.getASTContext();
393 Sema &
S = interpreter.getCI()->getSema();
395 SourceRange commentRange;
398 clang::Decl *declBaseClassPtr =
static_cast<clang::Decl *
>(&CXXRD);
399 auto declSelRulePair = declSelRulesMap.
find(declBaseClassPtr->getCanonicalDecl());
400 if (declSelRulePair == declSelRulesMap.end()){
401 const std::string thisClassName(CXXRD.getName());
402 ROOT::TMetaUtils::Error(
"AnnotateDecl",
"Cannot find class %s in the list of selected classes.\n",thisClassName.c_str());
407 if (thisClassBaseSelectionRule) {
410 BaseSelectionRule::AttributesMap_t::iterator iter;
411 std::string userDefinedProperty;
412 for (
auto const & attr : thisClassBaseSelectionRule->
GetAttributes()) {
413 const std::string &
name = attr.first;
415 const std::string &value = attr.second;
416 userDefinedProperty =
name + ROOT::TMetaUtils::propNames::separator + value;
418 CXXRD.addAttr(
new(
C) AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
425 for (CXXRecordDecl::decl_iterator
I = CXXRD.decls_begin(),
426 E = CXXRD.decls_end();
I !=
E; ++
I) {
430 if (!(*I)->isImplicit()
431 && (isa<CXXMethodDecl>(*
I) || isa<FieldDecl>(*
I) || isa<VarDecl>(*
I))) {
435 SourceLocation maybeMacroLoc = (*I)->getLocation();
436 bool isClassDefMacro = maybeMacroLoc.isMacroID() &&
S.findMacroSpelling(maybeMacroLoc,
"ClassDef");
437 if (isClassDefMacro) {
438 while (isa<NamedDecl>(*
I) && cast<NamedDecl>(*I)->getName() !=
"DeclFileLine") {
443 comment = ROOT::TMetaUtils::GetComment(**
I, &commentSLoc);
444 if (comment.size()) {
447 commentRange = SourceRange(commentSLoc, commentSLoc.getLocWithOffset(comment.size()));
449 if (isClassDefMacro) {
450 CXXRD.addAttr(
new(
C) AnnotateAttr(commentRange,
C, comment.str(), 0));
451 }
else if (!isGenreflex) {
457 (*I)->addAttr(
new(
C) AnnotateAttr(commentRange,
C, comment.str(), 0));
462 if (isGenreflex && thisClassSelectionRule != 0) {
466 if (FieldDecl *fieldDecl = dyn_cast<FieldDecl>(*
I)) {
478 llvm::APInt len = arrayType->getSize();
479 while (
const clang::ConstantArrayType *subArrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual())) {
480 len *= subArrayType->getSize();
481 arrayType = subArrayType;
483 return len.getLimitedValue();
489 const cling::Interpreter &interp)
491 static const clang::CXXRecordDecl *TObject_decl
492 = ROOT::TMetaUtils::ScopeSearch(
"TObject", interp,
true , 0);
494 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
495 return ROOT::TMetaUtils::IsBase(clxx, TObject_decl,
nullptr, interp);
501 const cling::Interpreter &interp)
503 static const clang::CXXRecordDecl *TObject_decl
504 = ROOT::TMetaUtils::ScopeSearch(
"TSelector", interp,
false , 0);
506 return ROOT::TMetaUtils::IsBase(llvm::dyn_cast<clang::CXXRecordDecl>(cl), TObject_decl,
nullptr, interp);
513 size_t len = strlen(filename);
515 if (strlen(filename) >= xmllen) {
516 return (0 == strcasecmp(filename + (len - xmllen),
".xml"));
542 if (exepath && *exepath) {
544 char *ep =
new char[PATH_MAX];
545 if (!realpath(exepath, ep)) {
546 fprintf(stderr,
"rootcling: error getting realpath of rootcling!");
547 strlcpy(ep, exepath, PATH_MAX);
550 int nche = strlen(exepath) + 1;
551 char *ep =
new char[nche];
552 strlcpy(ep, exepath, nche);
556 if ((
s = strrchr(ep,
'/'))) {
558 int removesubdirs = 2;
559 if (!strncmp(
s + 1,
"rootcling_stage1.exe", 20)) {
563 }
else if (!strncmp(
s + 1,
"rootcling_stage1", 16)) {
568 for (
int i = 1;
s && i < removesubdirs; ++i) {
570 s = strrchr(ep,
'/');
581 int ncha = strlen(ep) + 10;
582 char *env =
new char[ncha];
583 snprintf(env, ncha,
"ROOTSYS=%s", ep);
603 const char *expectedTokens[],
607 if (
line[0] !=
'#')
return false;
609 for (
const char **iToken = expectedTokens; *iToken; ++iToken) {
610 while (isspace(
line[pos])) ++pos;
611 size_t lenToken = strlen(*iToken);
612 if (
line.compare(pos, lenToken, *iToken)) {
631 if (recordDecl->hasOwningModule()) {
632 clang::Module *M = recordDecl->getOwningModule()->getTopLevelModule();
635 std::string qual_name;
641 if (need.length() &&
gLibsNeeded.find(need) == string::npos) {
650 if (classname.find(
':') == std::string::npos)
return;
653 int slen = classname.size();
654 for (
int k = 0; k < slen; ++k) {
655 if (classname[k] ==
':') {
656 if (k + 1 >= slen || classname[k + 1] !=
':') {
661 string base = classname.substr(0, k);
666 autoloads[base] =
"";
670 }
else if (classname[k] ==
'<') {
682 std::string classname;
686 if (
line.find(
"Library.") != 0)
continue;
688 int pos =
line.find(
":", 8);
689 classname =
line.substr(8, pos - 8);
691 ROOT::TMetaUtils::ReplaceAll(classname,
"@@",
"::");
692 ROOT::TMetaUtils::ReplaceAll(classname,
"-",
" ");
695 while (
line[0] ==
' ')
line.replace(0, 1,
"");
699 if (classname ==
"ROOT::TImpProxy") {
703 autoloads[classname] =
line;
718 const std::unordered_map<char, unsigned int> keyLenMap = {{
'c', 6}, {
'n', 10}, {
't', 8}};
721 if (
line ==
"{ decls }") {
723 if (
line[0] ==
'[')
break;
726 const char firstChar =
line[0];
727 if (firstChar ==
'[') {
729 libs =
line.substr(1,
line.find(
']') - 1);
730 while (libs[0] ==
' ') libs.replace(0, 1,
"");
731 }
else if (0 != keyLenMap.count(firstChar)) {
732 unsigned int keyLen = keyLenMap.at(firstChar);
733 keyname =
line.substr(keyLen,
line.length() - keyLen);
735 autoloads[keyname] = libs;
745void LoadLibraryMap(
const std::string &fileListName, map<string, string> &autoloads)
747 std::ifstream filelist(fileListName.c_str());
749 std::string filename;
752 while (filelist >> filename) {
754 if (llvm::sys::fs::is_directory(filename))
continue;
756 ifstream
file(filename.c_str());
760 bool new_format = (
line[0] ==
'[' ||
line[0] ==
'{') ;
762 file.seekg(0, std::ios::beg);
783 const string &fullname,
784 const clang::RecordDecl *cl,
785 cling::Interpreter &interp)
788 const clang::FunctionDecl *method
789 = ROOT::TMetaUtils::GetFuncWithProto(llvm::dyn_cast<clang::Decl>(cl->getDeclContext()), what,
proto, interp,
793 clang::TranslationUnitDecl *TU =
794 cl->getASTContext().getTranslationUnitDecl();
795 method = ROOT::TMetaUtils::GetFuncWithProto(TU, what,
proto, interp,
798 bool has_input_error =
false;
799 if (method != 0 && (method->getAccess() == clang::AS_public || method->getAccess() == clang::AS_none)) {
800 std::string filename = ROOT::TMetaUtils::GetFileName(*method, interp);
801 if (strstr(filename.c_str(),
"TBuffer.h") != 0 ||
802 strstr(filename.c_str(),
"Rtypes.h") != 0) {
804 has_input_error =
true;
807 has_input_error =
true;
809 if (has_input_error) {
811 const char *maybeconst =
"";
812 const char *mayberef =
"&";
813 if (what[strlen(what) - 1] ==
'<') {
814 maybeconst =
"const ";
818 "in this version of ROOT, the option '!' used in a linkdef file\n"
819 " implies the actual existence of customized operators.\n"
820 " The following declaration is now required:\n"
821 " TBuffer &%s(TBuffer &,%s%s *%s);\n", what, maybeconst, fullname.c_str(), mayberef);
823 return has_input_error;
834 ROOT::TMetaUtils::GetQualifiedName(fullname, *cl);
835 int ncha = fullname.length() + 13;
836 char *
proto =
new char[ncha];
848 return has_input_error;
854bool CheckClassDef(
const clang::RecordDecl &cl,
const cling::Interpreter &interp)
858 bool hasClassDef = ROOT::TMetaUtils::ClassInfo__HasMethod(&cl,
"Class_Version", interp);
860 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(&cl);
864 bool isAbstract = clxx->isAbstract();
867 std::string qualName;
868 ROOT::TMetaUtils::GetQualifiedName(qualName, cl);
869 const char *qualName_c = qualName.c_str();
871 "because it inherits from TObject but does not "
872 "have its own ClassDef.\n",
885 if (
m.getType().isConstQualified()) {
886 string ret =
"const_cast< ";
888 ROOT::TMetaUtils::GetQualifiedName(type_name,
m.getType(),
m);
889 if (type_name.substr(0,6)==
"const ") {
890 ret += type_name.c_str()+6;
896 ret +=
m.getName().str();
900 return prefix +
m.getName().str();
910 const cling::Interpreter &interp,
911 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
912 std::ostream &dictStream)
915 std::string mTypename;
916 ROOT::TMetaUtils::GetQualifiedName(mTypename,
m.getType(),
m);
918 const clang::CXXRecordDecl *clxx = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(ROOT::TMetaUtils::GetUnderlyingRecordDecl(
m.getType()));
925 clang::QualType utype(ROOT::TMetaUtils::GetUnderlyingType(
m.getType()), 0);
926 Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
928 if (clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
930 const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
931 if (!tmplt_specialization)
return 0;
934 string stlType(ROOT::TMetaUtils::ShortTypeName(mTypename.c_str()));
936 stlName = ROOT::TMetaUtils::ShortTypeName(
m.getName().str().c_str());
938 string fulName1, fulName2;
939 const char *tcl1 = 0, *tcl2 = 0;
940 const clang::TemplateArgument &arg0(tmplt_specialization->getTemplateArgs().get(0));
941 clang::QualType ti = arg0.getAsType();
943 if (ROOT::TMetaUtils::ElementStreamer(dictStream,
m, ti, 0, rwmode, interp)) {
945 fulName1 = ti.getAsString();
948 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
949 clang::QualType tmplti = arg1.getAsType();
950 if (ROOT::TMetaUtils::ElementStreamer(dictStream,
m, tmplti, 0, rwmode, interp)) {
952 fulName2 = tmplti.getAsString();
959 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
965 if (arrayType->getArrayElementTypeNoTypeQual()->isPointerType()) {
969 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
971 }
else if (
m.getType()->isPointerType()) {
976 dictStream <<
" {" << std::endl;
978 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
983 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
986 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
989 dictStream <<
" delete *" << stlName.c_str() <<
";" << std::endl
990 <<
" *" << stlName.c_str() <<
" = new " << stlType.c_str() <<
";" << std::endl
991 <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
994 dictStream <<
" delete " << stlName.c_str() <<
"[R__l];" << std::endl
995 <<
" " << stlName.c_str() <<
"[R__l] = new " << stlType.c_str() <<
";" << std::endl
996 <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1000 dictStream <<
" R__stl.clear();" << std::endl;
1003 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1004 <<
" if (R__tcl1==0) {" << std::endl
1005 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1006 << fulName1.c_str() <<
"!\");" << std::endl
1007 <<
" return;" << std::endl
1008 <<
" }" << std::endl;
1011 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1012 <<
" if (R__tcl2==0) {" << std::endl
1013 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1014 << fulName2.c_str() <<
"!\");" << std::endl
1015 <<
" return;" << std::endl
1016 <<
" }" << std::endl;
1019 dictStream <<
" int R__i, R__n;" << std::endl
1020 <<
" R__b >> R__n;" << std::endl;
1023 dictStream <<
" R__stl.reserve(R__n);" << std::endl;
1025 dictStream <<
" for (R__i = 0; R__i < R__n; R__i++) {" << std::endl;
1027 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, arg0.getAsType(),
"R__t", rwmode, interp, tcl1);
1029 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1030 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, arg1.getAsType(),
"R__t2", rwmode, interp, tcl2);
1049 std::string keyName(ti.getAsString());
1050 dictStream <<
" typedef " << keyName <<
" Value_t;" << std::endl
1051 <<
" std::pair<Value_t const, " << tmplt_specialization->getTemplateArgs().get(1).getAsType().getAsString() <<
" > R__t3(R__t,R__t2);" << std::endl
1052 <<
" R__stl.insert(R__t3);" << std::endl;
1060 dictStream <<
" R__stl.insert(R__t);" << std::endl;
1065 dictStream <<
" R__stl.push_back(R__t);" << std::endl;
1068 dictStream <<
" R__stl.push_front(R__t);" << std::endl;
1073 dictStream <<
" }" << std::endl
1074 <<
" }" << std::endl;
1075 if (isArr) dictStream <<
" }" << std::endl;
1081 dictStream <<
" for (Int_t R__l = 0; R__l < " << len <<
"; R__l++) {" << std::endl;
1083 dictStream <<
" {" << std::endl;
1086 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
";" << std::endl;
1089 dictStream <<
" " << stlType.c_str() <<
" &R__stl = " << stlName.c_str() <<
"[R__l];" << std::endl;
1092 dictStream <<
" " << stlType.c_str() <<
" &R__stl = **" << stlName.c_str() <<
";" << std::endl;
1095 dictStream <<
" " << stlType.c_str() <<
" &R__stl = *" << stlName.c_str() <<
"[R__l];" << std::endl;
1099 dictStream <<
" int R__n=int(R__stl.size());" << std::endl
1100 <<
" R__b << R__n;" << std::endl
1101 <<
" if(R__n) {" << std::endl;
1104 dictStream <<
" TClass *R__tcl1 = TBuffer::GetClass(typeid(" << fulName1.c_str() <<
"));" << std::endl
1105 <<
" if (R__tcl1==0) {" << std::endl
1106 <<
" Error(\"" << stlName.c_str() <<
" streamer\",\"Missing the TClass object for "
1107 << fulName1.c_str() <<
"!\");" << std::endl
1108 <<
" return;" << std::endl
1109 <<
" }" << std::endl;
1112 dictStream <<
" TClass *R__tcl2 = TBuffer::GetClass(typeid(" << fulName2.c_str() <<
"));" << std::endl
1113 <<
" if (R__tcl2==0) {" << std::endl
1114 <<
" Error(\"" << stlName.c_str() <<
"streamer\",\"Missing the TClass object for " << fulName2.c_str() <<
"!\");" << std::endl
1115 <<
" return;" << std::endl
1116 <<
" }" << std::endl;
1119 dictStream <<
" " << stlType.c_str() <<
"::iterator R__k;" << std::endl
1120 <<
" for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {" << std::endl;
1122 const clang::TemplateArgument &arg1(tmplt_specialization->getTemplateArgs().get(1));
1123 clang::QualType tmplti = arg1.getAsType();
1124 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, ti,
"((*R__k).first )", rwmode, interp, tcl1);
1125 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, tmplti,
"((*R__k).second)", rwmode, interp, tcl2);
1127 ROOT::TMetaUtils::ElementStreamer(dictStream,
m, ti,
"(*R__k)" , rwmode, interp, tcl1);
1130 dictStream <<
" }" << std::endl
1131 <<
" }" << std::endl
1132 <<
" }" << std::endl;
1133 if (isArr) dictStream <<
" }" << std::endl;
1145 std::string mTypenameStr;
1146 ROOT::TMetaUtils::GetQualifiedName(mTypenameStr,
m.getType(),
m);
1148 const char *mTypeName = ROOT::TMetaUtils::ShortTypeName(mTypenameStr.c_str());
1149 if (!strcmp(mTypeName,
"string")) {
1151 std::string fieldname =
m.getName().str();
1154 if (
m.getType()->isConstantArrayType()) {
1155 if (
m.getType().getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1156 dictStream <<
"// Array of pointer to std::string are not supported (" << fieldname <<
"\n";
1158 std::stringstream fullIdx;
1159 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1162 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1163 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1164 fullIdx <<
"[R__i" << dim <<
"]";
1165 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1168 dictStream <<
" { TString R__str; R__str.Streamer(R__b); "
1169 << fieldname << fullIdx.str() <<
" = R__str.Data();}" << std::endl;
1172 dictStream <<
" { TString R__str; R__str.Streamer(R__b); ";
1173 if (
m.getType()->isPointerType())
1174 dictStream <<
"if (*" << fieldname <<
") delete *" << fieldname <<
"; (*"
1175 << fieldname <<
" = new string(R__str.Data())); }" << std::endl;
1177 dictStream << fieldname <<
" = R__str.Data(); }" << std::endl;
1181 if (
m.getType()->isPointerType())
1182 dictStream <<
" { TString R__str; if (*" << fieldname <<
") R__str = (*"
1183 << fieldname <<
")->c_str(); R__str.Streamer(R__b);}" << std::endl;
1184 else if (
m.getType()->isConstantArrayType()) {
1185 std::stringstream fullIdx;
1186 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
m.getType().getTypePtr());
1189 dictStream <<
" for (int R__i" << dim <<
"=0; R__i" << dim <<
"<"
1190 << arrayType->getSize().getLimitedValue() <<
"; ++R__i" << dim <<
" )" << std::endl;
1191 fullIdx <<
"[R__i" << dim <<
"]";
1192 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1195 dictStream <<
" { TString R__str(" << fieldname << fullIdx.str() <<
".c_str()); R__str.Streamer(R__b);}" << std::endl;
1197 dictStream <<
" { TString R__str = " << fieldname <<
".c_str(); R__str.Streamer(R__b);}" << std::endl;
1208 if (
m.getType()->isPointerType()) {
1209 if (
m.getType()->getPointeeType()->isPointerType()) {
1221 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1223 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1225 dictStream <<
"[0]";
1226 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1236 bool add_template_keyword = ROOT::TMetaUtils::NeedTemplateKeyword(cl);
1241 int enclSpaceNesting = 0;
1243 if (ROOT::TMetaUtils::GetNameWithinNamespace(fullname, clsname, nsname, cl)) {
1244 enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl);
1248 dictStream <<
"#include \"TInterpreter.h\"\n";
1250 dictStream <<
"//_______________________________________"
1251 <<
"_______________________________________" << std::endl;
1252 if (add_template_keyword) dictStream <<
"template <> ";
1253 dictStream <<
"atomic_TClass_ptr " << clsname <<
"::fgIsA(0); // static to hold class pointer" << std::endl
1256 <<
"//_______________________________________"
1257 <<
"_______________________________________" << std::endl;
1258 if (add_template_keyword) dictStream <<
"template <> ";
1259 dictStream <<
"const char *" << clsname <<
"::Class_Name()" << std::endl <<
"{" << std::endl
1260 <<
" return \"" << fullname <<
"\";" << std::endl <<
"}" << std::endl << std::endl;
1262 dictStream <<
"//_______________________________________"
1263 <<
"_______________________________________" << std::endl;
1264 if (add_template_keyword) dictStream <<
"template <> ";
1265 dictStream <<
"const char *" << clsname <<
"::ImplFileName()" << std::endl <<
"{" << std::endl
1266 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1267 <<
"*)0x0)->GetImplFileName();" << std::endl <<
"}" << std::endl << std::endl
1269 <<
"//_______________________________________"
1270 <<
"_______________________________________" << std::endl;
1271 if (add_template_keyword) dictStream <<
"template <> ";
1272 dictStream <<
"int " << clsname <<
"::ImplFileLine()" << std::endl <<
"{" << std::endl
1273 <<
" return ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1274 <<
"*)0x0)->GetImplFileLine();" << std::endl <<
"}" << std::endl << std::endl
1276 <<
"//_______________________________________"
1277 <<
"_______________________________________" << std::endl;
1278 if (add_template_keyword) dictStream <<
"template <> ";
1279 dictStream <<
"TClass *" << clsname <<
"::Dictionary()" << std::endl <<
"{" << std::endl;
1283 dictStream <<
" gInterpreter->EnableAutoLoading();\n"
1284 <<
" gInterpreter->AutoLoad(\"" << fullname <<
"\");\n";
1285 dictStream <<
" fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::" << fullname
1286 <<
"*)0x0)->GetClass();" << std::endl
1287 <<
" return fgIsA;\n"
1288 <<
"}" << std::endl << std::endl
1290 <<
"//_______________________________________"
1291 <<
"_______________________________________" << std::endl;
1292 if (add_template_keyword) dictStream <<
"template <> ";
1293 dictStream <<
"TClass *" << clsname <<
"::Class()" << std::endl <<
"{" << std::endl;
1295 dictStream <<
" Dictionary();\n";
1297 dictStream <<
" if (!fgIsA.load()) { R__LOCKGUARD(gInterpreterMutex); fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::";
1298 dictStream << fullname <<
"*)0x0)->GetClass(); }" << std::endl;
1300 dictStream <<
" return fgIsA;" << std::endl
1301 <<
"}" << std::endl << std::endl;
1303 while (enclSpaceNesting) {
1304 dictStream <<
"} // namespace " << nsname << std::endl;
1313 cling::Interpreter &interp,
1314 std::ostream &dictStream)
1316 if (cl->isAnonymousNamespace()) {
1322 string classname = ROOT::TMetaUtils::GetQualifiedName(*cl).c_str();
1324 TMetaUtils::GetCppName(mappedname, classname.c_str());
1328 if (classname !=
"ROOT") {
1329 nesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream,cl);
1332 dictStream <<
" namespace ROOT {" << std::endl;
1335 dictStream <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance();" << std::endl;
1339 dictStream <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();" << std::endl;
1340 dictStream << std::endl
1342 <<
" // Function generating the singleton type initializer" << std::endl
1345 <<
" inline ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1346 <<
" {" << std::endl
1348 <<
" ::ROOT::TGenericClassInfo *GenerateInitInstance()" << std::endl
1349 <<
" {" << std::endl
1352 <<
" static ::ROOT::TGenericClassInfo " << std::endl
1354 <<
" instance(\"" << classname.c_str() <<
"\", ";
1357 dictStream <<
"::" << classname.c_str() <<
"::Class_Version(), ";
1359 dictStream <<
"0 /*version*/, ";
1362 std::string filename = ROOT::TMetaUtils::GetFileName(*cl, interp);
1363 for (
unsigned int i = 0; i < filename.length(); i++) {
1364 if (filename[i] ==
'\\') filename[i] =
'/';
1366 dictStream <<
"\"" << filename <<
"\", " << ROOT::TMetaUtils::GetLineNumber(cl) <<
"," << std::endl
1367 <<
" ::ROOT::Internal::DefineBehavior((void*)0,(void*)0)," << std::endl
1371 dictStream <<
"&::" << classname.c_str() <<
"::Dictionary, ";
1373 dictStream <<
"&" << mappedname.c_str() <<
"_Dictionary, ";
1376 dictStream << 0 <<
");" << std::endl
1378 <<
" return &instance;" << std::endl
1379 <<
" }" << std::endl
1380 <<
" // Insure that the inline function is _not_ optimized away by the compiler\n"
1381 <<
" ::ROOT::TGenericClassInfo *(*_R__UNIQUE_DICT_(InitFunctionKeeper))() = &GenerateInitInstance; " << std::endl
1382 <<
" // Static variable to force the class initialization" << std::endl
1384 <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstance();"
1385 <<
" R__UseDummy(_R__UNIQUE_DICT_(Init));" << std::endl;
1388 dictStream << std::endl <<
" // Dictionary for non-ClassDef classes" << std::endl
1389 <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary() {" << std::endl
1390 <<
" return GenerateInitInstance()->GetClass();" << std::endl
1391 <<
" }" << std::endl << std::endl;
1394 dictStream <<
" }" << std::endl;
1396 dictStream <<
"}" << std::endl;
1398 dictStream << std::endl;
1407llvm::StringRef
GrabIndex(
const clang::FieldDecl &member,
int printError)
1410 llvm::StringRef where;
1412 llvm::StringRef index = ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(member, &error, &where);
1413 if (index.size() == 0 && printError) {
1414 const char *errorstring;
1416 case TMetaUtils::NOT_INT:
1417 errorstring =
"is not an integer";
1419 case TMetaUtils::NOT_DEF:
1420 errorstring =
"has not been defined before the array";
1422 case TMetaUtils::IS_PRIVATE:
1423 errorstring =
"is a private member of a parent class";
1425 case TMetaUtils::UNKNOWN:
1426 errorstring =
"is not known";
1429 errorstring =
"UNKNOWN ERROR!!!!";
1432 if (where.size() == 0) {
1434 member.getParent()->getName().str().c_str(), member.getName().str().c_str());
1437 member.getParent()->getName().str().c_str(), member.getName().str().c_str(), where.str().c_str(), errorstring);
1446 const cling::Interpreter &interp,
1447 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
1448 std::ostream &dictStream)
1450 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
1451 if (clxx == 0)
return;
1453 bool add_template_keyword = ROOT::TMetaUtils::NeedTemplateKeyword(clxx);
1458 int enclSpaceNesting = 0;
1460 if (ROOT::TMetaUtils::GetNameWithinNamespace(fullname, clsname, nsname, clxx)) {
1461 enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl);
1464 dictStream <<
"//_______________________________________"
1465 <<
"_______________________________________" << std::endl;
1466 if (add_template_keyword) dictStream <<
"template <> ";
1467 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl <<
"{" << std::endl
1468 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl;
1473 int version = ROOT::TMetaUtils::GetClassVersion(clxx, interp);
1476 int basestreamer = 0;
1477 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1480 if (ROOT::TMetaUtils::ClassInfo__HasMethod(iter->getType()->getAsCXXRecordDecl(),
"Streamer", interp)) {
1481 string base_fullname;
1482 ROOT::TMetaUtils::GetQualifiedName(base_fullname, * iter->getType()->getAsCXXRecordDecl());
1484 if (strstr(base_fullname.c_str(),
"::")) {
1486 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1487 <<
" typedef " << base_fullname <<
" baseClass" << basestreamer <<
";" << std::endl
1488 <<
" baseClass" << basestreamer <<
"::Streamer(R__b);" << std::endl;
1490 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1495 if (!basestreamer) {
1496 dictStream <<
" ::Error(\"" << fullname <<
"::Streamer\", \"version id <=0 in ClassDef,"
1497 " dummy Streamer() called\"); if (R__b.IsReading()) { }" << std::endl;
1499 dictStream <<
"}" << std::endl << std::endl;
1500 while (enclSpaceNesting) {
1501 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1508 string classname = fullname;
1509 if (strstr(fullname.c_str(),
"::")) {
1511 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1512 <<
" typedef ::" << fullname <<
" thisClass;" << std::endl;
1513 classname =
"thisClass";
1515 for (
int i = 0; i < 2; i++) {
1520 dictStream <<
" UInt_t R__s, R__c;" << std::endl;
1521 dictStream <<
" if (R__b.IsReading()) {" << std::endl;
1522 dictStream <<
" Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }" << std::endl;
1524 dictStream <<
" R__b.CheckByteCount(R__s, R__c, " << classname.c_str() <<
"::IsA());" << std::endl;
1525 dictStream <<
" } else {" << std::endl;
1526 dictStream <<
" R__c = R__b.WriteVersion(" << classname.c_str() <<
"::IsA(), kTRUE);" << std::endl;
1531 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1534 if (ROOT::TMetaUtils::ClassInfo__HasMethod(iter->getType()->getAsCXXRecordDecl(),
"Streamer", interp)) {
1535 string base_fullname;
1536 ROOT::TMetaUtils::GetQualifiedName(base_fullname, * iter->getType()->getAsCXXRecordDecl());
1538 if (strstr(base_fullname.c_str(),
"::")) {
1540 dictStream <<
" //This works around a msvc bug and should be harmless on other platforms" << std::endl
1541 <<
" typedef " << base_fullname <<
" baseClass" << base <<
";" << std::endl
1542 <<
" baseClass" << base <<
"::Streamer(R__b);" << std::endl;
1545 dictStream <<
" " << base_fullname <<
"::Streamer(R__b);" << std::endl;
1551 for (clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
1554 const char *comment = ROOT::TMetaUtils::GetComment(**field_iter).data();
1556 clang::QualType
type = field_iter->getType();
1557 std::string type_name =
type.getAsString(clxx->getASTContext().getPrintingPolicy());
1559 const clang::Type *underling_type = ROOT::TMetaUtils::GetUnderlyingType(
type);
1567 if (strstr(type_name.c_str(),
"Float16_t")) isFloat16 = 1;
1571 if (strstr(type_name.c_str(),
"Double32_t")) isDouble32 = 1;
1574 if (strncmp(comment,
"!", 1)) {
1577 if (underling_type->isFundamentalType() || underling_type->isEnumeralType()) {
1578 if (
type.getTypePtr()->isConstantArrayType() &&
1579 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1580 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1584 dictStream <<
" int R__i;" << std::endl;
1587 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1589 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());
1590 dictStream <<
" ;//R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1592 dictStream <<
" ;//R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1594 }
else if (
type.getTypePtr()->isPointerType()) {
1595 llvm::StringRef indexvar =
GrabIndex(**field_iter, i == 0);
1596 if (indexvar.size() == 0) {
1598 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: pointer to fundamental type (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1599 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1601 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);" << std::endl;
1605 dictStream <<
" delete [] " << field_iter->getName().str() <<
";" << std::endl
1607 << ROOT::TMetaUtils::ShortTypeName(**field_iter) <<
"[" << indexvar.str() <<
"];" << std::endl;
1610 <<
"," << indexvar.str() <<
");" << std::endl;
1611 }
else if (isDouble32) {
1613 <<
"," << indexvar.str() <<
");" << std::endl;
1616 <<
"," << indexvar.str() <<
");" << std::endl;
1620 dictStream <<
" R__b.WriteFastArrayFloat16("
1621 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1622 }
else if (isDouble32) {
1623 dictStream <<
" R__b.WriteFastArrayDouble32("
1624 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1626 dictStream <<
" R__b.WriteFastArray("
1627 << field_iter->getName().str() <<
"," << indexvar.str() <<
");" << std::endl;
1631 }
else if (
type.getTypePtr()->isArrayType()) {
1633 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1634 if (underling_type->isEnumeralType())
1635 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1638 dictStream <<
" R__b.ReadStaticArrayFloat16((" << ROOT::TMetaUtils::TrueName(**field_iter)
1639 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1640 }
else if (isDouble32) {
1641 dictStream <<
" R__b.ReadStaticArrayDouble32((" << ROOT::TMetaUtils::TrueName(**field_iter)
1642 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1644 dictStream <<
" R__b.ReadStaticArray((" << ROOT::TMetaUtils::TrueName(**field_iter)
1645 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1649 if (underling_type->isEnumeralType()) {
1650 dictStream <<
" R__b.ReadStaticArray((Int_t*)" << field_iter->getName().str() <<
");" << std::endl;
1653 dictStream <<
" R__b.ReadStaticArrayFloat16(" << field_iter->getName().str() <<
");" << std::endl;
1654 }
else if (isDouble32) {
1655 dictStream <<
" R__b.ReadStaticArrayDouble32(" << field_iter->getName().str() <<
");" << std::endl;
1657 dictStream <<
" R__b.ReadStaticArray((" << ROOT::TMetaUtils::TrueName(**field_iter)
1658 <<
"*)" << field_iter->getName().str() <<
");" << std::endl;
1663 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1666 if (
type.getTypePtr()->getArrayElementTypeNoTypeQual()->isArrayType()) {
1667 if (underling_type->isEnumeralType())
1668 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", "
1669 <<
s <<
");" << std::endl;
1670 else if (isFloat16) {
1671 dictStream <<
" R__b.WriteArrayFloat16((" << ROOT::TMetaUtils::TrueName(**field_iter)
1672 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1673 }
else if (isDouble32) {
1674 dictStream <<
" R__b.WriteArrayDouble32((" << ROOT::TMetaUtils::TrueName(**field_iter)
1675 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1677 dictStream <<
" R__b.WriteArray((" << ROOT::TMetaUtils::TrueName(**field_iter)
1678 <<
"*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1681 if (underling_type->isEnumeralType())
1682 dictStream <<
" R__b.WriteArray((Int_t*)" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1683 else if (isFloat16) {
1684 dictStream <<
" R__b.WriteArrayFloat16(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1685 }
else if (isDouble32) {
1686 dictStream <<
" R__b.WriteArrayDouble32(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1688 dictStream <<
" R__b.WriteArray(" << field_iter->getName().str() <<
", " <<
s <<
");" << std::endl;
1692 }
else if (underling_type->isEnumeralType()) {
1694 dictStream <<
" void *ptr_" << field_iter->getName().str() <<
" = (void*)&" << field_iter->getName().str() <<
";\n";
1695 dictStream <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_" << field_iter->getName().str() <<
");" << std::endl;
1697 dictStream <<
" R__b << (Int_t)" << field_iter->getName().str() <<
";" << std::endl;
1702 <<
"=Float16_t(R_Dummy);}" << std::endl;
1705 }
else if (isDouble32) {
1708 <<
"=Double32_t(R_Dummy);}" << std::endl;
1730 if (
type.getTypePtr()->isConstantArrayType() &&
1731 type.getTypePtr()->getArrayElementTypeNoTypeQual()->isPointerType()) {
1732 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr());
1736 dictStream <<
" int R__i;" << std::endl;
1739 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1743 if (ROOT::TMetaUtils::IsBase(**field_iter,
"TObject", interp) && ROOT::TMetaUtils::IsBase(**field_iter,
"TArray", interp))
1744 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str();
1749 dictStream <<
"[R__i];" << std::endl;
1750 }
else if (
type.getTypePtr()->isPointerType()) {
1758 ROOT::TMetaUtils::Error(0,
"*** Datamember %s::%s: pointer to pointer (need manual intervention)\n", fullname.c_str(), field_iter->getName().str().c_str());
1759 dictStream <<
" //R__b.ReadArray(" << field_iter->getName().str() <<
");" << std::endl;
1761 dictStream <<
" //R__b.WriteArray(" << field_iter->getName().str() <<
", __COUNTER__);";
1764 if (ROOT::TMetaUtils::GetQualifiedName(*ROOT::TMetaUtils::GetUnderlyingType(field_iter->getType()), **field_iter) ==
"TClonesArray") {
1765 dictStream <<
" " << field_iter->getName().str() <<
"->Streamer(R__b);" << std::endl;
1778 if (ROOT::TMetaUtils::IsBase(**field_iter,
"TObject", interp) && ROOT::TMetaUtils::IsBase(**field_iter,
"TArray", interp))
1779 dictStream <<
" R__b << (TObject*)" << field_iter->getName().str() <<
";" << std::endl;
1785 }
else if (
const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(
type.getTypePtr())) {
1789 dictStream <<
" int R__i;" << std::endl;
1792 dictStream <<
" for (R__i = 0; R__i < " <<
s <<
"; R__i++)" << std::endl;
1793 std::string mTypeNameStr;
1794 ROOT::TMetaUtils::GetQualifiedName(mTypeNameStr, field_iter->getType(), **field_iter);
1795 const char *mTypeName = mTypeNameStr.c_str();
1796 const char *constwd =
"const ";
1797 if (strncmp(constwd, mTypeName, strlen(constwd)) == 0) {
1798 mTypeName += strlen(constwd);
1799 dictStream <<
" const_cast< " << mTypeName <<
" &>(" << field_iter->getName().str();
1801 dictStream <<
"[R__i]).Streamer(R__b);" << std::endl;
1805 dictStream <<
"[R__i].Streamer(R__b);" << std::endl;
1808 if (ROOT::TMetaUtils::ClassInfo__HasMethod(ROOT::TMetaUtils::GetUnderlyingRecordDecl(field_iter->getType()),
"Streamer", interp))
1811 dictStream <<
" R__b.StreamObject(&(" << field_iter->getName().str() <<
"),typeid("
1812 << field_iter->getName().str() <<
"));" << std::endl;
1823 dictStream <<
" R__b.SetByteCount(R__c, kTRUE);" << std::endl
1824 <<
" }" << std::endl
1825 <<
"}" << std::endl << std::endl;
1827 while (enclSpaceNesting) {
1828 dictStream <<
"} // namespace " << nsname.c_str() << std::endl;
1836 const cling::Interpreter &interp,
1837 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
1838 std::ostream &dictStream)
1842 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
1843 if (clxx == 0)
return;
1845 bool add_template_keyword = ROOT::TMetaUtils::NeedTemplateKeyword(clxx);
1848 for (clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
1851 int k = ROOT::TMetaUtils::IsSTLContainer(*iter);
1853 Internal::RStl::Instance().GenerateTClassFor(iter->getType(), interp, normCtxt);
1860 int enclSpaceNesting = 0;
1862 if (ROOT::TMetaUtils::GetNameWithinNamespace(fullname, clsname, nsname, clxx)) {
1863 enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl);
1866 dictStream <<
"//_______________________________________"
1867 <<
"_______________________________________" << std::endl;
1868 if (add_template_keyword) dictStream <<
"template <> ";
1869 dictStream <<
"void " << clsname <<
"::Streamer(TBuffer &R__b)" << std::endl
1871 <<
" // Stream an object of class " << fullname <<
"." << std::endl << std::endl
1872 <<
" if (R__b.IsReading()) {" << std::endl
1873 <<
" R__b.ReadClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1874 <<
" } else {" << std::endl
1875 <<
" R__b.WriteClassBuffer(" << fullname <<
"::Class(),this);" << std::endl
1876 <<
" }" << std::endl
1877 <<
"}" << std::endl << std::endl;
1879 while (enclSpaceNesting) {
1880 dictStream <<
"} // namespace " << nsname << std::endl;
1888 const cling::Interpreter &interp,
1889 const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
1890 std::ostream &dictStream,
1891 bool isAutoStreamer)
1893 if (isAutoStreamer) {
1903 std::string &code_for_parser)
1905 code_for_parser +=
"#ifdef __CINT__\n\n";
1906 code_for_parser +=
"#pragma link off all globals;\n";
1907 code_for_parser +=
"#pragma link off all classes;\n";
1908 code_for_parser +=
"#pragma link off all functions;\n\n";
1910 for (
int i = firstInputFile; i < *argc; i++) {
1912 int nostr = 0, noinp = 0, bcnt = 0,
l = strlen(argv[i]) - 1;
1913 for (
int j = 0; j < 3; j++) {
1914 if (argv[i][
l] ==
'-') {
1919 if (argv[i][
l] ==
'!') {
1924 if (argv[i][
l] ==
'+') {
1930 if (nostr || noinp) {
1932 if (nostr) strlcat(trail,
"-", 3);
1933 if (noinp) strlcat(trail,
"!", 3);
1936 strlcpy(trail,
"+", 3);
1940 char *cls = strrchr(argv[i],
'/');
1941 if (!cls) cls = strrchr(argv[i],
'\\');
1946 if ((
s = strrchr(cls,
'.'))) *
s =
'\0';
1947 code_for_parser +=
"#pragma link C++ class ";
1948 code_for_parser += cls;
1949 if (nostr || noinp || bcnt)
1950 code_for_parser += trail;
1951 code_for_parser +=
";\n";
1955 code_for_parser +=
"\n#endif\n";
1964bool Which(cling::Interpreter &interp,
const char *fname,
string &pname)
1969 static const char *fopenopts =
"rb";
1971 static const char *fopenopts =
"r";
1975 fp = fopen(pname.c_str(), fopenopts);
1981 llvm::SmallVector<std::string, 10> includePaths;
1983 interp.GetIncludePaths(includePaths,
false,
false);
1985 const size_t nPaths = includePaths.size();
1986 for (
size_t i = 0; i < nPaths; i += 1 ) {
1990 fp = fopen(pname.c_str(), fopenopts);
2012 const char *inc = strstr(original,
"\\inc\\");
2014 inc = strstr(original,
"/inc/");
2015 if (inc && strlen(inc) > 5)
2035 cling::Interpreter &interp,
2038 std::ostringstream out;
2046 if (interp.declare(out.str()) != cling::Interpreter::kSuccess) {
2047 const std::string &hdrName
2062static bool WriteAST(StringRef fileName, clang::CompilerInstance *compilerInstance, StringRef iSysRoot,
2063 clang::Module *module =
nullptr)
2066 llvm::SmallVector<char, 128> buffer;
2067 llvm::BitstreamWriter stream(buffer);
2068 clang::ASTWriter
writer(stream, buffer, compilerInstance->getPCMCache(), {});
2069 std::unique_ptr<llvm::raw_ostream> out =
2070 compilerInstance->createOutputFile(fileName,
true,
2079 compilerInstance->getFrontendOpts().RelocatablePCH =
true;
2081 writer.WriteAST(compilerInstance->getSema(), fileName, module, iSysRoot);
2084 out->write(&buffer.front(), buffer.size());
2088 bool deleteOutputFile = compilerInstance->getDiagnostics().hasErrorOccurred();
2089 compilerInstance->clearOutputFiles(deleteOutputFile);
2098 const std::string ¤tDirectory)
2100 assert(modGen.
IsPCH() &&
"modGen must be in PCH mode");
2102 std::string iSysRoot(
"/DUMMY_SYSROOT/include/");
2110static bool IncludeHeaders(
const std::vector<std::string> &headers, cling::Interpreter &interpreter)
2113 if (headers.empty())
2117 std::stringstream includes;
2118 for (
const std::string &header : headers) {
2119 includes <<
"#include \"" << header <<
"\"\n";
2121 std::string includeListStr = includes.str();
2122 auto result = interpreter.declare(includeListStr);
2123 return result == cling::Interpreter::CompilationResult::kSuccess;
2133 std::vector<std::string> &missingHeaders)
2136 std::set<std::string> moduleHeaders;
2137 ROOT::TMetaUtils::foreachHeaderInModule(
2138 *module, [&moduleHeaders](
const clang::Module::Header &
h) { moduleHeaders.insert(
h.NameAsWritten); });
2143 bool foundAllHeaders =
true;
2144 for (
const std::string &header : modGen.
GetHeaders()) {
2145 if (moduleHeaders.find(header) == moduleHeaders.end()) {
2146 missingHeaders.push_back(header);
2147 foundAllHeaders =
false;
2150 return foundAllHeaders;
2156 StringRef LinkdefPath,
const std::string &moduleName)
2160 if (moduleName ==
"Krb5Auth" || moduleName ==
"GCocoa" || moduleName ==
"GQuartz")
2164 clang::CompilerInstance *CI = interpreter.getCI();
2165 clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo();
2166 headerSearch.loadTopLevelSystemModules();
2169 clang::Module *module = headerSearch.lookupModule(StringRef(moduleName));
2174 moduleName.c_str());
2181 std::vector<std::string> missingHeaders;
2184 std::stringstream msgStream;
2185 msgStream <<
"warning: Couldn't find the following specified headers in "
2186 <<
"the module " << module->Name <<
":\n";
2187 for (
auto &
H : missingHeaders) {
2188 msgStream <<
" " <<
H <<
"\n";
2190 std::string warningMessage = msgStream.str();
2195 module->Name.c_str());
2206 char platformDefines[64] = {0};
2207#ifdef __INTEL_COMPILER
2208 snprintf(platformDefines, 64,
"-DG__INTEL_COMPILER=%ld", (
long)__INTEL_COMPILER);
2209 clingArgs.push_back(platformDefines);
2212 snprintf(platformDefines, 64,
"-DG__xlC=%ld", (
long)__xlC__);
2213 clingArgs.push_back(platformDefines);
2216 snprintf(platformDefines, 64,
"-DG__GNUC=%ld", (
long)__GNUC__);
2217 snprintf(platformDefines, 64,
"-DG__GNUC_VER=%ld", (
long)__GNUC__ * 1000 + __GNUC_MINOR__);
2218 clingArgs.push_back(platformDefines);
2220#ifdef __GNUC_MINOR__
2221 snprintf(platformDefines, 64,
"-DG__GNUC_MINOR=%ld", (
long)__GNUC_MINOR__);
2222 clingArgs.push_back(platformDefines);
2225 snprintf(platformDefines, 64,
"-DG__HP_aCC=%ld", (
long)__HP_aCC);
2226 clingArgs.push_back(platformDefines);
2229 snprintf(platformDefines, 64,
"-DG__sun=%ld", (
long)__sun);
2230 clingArgs.push_back(platformDefines);
2233 snprintf(platformDefines, 64,
"-DG__SUNPRO_CC=%ld", (
long)__SUNPRO_CC);
2234 clingArgs.push_back(platformDefines);
2236#ifdef _STLPORT_VERSION
2238 snprintf(platformDefines, 64,
"-DG__STLPORT_VERSION=%ld", (
long)_STLPORT_VERSION);
2239 clingArgs.push_back(platformDefines);
2242 snprintf(platformDefines, 64,
"-DG__ia64=%ld", (
long)__ia64__);
2243 clingArgs.push_back(platformDefines);
2246 snprintf(platformDefines, 64,
"-DG__x86_64=%ld", (
long)__x86_64__);
2247 clingArgs.push_back(platformDefines);
2250 snprintf(platformDefines, 64,
"-DG__i386=%ld", (
long)__i386__);
2251 clingArgs.push_back(platformDefines);
2254 snprintf(platformDefines, 64,
"-DG__arm=%ld", (
long)__arm__);
2255 clingArgs.push_back(platformDefines);
2258 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)_WIN32);
2259 clingArgs.push_back(platformDefines);
2262 snprintf(platformDefines, 64,
"-DG__WIN32=%ld", (
long)WIN32);
2263 clingArgs.push_back(platformDefines);
2267 snprintf(platformDefines, 64,
"-DG__MSC_VER=%ld", (
long)_MSC_VER);
2268 clingArgs.push_back(platformDefines);
2269 snprintf(platformDefines, 64,
"-DG__VISUAL=%ld", (
long)_MSC_VER);
2270 clingArgs.push_back(platformDefines);
2279 return llvm::sys::path::filename(path);
2289 if (std::string::npos != pos) {
2290 dirname.assign(path.begin(), path.begin() + pos + 1);
2301 std::string dictLocation;
2303 return !dictLocation.empty();
2309 std::string &rootmapLibName)
2313 if (rootmapFileName.empty()) {
2315 rootmapFileName = rootmapLibName.substr(0, libExtensionPos) +
".rootmap";
2316 size_t libCleanNamePos = rootmapLibName.find_last_of(
gPathSeparator) + 1;
2317 rootmapLibName = rootmapLibName.substr(libCleanNamePos, std::string::npos);
2319 rootmapLibName.c_str(),
2320 rootmapFileName.c_str());
2329 std::string &ctxtName,
2330 const cling::Interpreter &interpreter,
2331 bool treatParent =
true)
2333 const clang::DeclContext *outerCtxt = treatParent ? theContext.getParent() : &theContext;
2335 if (!outerCtxt)
return;
2337 if (
const clang::RecordDecl *thisRcdDecl = llvm::dyn_cast<clang::RecordDecl>(outerCtxt)) {
2347 std::string &ctxtName,
2348 const cling::Interpreter &interpreter)
2350 const clang::DeclContext *theContext = theDecl.getDeclContext();
2358 const cling::Interpreter &interp)
2360 if (!decls.empty()) {
2361 std::string autoLoadKey;
2362 for (
auto &
d : decls) {
2366 if (autoLoadKey.empty()) {
2367 names.push_back(
d->getQualifiedNameAsString());
2385 const std::string &rootmapLibName,
2386 const std::list<std::string> &classesDefsList,
2387 const std::list<std::string> &classesNames,
2388 const std::list<std::string> &nsNames,
2389 const std::list<std::string> &tdNames,
2390 const std::list<std::string> &enNames,
2391 const std::list<std::string> &varNames,
2393 const std::unordered_set<std::string> headersToIgnore)
2396 std::ofstream rootmapFile(rootmapFileName.c_str());
2404 std::unordered_set<std::string> classesKeys;
2408 if (!classesNames.empty() || !nsNames.empty() || !tdNames.empty() ||
2409 !enNames.empty() || !varNames.empty()) {
2412 if (!classesDefsList.empty()) {
2413 rootmapFile <<
"{ decls }\n";
2414 for (
auto & classDef : classesDefsList) {
2415 rootmapFile << classDef << std::endl;
2417 rootmapFile <<
"\n";
2419 rootmapFile <<
"[ " << rootmapLibName <<
" ]\n";
2422 if (!classesNames.empty()) {
2423 rootmapFile <<
"# List of selected classes\n";
2424 for (
auto & className : classesNames) {
2425 rootmapFile <<
"class " << className << std::endl;
2426 classesKeys.insert(className);
2429 std::unordered_set<std::string> treatedHeaders;
2430 for (
auto & className : classesNames) {
2432 if (className.find(
"<") != std::string::npos)
continue;
2433 if (headersClassesMap.count(className)) {
2434 auto &headers = headersClassesMap.at(className);
2435 if (!headers.empty()){
2436 auto &header = headers.front();
2437 if (treatedHeaders.insert(header).second &&
2438 headersToIgnore.find(header) == headersToIgnore.end() &&
2439 ROOT::TMetaUtils::IsHeaderName(header)){
2440 rootmapFile <<
"header " << header << std::endl;
2448 if (!nsNames.empty()) {
2449 rootmapFile <<
"# List of selected namespaces\n";
2450 for (
auto & nsName : nsNames) {
2451 rootmapFile <<
"namespace " << nsName << std::endl;
2456 if (!tdNames.empty()) {
2457 rootmapFile <<
"# List of selected typedefs and outer classes\n";
2458 for (
const auto & autoloadKey : tdNames)
2459 if (classesKeys.insert(autoloadKey).second)
2460 rootmapFile <<
"typedef " << autoloadKey << std::endl;
2465 if (!enNames.empty()){
2466 rootmapFile <<
"# List of selected enums and outer classes\n";
2467 for (
const auto & autoloadKey : enNames)
2468 if (classesKeys.insert(autoloadKey).second)
2469 rootmapFile <<
"enum " << autoloadKey << std::endl;
2473 if (!varNames.empty()){
2474 rootmapFile <<
"# List of selected vars\n";
2475 for (
const auto & autoloadKey : varNames)
2476 if (classesKeys.insert(autoloadKey).second)
2477 rootmapFile <<
"var " << autoloadKey << std::endl;
2491 auto nsPattern =
'{';
auto nsPatternLength = 1;
2492 auto foundNsPos =
line.find_last_of(nsPattern);
2493 if (foundNsPos == std::string::npos)
return {
"",
""};
2494 foundNsPos+=nsPatternLength;
2495 auto extNs =
line.substr(0,foundNsPos);
2497 auto nsEndPattern =
'}';
2498 auto foundEndNsPos =
line.find(nsEndPattern);
2499 auto contained =
line.substr(foundNsPos, foundEndNsPos-foundNsPos);
2501 return {extNs, contained};
2517 std::map<std::string, std::string> nsEntitiesMap;
2518 std::list<std::string> optFwdDeclList;
2519 for (
auto const & fwdDecl : fwdDeclarationsList){
2522 if (extNsAndEntities.first.empty()) {
2524 optFwdDeclList.push_front(fwdDecl);
2526 auto currentVal = nsEntitiesMap[extNsAndEntities.first];
2527 nsEntitiesMap[extNsAndEntities.first] = currentVal +=extNsAndEntities.second;
2531 std::string optFwdDecl;
2532 for (
auto const & extNsAndEntities : nsEntitiesMap) {
2533 optFwdDecl = extNsAndEntities.first;
2534 optFwdDecl += extNsAndEntities.second;
2535 for (
int i = 0; i < std::count(optFwdDecl.begin(), optFwdDecl.end(),
'{'); ++i ){
2538 optFwdDeclList.push_front(optFwdDecl);
2541 return optFwdDeclList;
2549 std::list<std::string> &el_list,
2550 std::unordered_set<std::string> &el_set)
2552 std::stringstream elStream(el);
2555 while (getline(elStream, tmp,
'\n')) {
2557 if (el_set.insert(tmp).second && !tmp.empty()) {
2558 el_list.push_back(tmp);
2569 std::list<std::string> &classesList,
2570 std::list<std::string> &classesListForRootmap,
2571 std::list<std::string> &fwdDeclarationsList,
2572 const cling::Interpreter &interpreter)
2580 std::unordered_set<std::string> classesSet;
2581 std::unordered_set<std::string> outerMostClassesSet;
2583 std::string attrName, attrValue;
2584 bool isClassSelected;
2585 std::unordered_set<std::string> availableFwdDecls;
2586 std::string fwdDeclaration;
2588 fwdDeclaration =
"";
2589 int retCode = ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces(*selVar, fwdDeclaration);
2594 fwdDeclaration =
"";
2595 int retCode = ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces(*selEnum, fwdDeclaration);
2601 isClassSelected =
true;
2602 const clang::RecordDecl *rDecl = selClass.GetRecordDecl();
2603 std::string normalizedName;
2604 normalizedName = selClass.GetNormalizedName();
2605 if (!normalizedName.empty() &&
2606 !classesSet.insert(normalizedName).second &&
2607 outerMostClassesSet.count(normalizedName) == 0) {
2608 std::cerr <<
"FATAL: A class with normalized name " << normalizedName
2609 <<
" was already selected. This means that two different instances of"
2610 <<
" clang::RecordDecl had the same name, which is not possible."
2611 <<
" This can be a hint of a serious problem in the class selection."
2612 <<
" In addition, the generated dictionary would not even compile.\n";
2615 classesList.push_back(normalizedName);
2618 const char *reqName(selClass.GetRequestedName());
2621 fwdDeclaration =
"";
2622 int retCode = ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces(*rDecl, fwdDeclaration);
2626 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl)) {
2627 fwdDeclaration =
"";
2628 retCode = ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromRcdDecl(*rDecl, interpreter, fwdDeclaration);
2634 for (
auto ait = rDecl->attr_begin(); ait != rDecl->attr_end(); ++ait) {
2635 if (0 == ROOT::TMetaUtils::extractPropertyNameVal(*ait, attrName, attrValue) &&
2636 attrName ==
"rootmap" &&
2637 attrValue ==
"false") {
2638 attrName = attrValue =
"";
2639 isClassSelected =
false;
2643 if (isClassSelected) {
2659 std::string outerMostClassName;
2661 if (!outerMostClassName.empty() &&
2662 !llvm::isa<clang::ClassTemplateSpecializationDecl>(rDecl) &&
2663 classesSet.insert(outerMostClassName).second &&
2664 outerMostClassesSet.insert(outerMostClassName).second) {
2665 classesListForRootmap.push_back(outerMostClassName);
2667 classesListForRootmap.push_back(normalizedName);
2668 if (reqName !=
nullptr && 0 != strcmp(reqName,
"") && reqName != normalizedName) {
2669 classesListForRootmap.push_back(reqName);
2673 if (normalizedName.find(
"Double32_t") == std::string::npos
2674 && normalizedName.find(
"Float16_t") == std::string::npos) {
2675 std::unique_ptr<clang::MangleContext> mangleCtx(rDecl->getASTContext().createMangleContext());
2676 std::string mangledName;
2678 llvm::raw_string_ostream sstr(mangledName);
2679 if (
const clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(rDecl)) {
2680 mangleCtx->mangleCXXRTTI(clang::QualType(TD->getTypeForDecl(), 0), sstr);
2683 if (!mangledName.empty()) {
2684 int errDemangle = 0;
2686 if (mangledName[0] ==
'\01')
2687 mangledName.erase(0, 1);
2689 if (!errDemangle && demangledTIName) {
2690 static const char typeinfoNameFor[] =
" `RTTI Type Descriptor'";
2691 if (strstr(demangledTIName, typeinfoNameFor)) {
2692 std::string demangledName = demangledTIName;
2693 demangledName.erase(demangledName.end() - strlen(typeinfoNameFor), demangledName.end());
2694 if (demangledName.compare(0, 6,
"class ") == 0)
2695 demangledName.erase(0, 6);
2696 else if (demangledName.compare(0, 7,
"struct ") == 0)
2697 demangledName.erase(0, 7);
2700 if (!errDemangle && demangledTIName) {
2701 static const char typeinfoNameFor[] =
"typeinfo for ";
2702 if (!strncmp(demangledTIName, typeinfoNameFor, strlen(typeinfoNameFor))) {
2703 std::string demangledName = demangledTIName + strlen(typeinfoNameFor);
2709 if (demangledName != normalizedName && (!reqName || demangledName != reqName)) {
2710 classesListForRootmap.push_back(demangledName);
2715 "Demangled typeinfo name '%s' does not contain `RTTI Type Descriptor'\n",
2719 "Demangled typeinfo name '%s' does not start with 'typeinfo for'\n",
2724 free(demangledTIName);
2730 classesListForRootmap.sort();
2743 for (RScanner::NamespaceColl_t::const_iterator selNsIter = scan.
fSelectedNamespaces.begin();
2745 nsList.push_back(ROOT::TMetaUtils::GetQualifiedName(* selNsIter->GetNamespaceDecl()));
2758 if (clang::CXXRecordDecl *CXXRD =
2759 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2771 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2774 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2775 if (cxxdecl && ROOT::TMetaUtils::ClassInfo__HasMethod(selClass,
"Class_Name", interp)) {
2777 "Interactivity only dictionaries are not supported for classes with ClassDef\n");
2793 if (interp.parseForModule(
"#include \"TStreamerInfo.h\"\n"
2794 "#include \"TFile.h\"\n"
2795 "#include \"TObjArray.h\"\n"
2796 "#include \"TVirtualArray.h\"\n"
2797 "#include \"TStreamerElement.h\"\n"
2798 "#include \"TProtoClass.h\"\n"
2799 "#include \"TBaseClass.h\"\n"
2800 "#include \"TListOfDataMembers.h\"\n"
2801 "#include \"TListOfEnums.h\"\n"
2802 "#include \"TListOfEnumsWithLock.h\"\n"
2803 "#include \"TDataMember.h\"\n"
2804 "#include \"TEnum.h\"\n"
2805 "#include \"TEnumConstant.h\"\n"
2806 "#include \"TDictAttributeMap.h\"\n"
2807 "#include \"TMessageHandler.h\"\n"
2808 "#include \"TArray.h\"\n"
2809 "#include \"TRefArray.h\"\n"
2810 "#include \"root_std_complex.h\"\n")
2811 != cling::Interpreter::kSuccess)
2822 cling::Interpreter &interp,
2824 const ROOT::TMetaUtils::RConstructorTypes &ctorTypes,
2827 bool writeEmptyRootPCM)
2829 ROOT::TMetaUtils::TNormalizedCtxt normCtxt(interp.getLookupHelper());
2831 bool needsCollectionProxy =
false;
2851 auto nsName =
ns.GetNamespaceDecl()->getQualifiedNameAsString();
2852 if (nsName.find(
"(anonymous)") == std::string::npos)
2857 if (!selClass.GetRecordDecl()->isCompleteDefinition()) {
2858 ROOT::TMetaUtils::Error(0,
"A dictionary has been requested for %s but there is no declaration!\n", ROOT::TMetaUtils::GetQualifiedName(selClass).c_str());
2861 if (selClass.RequestOnlyTClass()) {
2869 if (clang::CXXRecordDecl *CXXRD =
2870 llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::RecordDecl *
>(selClass.GetRecordDecl()))) {
2874 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2881 Internal::RStl::Instance().GenerateTClassFor(selClass.GetNormalizedName(), CRD, interp, normCtxt);
2883 ROOT::TMetaUtils::WriteClassInit(dictStream, selClass, CRD, interp, normCtxt, ctorTypes, needsCollectionProxy);
2897 if (!selClass.GetRecordDecl()->isCompleteDefinition() || selClass.RequestOnlyTClass()) {
2901 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2902 if (cxxdecl && ROOT::TMetaUtils::ClassInfo__HasMethod(selClass,
"Class_Name", interp)) {
2913 if (!selClass.GetRecordDecl()->isCompleteDefinition() || !selClass.RequestOnlyTClass()) {
2917 const clang::CXXRecordDecl *CRD = llvm::dyn_cast<clang::CXXRecordDecl>(selClass.GetRecordDecl());
2919 if (!ROOT::TMetaUtils::IsSTLContainer(selClass)) {
2920 ROOT::TMetaUtils::WriteClassInit(dictStream, selClass, CRD, interp, normCtxt, ctorTypes, needsCollectionProxy);
2937 ROOT::Internal::RStl::Instance().WriteClassInit(dictStream, interp, normCtxt, ctorTypes, needsCollectionProxy,
EmitStreamerInfo);
2945 if (finRetCode != 0)
return finRetCode;
2955 dictStream <<
"// Do NOT change. Changes will be lost next time file is generated\n\n"
2956 <<
"#define R__DICTIONARY_FILENAME " << main_dictname << std::endl
2959 <<
"#define R__NO_DEPRECATION" << std::endl
2964 <<
"\n/*******************************************************************/\n"
2965 <<
"#include <stddef.h>\n"
2966 <<
"#include <stdio.h>\n"
2967 <<
"#include <stdlib.h>\n"
2968 <<
"#include <string.h>\n"
2969 <<
"#include <assert.h>\n"
2970 <<
"#define G__DICTIONARY\n"
2971 <<
"#include \"RConfig.h\"\n"
2972 <<
"#include \"TClass.h\"\n"
2973 <<
"#include \"TDictAttributeMap.h\"\n"
2974 <<
"#include \"TInterpreter.h\"\n"
2975 <<
"#include \"TROOT.h\"\n"
2976 <<
"#include \"TBuffer.h\"\n"
2977 <<
"#include \"TMemberInspector.h\"\n"
2978 <<
"#include \"TInterpreter.h\"\n"
2979 <<
"#include \"TVirtualMutex.h\"\n"
2980 <<
"#include \"TError.h\"\n\n"
2981 <<
"#ifndef G__ROOT\n"
2982 <<
"#define G__ROOT\n"
2984 <<
"#include \"RtypesImp.h\"\n"
2985 <<
"#include \"TIsAProxy.h\"\n"
2986 <<
"#include \"TFileMergeInfo.h\"\n"
2987 <<
"#include <algorithm>\n"
2988 <<
"#include \"TCollectionProxyInfo.h\"\n"
2989 <<
"/*******************************************************************/\n\n"
2990 <<
"#include \"TDataMember.h\"\n\n";
2992 dictStream <<
"// The generated code does not explicitly qualifies STL entities\n"
2993 <<
"namespace std {} using namespace std;\n\n";
3000 const std::string &includeForSource,
3001 const std::string &extraIncludes)
3003 dictStream <<
"// Header files passed as explicit arguments\n"
3004 << includeForSource << std::endl
3005 <<
"// Header files passed via #pragma extra_include\n"
3006 << extraIncludes << std::endl;
3012#if defined(R__IOSSIM) || defined(R__IOS)
3031class tempFileNamesCatalog {
3034 tempFileNamesCatalog(): m_size(0), m_emptyString(
"") {};
3036 std::string getTmpFileName(
const std::string &filename) {
3037 return filename +
"_tmp_" + std::to_string(getpid());
3043 void addFileName(std::string &nameStr) {
3044 if (nameStr.empty())
return;
3046 std::string tmpNameStr(getTmpFileName(nameStr));
3049 const char *
name(nameStr.c_str());
3050 const char *tmpName(tmpNameStr.c_str());
3052 m_names.push_back(nameStr);
3053 m_tempNames.push_back(tmpNameStr);
3057 if (0 == std::rename(
name , tmpName)) {
3062 nameStr = tmpNameStr;
3073 for (
unsigned int i = 0; i < m_size; ++i) {
3074 const char *tmpName = m_tempNames[i].c_str();
3076 std::ifstream ifile(tmpName);
3080 if (0 != std::remove(tmpName)) {
3093 for (
unsigned int i = 0; i < m_size; ++i) {
3094 const char *tmpName = m_tempNames[i].c_str();
3095 const char *
name = m_names[i].c_str();
3097 std::ifstream ifile(tmpName);
3104 if (ifile.is_open())
3106 if (0 != std::rename(tmpName ,
name)) {
3107 if (llvm::sys::fs::copy_file(tmpName ,
name)) {
3108 llvm::sys::fs::remove(tmpName);
3112 if (0 != std::rename(tmpName ,
name)) {
3123 const std::string &getFileName(
const std::string &tmpFileName) {
3124 size_t i = std::distance(m_tempNames.begin(),
3125 find(m_tempNames.begin(), m_tempNames.end(), tmpFileName));
3126 if (i == m_tempNames.size())
return m_emptyString;
3133 std::cout <<
"Restoring files in temporary file catalog:\n";
3134 for (
unsigned int i = 0; i < m_size; ++i) {
3135 std::cout << m_tempNames[i] <<
" --> " << m_names[i] << std::endl;
3140 unsigned int m_size;
3141 const std::string m_emptyString;
3142 std::vector<std::string> m_names;
3143 std::vector<std::string> m_tempNames;
3150 tempFileNamesCatalog &tmpCatalog)
3152 std::string splitDictName(tmpCatalog.getFileName(dictpathname));
3153 const size_t dotPos = splitDictName.find_last_of(
".");
3154 splitDictName.insert(dotPos,
"_classdef");
3155 tmpCatalog.addFileName(splitDictName);
3156 return new std::ofstream(splitDictName.c_str());
3165 std::list<std::string> &diagnosticPragmas)
3167 static const std::string pattern(
"-Wno-");
3169 std::string localArg(arg);
3170 if (localArg.find(pattern) != 0)
return;
3171 if (localArg ==
"-Wno-noexcept-type") {
3176 ROOT::TMetaUtils::ReplaceAll(localArg, pattern,
"#pragma clang diagnostic ignored \"-W");
3178 diagnosticPragmas.push_back(localArg);
3184 cling::Interpreter &interp)
3186 using namespace ROOT::TMetaUtils::AST2SourceTools;
3187 std::string fwdDecl;
3188 std::string initStr(
"{");
3189 auto &fwdDeclnArgsToSkipColl = normCtxt.GetTemplNargsToKeepMap();
3190 for (
auto & strigNargsToKeepPair : fwdDeclnArgsToSkipColl) {
3191 auto &clTemplDecl = *strigNargsToKeepPair.first;
3192 FwdDeclFromTmplDecl(clTemplDecl , interp, fwdDecl);
3195 + std::to_string(strigNargsToKeepPair.second)
3198 if (!fwdDeclnArgsToSkipColl.empty())
3209 if (qt.isNull())
return qt;
3210 clang::QualType thisQt(qt);
3211 while (thisQt->isPointerType() ||
3212 thisQt->isReferenceType()) {
3213 thisQt = thisQt->getPointeeType();
3223 const cling::Interpreter &interp,
3224 std::set<const clang::CXXRecordDecl *> &visitedDecls)
3226 std::list<std::string> headers;
3229 cling::Interpreter::PushTransactionRAII RAII(&interp);
3232 if (!visitedDecls.insert(rcd.getCanonicalDecl()).second)
3236 if (
const clang::ClassTemplateSpecializationDecl *tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)) {
3239 for (
auto & tArg : tsd->getTemplateArgs().asArray()) {
3242 if (tArgQualType.isNull())
continue;
3243 if (
const clang::CXXRecordDecl *tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()) {
3244 headers.splice(headers.end(),
RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls));
3251 for (
auto baseIt = tsd->bases_begin(); baseIt != tsd->bases_end(); baseIt++) {
3253 if (baseQualType.isNull())
continue;
3254 if (
const clang::CXXRecordDecl *baseRcdPtr = baseQualType->getAsCXXRecordDecl()) {
3255 headers.splice(headers.end(),
RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls));
3260 for (
auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) {
3261 if (
const clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)) {
3263 if (fieldQualType.isNull()) continue ;
3264 if (
const clang::CXXRecordDecl *fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()) {
3265 if (fieldCxxRcd->hasDefinition())
3266 headers.splice(headers.end(),
RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls));
3272 for (
auto methodIt = tsd->method_begin(); methodIt != tsd->method_end(); ++methodIt) {
3274 for (
auto & fPar : methodIt->parameters()) {
3276 if (fParQualType.isNull())
continue;
3277 if (
const clang::CXXRecordDecl *fParCxxRcd = fParQualType->getAsCXXRecordDecl()) {
3278 if (fParCxxRcd->hasDefinition())
3279 headers.splice(headers.end(),
RecordDecl2Headers(*fParCxxRcd, interp, visitedDecls));
3284 if (retQualType.isNull())
continue;
3285 if (
const clang::CXXRecordDecl *retCxxRcd = retQualType->getAsCXXRecordDecl()) {
3286 if (retCxxRcd->hasDefinition())
3294 std::string header = ROOT::TMetaUtils::GetFileName(rcd, interp);
3295 headers.emplace_back(header);
3308 if (
auto dclCtxt= rcd.getDeclContext()){
3309 if (! dclCtxt->isStdNamespace()){
3318 auto clAsTmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd);
3319 if (!clAsTmplSpecDecl)
return false;
3324 auto& astCtxt = rcd.getASTContext();
3325 auto& templInstArgs = clAsTmplSpecDecl->getTemplateInstantiationArgs();
3326 for (
auto&& arg : templInstArgs.asArray()){
3328 auto argKind = arg.getKind();
3330 if (argKind == clang::TemplateArgument::Integral)
continue;
3334 auto argQualType = arg.getAsType();
3335 auto isPOD = argQualType.isPODType(astCtxt);
3337 if (isPOD)
continue;
3339 auto argType = argQualType.getTypePtr();
3340 if (
auto recType = llvm::dyn_cast<clang::RecordType>(argType)){
3343 if (isArgGoodForAutoParseMap)
continue;
3362 const cling::Interpreter &interp)
3364 std::set<const clang::CXXRecordDecl *> visitedDecls;
3365 std::unordered_set<std::string> buffer;
3366 std::string autoParseKey;
3369 for (
auto & annotatedRcd : annotatedRcds) {
3370 if (
const clang::CXXRecordDecl *cxxRcd =
3371 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())) {
3373 visitedDecls.clear();
3377 headers.remove_if([&buffer](
const std::string &
s) {
3378 return !buffer.insert(
s).
second;
3381 if (autoParseKey.empty()) autoParseKey = annotatedRcd.GetNormalizedName();
3383 headersDeclsMap[autoParseKey] = headers;
3384 headersDeclsMap[annotatedRcd.GetRequestedName()] = headers;
3386 ROOT::TMetaUtils::Info(0,
"Class %s is not included in the set of autoparse keys.\n", autoParseKey.c_str());
3391 if (!llvm::isa<clang::ClassTemplateSpecializationDecl>(cxxRcd)){
3392 headersClassesMap[autoParseKey] = headersDeclsMap[autoParseKey];
3393 headersClassesMap[annotatedRcd.GetRequestedName()] = headersDeclsMap[annotatedRcd.GetRequestedName()];
3399 for (
auto & tDef : tDefDecls) {
3400 if (clang::CXXRecordDecl *cxxRcd = tDef->getUnderlyingType()->getAsCXXRecordDecl()) {
3402 visitedDecls.clear();
3404 headers.push_back(ROOT::TMetaUtils::GetFileName(*tDef, interp));
3407 headers.remove_if([&buffer](
const std::string &
s) {
3408 return !buffer.insert(
s).
second;
3411 if (autoParseKey.empty()) autoParseKey = tDef->getQualifiedNameAsString();
3412 headersDeclsMap[autoParseKey] = headers;
3417 for (
auto & func : funcDecls) {
3418 std::list<std::string> headers = {ROOT::TMetaUtils::GetFileName(*func, interp)};
3419 headersDeclsMap[ROOT::TMetaUtils::GetQualifiedName(*func)] = headers;
3423 for (
auto & var : varDecls) {
3424 std::list<std::string> headers = {ROOT::TMetaUtils::GetFileName(*var, interp)};
3425 headersDeclsMap[ROOT::TMetaUtils::GetQualifiedName(*var)] = headers;
3429 for (
auto & en : enumDecls) {
3430 std::list<std::string> headers = {ROOT::TMetaUtils::GetFileName(*en, interp)};
3431 headersDeclsMap[ROOT::TMetaUtils::GetQualifiedName(*en)] = headers;
3439 const cling::Interpreter &interp)
3441 std::string newFwdDeclString;
3443 using namespace ROOT::TMetaUtils::AST2SourceTools;
3445 std::string fwdDeclString;
3447 std::unordered_set<std::string> fwdDecls;
3468 std::vector<const clang::Decl *> selectedDecls(scan.
fSelectedClasses.size());
3473 selectedDecls.begin(),
3474 [](
const ROOT::TMetaUtils::AnnotatedRecordDecl& rcd){return rcd.GetRecordDecl();});
3477 selectedDecls.push_back(TD);
3485 fwdDeclString += Decls2FwdDecls(selectedDecls,
IsLinkdefFile,interp);
3501 if (fwdDeclString.empty()) fwdDeclString =
"";
3502 return fwdDeclString;
3509 const std::string &detectedUmbrella,
3510 bool payLoadOnly =
false)
3512 std::string headerName;
3515 std::cout <<
"Class-headers Mapping:\n";
3516 std::string headersClassesMapString =
"static const char* classesHeaders[]={\n";
3517 for (
auto const & classHeaders : headersClassesMap) {
3519 std::cout <<
" o " << classHeaders.first <<
" --> ";
3520 headersClassesMapString +=
"\"";
3521 headersClassesMapString += classHeaders.first +
"\"";
3522 for (
auto const & header : classHeaders.second) {
3523 headerName = (detectedUmbrella == header || payLoadOnly) ?
"payloadCode" :
"\"" + header +
"\"";
3524 headersClassesMapString +=
", " + headerName;
3526 std::cout <<
", " << headerName;
3531 std::cout << std::endl;
3532 headersClassesMapString +=
", \"@\",\n";
3534 headersClassesMapString +=
"nullptr};\n";
3535 return headersClassesMapString;
3542 return !ROOT::TMetaUtils::IsHeaderName(filename);
3552 auto vetos = {
"-pipe",
"-fPIC",
"-fpic",
3553 "-fno-plt",
"--save-temps" };
3555 for (
auto veto : vetos) {
3556 if (argument == veto)
return 1;
3559 if (ROOT::TMetaUtils::BeginsWith(argument,
"--gcc-toolchain="))
3571 if (ROOT::TMetaUtils::BeginsWith(argument,
"--") && !ROOT::TMetaUtils::BeginsWith(argument,
"--param"))
return false;
3578 static const std::vector<std::string> namePrfxes {
3581 auto pos = find_if(namePrfxes.begin(),
3583 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3584 return namePrfxes.end() == pos;
3591 static const std::vector<std::string> uclNamePrfxes {
3595 static const std::set<std::string> unsupportedClassesNormNames{
3598 if ( unsupportedClassesNormNames.count(
name) == 1)
return false;
3599 auto pos = find_if(uclNamePrfxes.begin(),
3600 uclNamePrfxes.end(),
3601 [&](
const std::string& str){return ROOT::TMetaUtils::BeginsWith(name,str);});
3602 return uclNamePrfxes.end() == pos;
3612 for (
auto&& aRcd : annotatedRcds){
3613 auto clName = aRcd.GetNormalizedName();
3615 std::cerr <<
"Error: Class " << clName <<
" has been selected but "
3616 <<
"currently the support for its I/O is not yet available. Note that "
3617 << clName <<
", even if not selected, will be available for "
3618 <<
"interpreted code.\n";
3622 std::cerr <<
"Error: It is not necessary to explicitly select class "
3623 << clName <<
". I/O is supported for it transparently.\n";
3632class TRootClingCallbacks :
public cling::InterpreterCallbacks {
3634 std::list<std::string>& fFilesIncludedByLinkdef;
3635 bool isLocked =
false;
3637 TRootClingCallbacks(cling::Interpreter* interp, std::list<std::string>& filesIncludedByLinkdef):
3638 InterpreterCallbacks(interp),
3639 fFilesIncludedByLinkdef(filesIncludedByLinkdef){};
3641 ~TRootClingCallbacks(){};
3643 virtual void InclusionDirective(clang::SourceLocation ,
const clang::Token & ,
3644 llvm::StringRef FileName,
bool IsAngled, clang::CharSourceRange ,
3645 const clang::FileEntry * , llvm::StringRef ,
3646 llvm::StringRef ,
const clang::Module * )
3648 if (isLocked)
return;
3649 if (IsAngled)
return;
3650 auto& PP = m_Interpreter->getCI()->getPreprocessor();
3651 auto curLexer = PP.getCurrentFileLexer();
3652 if (!curLexer)
return;
3653 auto fileEntry = curLexer->getFileEntry();
3654 if (!fileEntry)
return;
3655 auto thisFileName = fileEntry->getName();
3656 auto fileNameAsString = FileName.str();
3658 if (isThisLinkdef) {
3660 if (isTheIncludedLinkdef) {
3661 fFilesIncludedByLinkdef.clear();
3664 fFilesIncludedByLinkdef.emplace_back(fileNameAsString.c_str());
3680class CheckModuleBuildClient :
public clang::DiagnosticConsumer {
3681 clang::DiagnosticConsumer *fChild;
3683 clang::ModuleMap &fMap;
3686 CheckModuleBuildClient(clang::DiagnosticConsumer *Child,
bool OwnsChild, clang::ModuleMap &
Map)
3687 : fChild(Child), fOwnsChild(OwnsChild), fMap(
Map)
3691 ~CheckModuleBuildClient()
3697 virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &
Info)
override
3699 using namespace clang::diag;
3705 std::string moduleName;
3706 const clang::Module *module =
nullptr;
3709 const auto &ID =
Info.getID();
3710 if (ID == remark_module_build || ID == remark_module_build_done) {
3711 moduleName =
Info.getArgStdStr(0);
3712 module = fMap.findModule(moduleName);
3718 "Couldn't find module %s in the available modulemaps. This"
3719 "prevents us from correctly diagnosing wrongly built modules.\n",
3720 moduleName.c_str());
3727 bool isROOTSystemModuleDiag = module && llvm::StringRef(moduleName).startswith(
"ROOT_");
3728 bool isSystemModuleDiag = module && module && module->IsSystem;
3729 if (!isROOTSystemModuleDiag && !isSystemModuleDiag)
3730 fChild->HandleDiagnostic(DiagLevel,
Info);
3732 if (ID == remark_module_build && !isROOTSystemModuleDiag && !isSystemModuleDiag) {
3734 "Had to build non-system module %s implicitly. You first need to\n"
3735 "generate the dictionary for %s or mark the C++ module as a system\n"
3736 "module if you provided your own system modulemap file:\n"
3737 "%s [system] { ... }\n",
3738 moduleName.c_str(), moduleName.c_str(), moduleName.c_str());
3743 virtual void clear()
override
3746 DiagnosticConsumer::clear();
3749 virtual void BeginSourceFile(
const clang::LangOptions &LangOpts,
const clang::Preprocessor *PP)
override
3751 fChild->BeginSourceFile(LangOpts, PP);
3752 DiagnosticConsumer::BeginSourceFile(LangOpts, PP);
3755 virtual void EndSourceFile()
override
3757 fChild->EndSourceFile();
3758 DiagnosticConsumer::EndSourceFile();
3761 virtual void finish()
override
3764 DiagnosticConsumer::finish();
3767 virtual bool IncludeInDiagnosticCounts()
const override {
return fChild->IncludeInDiagnosticCounts(); }
3774 bool isDeep =
false,
3775 bool isGenreflex =
false)
3781 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
3782 llvm::PrettyStackTraceProgram X(argc, argv);
3784#if defined(_WIN32) && defined(_MSC_VER)
3788 const char *EnablePopups = getenv(
"Cling_GuiOnAssert");
3789 if (EnablePopups ==
nullptr || EnablePopups[0] ==
'0') {
3790 ::_set_error_mode(_OUT_TO_STDERR);
3791 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3792 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3793 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3794 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3795 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3796 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3804 fprintf(stderr,
"For more extensive help type: %s --help\n", argv[0]);
3808 std::string dictname;
3809 std::string dictpathname;
3810 int ic, force = 0, onepcm = 0;
3811 bool ignoreExistingDict =
false;
3812 bool requestAllSymbols = isDeep;
3814 std::string currentDirectory;
3819 if (strcmp(
"-rootbuild", argv[ic]) == 0) {
3827 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kWarning;
3829 if (!strcmp(argv[ic],
"-v")) {
3830 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kError;
3832 }
else if (!strcmp(argv[ic],
"-v0")) {
3833 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kFatal;
3835 }
else if (!strcmp(argv[ic],
"-v1")) {
3836 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kError;
3838 }
else if (!strcmp(argv[ic],
"-v2")) {
3839 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kWarning;
3841 }
else if (!strcmp(argv[ic],
"-v3")) {
3842 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kNote;
3844 }
else if (!strcmp(argv[ic],
"-v4")) {
3845 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kInfo;
3850 if (!strcmp(argv[ic],
"-cint")) {
3853 }
else if (!strcmp(argv[ic],
"-reflex")) {
3856 }
else if (!strcmp(argv[ic],
"-gccxml")) {
3862 const char *libprefixOption =
"--lib-list-prefix=";
3863 std::string liblistPrefix;
3865 while (ic < argc && strncmp(argv[ic],
"-", 1) == 0
3866 && strcmp(argv[ic],
"-f") != 0 && strcmp(argv[ic],
"-r") != 0) {
3867 if (!strcmp(argv[ic],
"-l")) {
3869 }
else if (!strcmp(argv[ic],
"-1")) {
3872 }
else if (!strncmp(argv[ic], libprefixOption, strlen(libprefixOption))) {
3874 liblistPrefix = argv[ic] + strlen(libprefixOption);
3876 string filein = liblistPrefix +
".in";
3878 if ((fp = fopen(filein.c_str(),
"r")) == 0) {
3890 if (ic < argc && !strcmp(argv[ic],
"-f")) {
3893 }
else if (ic < argc && !strcmp(argv[ic],
"-r")) {
3894 ignoreExistingDict =
true;
3896 }
else if (argc > 1 && (!strcmp(argv[1],
"-?") || !strcmp(argv[1],
"-h"))) {
3899 }
else if (argc > 1 && !strcmp(argv[1],
"--help")) {
3900 fprintf(stderr, kCommandLineOptionsHelp);
3902 }
else if (ic < argc && !strncmp(argv[ic],
"-", 1)) {
3904 fprintf(stderr,
"Only one verbose flag is authorized (one of -v, -v0, -v1, -v2, -v3, -v4)\n"
3905 "and must be before the -f flags\n");
3906 fprintf(stderr,
"For more extensive help type: %s --help\n", argv[0]);
3918#if defined(R__WIN32) && !defined(R__WINGCC)
3921 for (
int iic = ic; iic < argc; ++iic) {
3922 std::string iiarg(argv[iic]);
3924 size_t len = iiarg.length();
3926 char *argviic =
new char[len + 1];
3927 strlcpy(argviic, iiarg.c_str(), len + 1);
3928 argv[iic] = argviic;
3934 tempFileNamesCatalog tmpCatalog;
3938 if (!ignoreExistingDict && (fp = fopen(argv[ic],
"r")) != 0) {
3947 if (strlen(argv[ic]) > (PATH_MAX - 1)) {
3949 (PATH_MAX - 1), argv[ic]);
3953 dictpathname = argv[ic];
3954 dictname = llvm::sys::path::filename(dictpathname);
3957 }
else if (!strcmp(argv[1],
"-?") || !strcmp(argv[1],
"-h")) {
3958 fprintf(stderr, kCommandLineOptionsHelp);
3965 if (force && dictname.empty()) {
3966 ROOT::TMetaUtils::Error(0,
"Inconsistent set of arguments detected: overwrite of dictionary file forced but no filename specified.\n");
3971 std::vector<std::string> clingArgs;
3972 clingArgs.push_back(argv[0]);
3973 clingArgs.push_back(
"-iquote.");
3975 if (ic < argc && !strcmp(argv[ic],
"-c")) {
3980 std::vector<std::string> baseModules;
3981 std::string sharedLibraryPathName;
3982 std::vector<std::string> rootmapLibNames;
3983 std::string rootmapFileName;
3984 std::vector<std::string> excludePaths;
3986 bool inlineInputHeader =
false;
3987 bool interpreteronly =
false;
3988 bool doSplit =
false;
3989 bool dictSelection =
true;
3990 bool multiDict =
false;
3991 bool writeEmptyRootPCM =
false;
3992 bool selSyntaxOnly =
false;
3993 bool noIncludePaths =
false;
3994 bool cxxmodule =
false;
3995 bool isAclic =
false;
3999 std::list<std::string> diagnosticPragmas = {
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""};
4003 if (*argv[ic] ==
'-' || *argv[ic] ==
'+') {
4005 if (strcmp(
"-rml", argv[ic]) == 0 && (ic + 1) < argc) {
4007 rootmapLibNames.push_back(argv[ic + 1]);
4012 if (strcmp(
"-rmf", argv[ic]) == 0 && (ic + 1) < argc) {
4014 rootmapFileName = argv[ic + 1];
4019 if (strcmp(
"-cxxmodule", argv[ic]) == 0) {
4025 if (strcmp(
"-multiDict", argv[ic]) == 0) {
4032 if (strcmp(
"-interpreteronly", argv[ic]) == 0) {
4034 interpreteronly =
true;
4039 if (strcmp(
"-split", argv[ic]) == 0) {
4046 if (strcmp(
"-noDictSelection", argv[ic]) == 0) {
4048 dictSelection =
false;
4053 if (strcmp(
"-s", argv[ic]) == 0 && (ic + 1) < argc) {
4055 sharedLibraryPathName = argv[ic + 1];
4061 if (strcmp(
"-m", argv[ic]) == 0 && (ic + 1) < argc) {
4063 baseModules.push_back(argv[ic + 1]);
4068 if (strcmp(
"-excludePath", argv[ic]) == 0 && (ic + 1) < argc) {
4070 excludePaths.push_back(argv[ic + 1]);
4074 if (strcmp(
"+P", argv[ic]) == 0 ||
4075 strcmp(
"+V", argv[ic]) == 0 ||
4076 strcmp(
"+STUB", argv[ic]) == 0) {
4081 if (strcmp(
"-inlineInputHeader", argv[ic]) == 0) {
4083 inlineInputHeader =
true;
4088 if (strcmp(
"-writeEmptyRootPCM", argv[ic]) == 0) {
4090 writeEmptyRootPCM =
true;
4095 if (strcmp(
"-selSyntaxOnly", argv[ic]) == 0) {
4097 selSyntaxOnly =
true;
4102 if (strcmp(
"-failOnWarnings", argv[ic]) == 0) {
4107 if (GetErrorIgnoreLevel() >
kWarning)
4109 GetWarningsAreErrors() =
true;
4114 if (strcmp(
"-noIncludePaths", argv[ic]) == 0) {
4115 noIncludePaths =
true;
4120 if ((ic + 1) < argc && strcmp(
"-isysroot", argv[ic]) == 0) {
4121 clingArgs.push_back(argv[ic++]);
4122 clingArgs.push_back(argv[ic++]);
4131 if (strcmp(
"-p", argv[ic])) {
4133 clingArgs.push_back(llvm::sys::path::convert_to_slash(argv[ic]));
4136 }
else if (nextStart == 0) {
4141 if (liblistPrefix.length())
4145 if (multiDict && sharedLibraryPathName.empty()) {
4146 ROOT::TMetaUtils::Error(
"",
"Multidict requested but no target library. Please specify one with the -s argument.\n");
4152 clingArgs.push_back(std::string(
"-I") + includeDir);
4154 std::vector<std::string> pcmArgs;
4155 for (
size_t parg = 0,
n = clingArgs.size(); parg <
n; ++parg) {
4156 auto thisArg = clingArgs[parg];
4157 auto isInclude = ROOT::TMetaUtils::BeginsWith(thisArg,
"-I");
4158 if (thisArg ==
"-c" ||
4159 (noIncludePaths && isInclude))
continue;
4162 unsigned int offset = 2;
4163 char c = thisArg[offset];
4164 while (
c ==
' ')
c = thisArg[++offset];
4165 auto excludePathsEnd = excludePaths.end();
4166 auto excludePathPos = std::find_if(excludePaths.begin(),
4168 [&](
const std::string& path){
4169 return ROOT::TMetaUtils::BeginsWith(&thisArg[offset], path);});
4170 if (excludePathsEnd != excludePathPos)
continue;
4172 pcmArgs.push_back(thisArg);
4179 clingArgs.push_back(
"-D__ROOTCLING__");
4181 clingArgs.push_back(
"-fsyntax-only");
4183 clingArgs.push_back(
"-fPIC");
4185 clingArgs.push_back(
"-Xclang");
4186 clingArgs.push_back(
"-fmodules-embed-all-files");
4187 clingArgs.push_back(
"-Xclang");
4188 clingArgs.push_back(
"-main-file-name");
4189 clingArgs.push_back(
"-Xclang");
4190 clingArgs.push_back((dictname +
".h").c_str());
4192 ROOT::TMetaUtils::SetPathsForRelocatability(clingArgs);
4197 bool isPCH = (dictpathname ==
"allDict.cxx");
4198 std::string outputFile;
4200 StringRef moduleName;
4205 auto clingArgsInterpreter = clingArgs;
4207 if (sharedLibraryPathName.empty()) {
4208 sharedLibraryPathName = dictpathname;
4211 if (!isPCH && cxxmodule) {
4218 clingArgsInterpreter.push_back(
"-modulemap_overlay=" + includeDir);
4223 clingArgsInterpreter.push_back(
"-fmodules");
4226 outputFile = llvm::sys::path::stem(sharedLibraryPathName).str();
4228 moduleName = llvm::sys::path::filename(outputFile);
4229 moduleName.consume_front(
"lib");
4230 moduleName.consume_back(
"_rdict.pcm");
4232 clingArgsInterpreter.push_back(
"-fmodule-name");
4233 clingArgsInterpreter.push_back(moduleName.str());
4237 clingArgsInterpreter.push_back(
"-fmodules-cache-path=" +
4238 llvm::sys::path::parent_path(sharedLibraryPathName).str());
4242 std::vector<const char *> clingArgsC;
4243 for (
auto const &clingArg : clingArgsInterpreter) {
4245 std::cerr <<
"Argument \""<< clingArg <<
"\" is not a supported cling argument. "
4246 <<
"This could be mistyped rootcling argument. Please check the commandline.\n";
4249 clingArgsC.push_back(clingArg.c_str());
4252#ifdef R__EXTERN_LLVMDIR
4253 std::string resourceDir = R__EXTERN_LLVMDIR;
4258 std::unique_ptr<cling::Interpreter> owningInterpPtr;
4259 cling::Interpreter* interpPtr =
nullptr;
4261 std::list<std::string> filesIncludedByLinkdef;
4264 clingArgsC.push_back(
"-resource-dir");
4265 clingArgsC.push_back(resourceDir.c_str());
4266 clingArgsC.push_back(0);
4268 extraArgs = &clingArgsC[1];
4270 if (!isGenreflex && !onepcm) {
4271 std::unique_ptr<TRootClingCallbacks> callBacks (
new TRootClingCallbacks(interpPtr, filesIncludedByLinkdef));
4272 interpPtr->setCallbacks(std::move(callBacks));
4277 clingArgsC.push_back(
"-ffast-math");
4280 owningInterpPtr.reset(
new cling::Interpreter(clingArgsC.size(), &clingArgsC[0],
4281 resourceDir.c_str()));
4282 interpPtr = owningInterpPtr.get();
4284 cling::Interpreter &interp = *interpPtr;
4285 clang::CompilerInstance *CI = interp.getCI();
4287 CI->getFrontendOpts().ModulesEmbedAllFiles =
true;
4288 CI->getSourceManager().setAllFilesAreTransient(
true);
4290 clang::Preprocessor &PP = CI->getPreprocessor();
4291 clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo();
4292 clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
4293 auto &diags = interp.getDiagnostics();
4300 diags.setSeverity(clang::diag::remark_module_build, clang::diag::Severity::Remark, clang::SourceLocation());
4304 auto recordingClient =
new CheckModuleBuildClient(diags.getClient(), diags.ownsClient(), moduleMap);
4305 diags.setClient(recordingClient,
true);
4307 if (ROOT::TMetaUtils::GetErrorIgnoreLevel() == ROOT::TMetaUtils::kInfo) {
4311 interp.DumpIncludePath();
4316 interp.printIncludedFiles(llvm::outs());
4317 llvm::outs() <<
"\n\n";
4318 llvm::outs().flush();
4321 const clang::LangOptions& LangOpts
4322 = interp.getCI()->getASTContext().getLangOpts();
4323#define LANGOPT(Name, Bits, Default, Description) \
4324 ROOT::TMetaUtils::Info(0, "%s = %d // %s\n", #Name, (int)LangOpts.Name, Description);
4325#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
4326#include "clang/Basic/LangOptions.def"
4330 interp.getOptions().ErrorOut =
true;
4331 interp.enableRawInput(
true);
4333 if (interp.declare(
"namespace std {} using namespace std;") != cling::Interpreter::kSuccess) {
4340 if (interp.declare(
"namespace std {} using namespace std;") != cling::Interpreter::kSuccess
4342 || interp.declare(
"#include <assert.h>\n"
4343 "#include <stdlib.h>\n"
4344 "#include <stddef.h>\n"
4345 "#include <string.h>\n"
4346 ) != cling::Interpreter::kSuccess
4347 || interp.declare(
"#include \"Rtypes.h\"\n"
4348 "#include \"TClingRuntime.h\"\n"
4349 "#include \"TObject.h\""
4350 ) != cling::Interpreter::kSuccess
4359 interp.declare(
"#include <string>");
4362 ROOT::TMetaUtils::TNormalizedCtxt normCtxt(interp.getLookupHelper());
4363 ROOT::TMetaUtils::TClingLookupHelper helper(interp, normCtxt, 0, 0,
nullptr);
4367 clingArgs.push_back(
"-D__CINT__");
4368 clingArgs.push_back(
"-D__MAKECINT__");
4371 clingArgs.push_back(
"-D_XKEYCHECK_H");
4376 std::string interpPragmaSource;
4377 std::string includeForSource;
4378 std::string interpreterDeclarations;
4380 int firstInputFile = 0;
4382 for (
int i = ic; i < argc; i++) {
4383 if (strcmp(
"-m", argv[i]) == 0 && (i + 1) < argc) {
4385 baseModules.push_back(argv[ic + 1]);
4389 if (!firstInputFile && *argv[i] !=
'-' && *argv[i] !=
'+') {
4394 if (i != argc - 1) {
4399 if (!strcmp(argv[i],
"-c")) {
4410 if (*argv[i] !=
'-' && *argv[i] !=
'+') {
4416 std::string fullheader(argv[i]);
4419 if (fullheader[fullheader.length() - 1] ==
'+') {
4420 fullheader.erase(fullheader.length() - 1);
4424 interpPragmaSource += std::string(
"#include \"") + header +
"\"\n";
4425 if (!isSelectionFile) {
4433 includeForSource += std::string(
"#include \"") + fullheader +
"\"\n";
4434 pcmArgs.push_back(header);
4436 interpreterDeclarations += std::string(
"#include \"") + header +
"\"\n";
4443 for (
const auto & baseModule : baseModules)
4447 if (!firstInputFile) {
4456 std::string newName = llvm::sys::path::parent_path(sharedLibraryPathName).str();
4457 if (!newName.empty())
4459 newName += llvm::sys::path::stem(sharedLibraryPathName);
4461 newName += llvm::sys::path::stem(dictpathname);
4463 sharedLibraryPathName = newName;
4470 string incCurDir =
"-I";
4471 incCurDir += currentDirectory;
4472 pcmArgs.push_back(incCurDir);
4477 std::stringstream res;
4478 const char* delim=
"\n";
4479 std::copy(diagnosticPragmas.begin(),
4480 diagnosticPragmas.end(),
4481 std::ostream_iterator<std::string>(res, delim));
4482 interp.declare(res.str());
4485 class IgnoringPragmaHandler:
public clang::PragmaNamespace {
4487 IgnoringPragmaHandler(
const char* pragma):
4488 clang::PragmaNamespace(pragma) {}
4489 void HandlePragma(clang::Preprocessor &PP,
4490 clang::PragmaIntroducerKind Introducer,
4491 clang::Token &tok) {
4492 PP.DiscardUntilEndOfDirective();
4498 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"link"));
4499 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"extra_include"));
4500 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"read"));
4501 PP.AddPragmaHandler(
new IgnoringPragmaHandler(
"create"));
4503 if (!interpreterDeclarations.empty() &&
4504 interp.declare(interpreterDeclarations) != cling::Interpreter::kSuccess) {
4512 sharedLibraryPathName,
4516 pcmArgs.push_back(argv[linkdefLoc]);
4524 interp.AddIncludePath(inclPath);
4526 std::stringstream definesUndefinesStr;
4529 if (!definesUndefinesStr.str().empty())
4530 interp.declare(definesUndefinesStr.str());
4544 std::ofstream fileout;
4545 string main_dictname(dictpathname);
4546 std::ostream *dictStreamPtr = NULL;
4547 if (!ignoreExistingDict) {
4548 if (!dictpathname.empty()) {
4549 tmpCatalog.addFileName(dictpathname);
4550 fileout.open(dictpathname.c_str());
4551 dictStreamPtr = &fileout;
4552 if (!(*dictStreamPtr)) {
4554 dictpathname.c_str());
4558 dictStreamPtr = &std::cout;
4561 fileout.open(
"/dev/null");
4562 dictStreamPtr = &fileout;
4567 std::ostream &dictStream = *dictStreamPtr;
4568 std::ostream &splitDictStream = *splitDictStreamPtr;
4570 size_t dh = main_dictname.rfind(
'.');
4571 if (dh != std::string::npos) {
4572 main_dictname.erase(dh);
4575 std::string main_dictname_copy(main_dictname);
4576 TMetaUtils::GetCppName(main_dictname, main_dictname_copy.c_str());
4586 string linkdefFilename;
4588 linkdefFilename =
"in memory";
4590 bool found =
Which(interp, argv[linkdefLoc], linkdefFilename);
4598 std::vector<std::pair<std::string, std::string>> namesForExclusion;
4601 namesForExclusion.push_back(std::make_pair(ROOT::TMetaUtils::propNames::pattern,
"ROOT::Meta::Selection*"));
4604 SelectionRules selectionRules(interp, normCtxt, namesForExclusion);
4606 std::string extraIncludes;
4608 ROOT::TMetaUtils::RConstructorTypes constructorTypes;
4611 const unsigned int selRulesInitialSize = selectionRules.
Size();
4612 if (dictSelection && !onepcm)
4613 ROOT::Internal::DictSelectionReader dictSelReader(interp, selectionRules, CI->getASTContext(), normCtxt);
4615 bool dictSelRulesPresent = selectionRules.
Size() > selRulesInitialSize;
4619 int rootclingRetCode(0);
4621 if (requestAllSymbols && !isSelXML) {
4623 }
else if (!linkdefLoc) {
4628 clingArgs.push_back(
"-Ietc/cling/cint");
4630 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4631 resourceDir.c_str())) {
4633 rootclingRetCode += 1;
4643 }
else if (isSelXML) {
4647 std::ifstream
file(linkdefFilename.c_str());
4648 if (
file.is_open()) {
4652 if (!xmlr.
Parse(linkdefFilename.c_str(), selectionRules)) {
4665 std::ifstream
file(linkdefFilename.c_str());
4666 if (
file.is_open()) {
4676 clingArgs.push_back(
"-Ietc/cling/cint");
4678 if (!ldefr.
Parse(selectionRules, interpPragmaSource, clingArgs,
4679 resourceDir.c_str())) {
4681 rootclingRetCode += 1;
4716 dictStream <<
"#include \"TBuffer.h\"\n"
4717 <<
"#include \"TVirtualObject.h\"\n"
4718 <<
"#include <vector>\n"
4719 <<
"#include \"TSchemaHelper.h\"\n\n";
4721 std::list<std::string> includes;
4723 for (
auto & incFile : includes) {
4724 dictStream <<
"#include <" << incFile <<
">" << std::endl;
4726 dictStream << std::endl;
4731 int scannerVerbLevel = 0;
4734 scannerVerbLevel = GetErrorIgnoreLevel() ==
kInfo;
4736 scannerVerbLevel = GetErrorIgnoreLevel() <
kWarning;
4754 if (liblistPrefix.length()) {
4759 if (requestAllSymbols) {
4763 scan.
Scan(CI->getASTContext());
4765 bool has_input_error =
false;
4770 if (ROOT::TMetaUtils::GetErrorIgnoreLevel() != ROOT::TMetaUtils::kFatal &&
4772 !dictSelRulesPresent &&
4779 if (rootclingRetCode)
return rootclingRetCode;
4785 if (ROOT::TMetaUtils::ClassInfo__HasMethod(annRcd,
"Streamer", interp)) {
4786 if (annRcd.RequestNoInputOperator()) {
4787 int version = ROOT::TMetaUtils::GetClassVersion(annRcd, interp);
4798 if (has_input_error) {
4808 for (
auto &&includedFromLinkdef : filesIncludedByLinkdef) {
4809 includeForSource +=
"#include \"" + includedFromLinkdef +
"\"\n";
4825 if (!interpreteronly) {
4826 constructorTypes.push_back(ROOT::TMetaUtils::RConstructorType(
"TRootIOCtor", interp));
4827 constructorTypes.push_back(ROOT::TMetaUtils::RConstructorType(
"__void__", interp));
4828 constructorTypes.push_back(ROOT::TMetaUtils::RConstructorType(
"", interp));
4834 }
else if (interpreteronly) {
4851 if (rootclingRetCode != 0) {
4852 return rootclingRetCode;
4855 if (doSplit && splitDictStreamPtr)
delete splitDictStreamPtr;
4861 if (!ignoreExistingDict) {
4873 std::string detectedUmbrella;
4874 for (
auto & arg : pcmArgs) {
4876 detectedUmbrella = arg;
4881 if (writeEmptyRootPCM){
4882 headersDeclsMap.clear();
4889 std::string fwdDeclsString =
"\"\"";
4891 if (writeEmptyRootPCM) {
4892 fwdDeclsString =
"nullptr";
4898 modGen.
WriteRegistrationSource(dictStream, fwdDeclnArgsToKeepString, headersClassesMapString, fwdDeclsString, extraIncludes);
4901 if (!inlineInputHeader) {
4903 if (modGen.
IsPCH()) {
4905 }
else if (cxxmodule && !isAclic) {
4906 if (!
CheckModuleValid(modGen, resourceDir, interp, linkdefFilename, moduleName.str()))
4913 if (liblistPrefix.length()) {
4914 string liblist_filename = liblistPrefix +
".out";
4916 ofstream outputfile(liblist_filename.c_str(), ios::out);
4919 argv[0], liblist_filename.c_str());
4921 const size_t endStr =
gLibsNeeded.find_last_not_of(
" \t");
4922 outputfile <<
gLibsNeeded.substr(0, endStr + 1) << endl;
4924 outputfile <<
"# Now the list of classes\n";
4929 outputfile << annRcd.GetNormalizedName() << endl;
4936 if (0 != rootclingRetCode)
return rootclingRetCode;
4939 std::string rootmapLibName = std::accumulate(rootmapLibNames.begin(),
4940 rootmapLibNames.end(),
4942 [](
const std::string &
a,
const std::string &
b) -> std::string {
4943 if (a.empty()) return b;
4944 else return a +
" " + b;
4947 bool rootMapNeeded = !rootmapFileName.empty() || !rootmapLibName.empty();
4949 std::list<std::string> classesNames;
4950 std::list<std::string> classesNamesForRootmap;
4951 std::list<std::string> classesDefsList;
4955 classesNamesForRootmap,
4959 std::list<std::string> enumNames;
4964 std::list<std::string> varNames;
4969 if (0 != rootclingRetCode)
return rootclingRetCode;
4972 if (rootMapNeeded) {
4974 std::list<std::string> nsNames;
4982 rootmapFileName.c_str(),
4983 rootmapLibName.c_str());
4985 tmpCatalog.addFileName(rootmapFileName);
4986 std::unordered_set<std::string> headersToIgnore;
4987 if (inlineInputHeader) {
4988 for (
int index = 0; index < argc; ++index) {
4989 if (*argv[index] !=
'-' && ROOT::TMetaUtils::IsHeaderName(argv[index])) {
4990 headersToIgnore.insert(argv[index]);
4995 std::list<std::string> typedefsRootmapLines;
5003 classesNamesForRootmap,
5005 typedefsRootmapLines,
5011 if (0 != rootclingRetCode)
return 1;
5022 cling::Interpreter::PushTransactionRAII RAII(&interp);
5023 CI->getSema().getASTConsumer().HandleTranslationUnit(CI->getSema().getASTContext());
5024 CI->clearOutputFiles(CI->getDiagnostics().hasErrorOccurred());
5028 rootclingRetCode += ROOT::TMetaUtils::GetNumberOfErrors();
5035 if(rootclingRetCode == 0) {
5036 rootclingRetCode += tmpCatalog.commit();
5041 return rootclingRetCode;
5052 unsigned int numberOfHeaders = 0;
5053 for (std::vector<std::string>::iterator it = headersNames.begin();
5054 it != headersNames.end(); ++it) {
5055 const std::string headername(*it);
5056 if (ROOT::TMetaUtils::IsHeaderName(headername)) {
5060 "*** genreflex: %s is not a valid header name (.h and .hpp extensions expected)!\n",
5061 headername.c_str());
5064 return numberOfHeaders;
5070 unsigned int extractArgs(
int argc,
char **argv, std::vector<std::string> &args)
5073 unsigned int argvCounter = 0;
5074 for (
int i = 1; i < argc; ++i) {
5075 if (!ROOT::TMetaUtils::BeginsWith(argv[i - 1],
"-") &&
5076 !ROOT::TMetaUtils::BeginsWith(argv[i],
"-")) {
5077 args.push_back(argv[i]);
5079 }
else if (argvCounter) {
5080 argv[i - argvCounter] = argv[i];
5087 std::cout <<
"Args: \n";
5088 for (std::vector<std::string>::iterator it = args.begin();
5089 it < args.end(); ++it) {
5090 std::cout << i <<
") " << *it << std::endl;
5103 size_t result = filename.find_last_of(
'.');
5104 if (std::string::npos != result) {
5105 filename.erase(result);
5106 filename.append(newExtension);
5116 const unsigned int size(str.size());
5117 char *
a =
new char[size + 1];
5119 memcpy(
a, str.c_str(), size);
5135 std::vector<std::string> &ofilesnames)
5137 ofilesnames.reserve(headersNames.size());
5139 for (std::vector<std::string>::const_iterator it = headersNames.begin();
5140 it != headersNames.end(); ++it) {
5141 std::string ofilename(*it);
5143 ofilesnames.push_back(ofilename);
5150 const std::vector<std::string> &argsToBeAdded,
5151 const std::string &optName =
"")
5153 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5154 it != argsToBeAdded.end(); ++it) {
5162 const std::vector<std::string> &argsToBeAdded,
5163 const std::string &optName =
"")
5165 for (std::vector<std::string>::const_iterator it = argsToBeAdded.begin();
5166 it != argsToBeAdded.end(); ++it) {
5167 if (optName.length()) {
5177 const std::string &selectionFileName,
5178 const std::string &targetLibName,
5180 const std::vector<std::string> &pcmsNames,
5181 const std::vector<std::string> &includes,
5182 const std::vector<std::string> &preprocDefines,
5183 const std::vector<std::string> &preprocUndefines,
5184 const std::vector<std::string> &warnings,
5185 const std::string &rootmapFileName,
5186 const std::string &rootmapLibName,
5187 bool interpreteronly,
5191 bool writeEmptyRootPCM,
5193 bool noIncludePaths,
5194 const std::vector<std::string> &headersNames,
5195 bool failOnWarnings,
5196 const std::string &ofilename)
5200 std::vector<char *> argvVector;
5211 std::string dictLocation;
5217 std::string newRootmapLibName(rootmapLibName);
5218 if (!rootmapFileName.empty() && newRootmapLibName.empty()) {
5219 if (headersNames.size() != 1) {
5221 "*** genreflex: No rootmap lib and several header specified!\n");
5224 newRootmapLibName =
"lib";
5225 newRootmapLibName += cleanHeaderName;
5231 std::string newRootmapFileName(rootmapFileName);
5232 if (!newRootmapFileName.empty() && !
HasPath(newRootmapFileName)) {
5233 newRootmapFileName = dictLocation + newRootmapFileName;
5238 if (!newRootmapFileName.empty()) {
5244 if (!newRootmapLibName.empty()) {
5250 if (interpreteronly)
5258 if (!targetLibName.empty()) {
5274 if (writeEmptyRootPCM)
5297 if (!selectionFileName.empty()) {
5301 const int argc = argvVector.size();
5305 std::cout <<
"Rootcling commandline:\n";
5306 for (
int i = 0; i < argc; i++)
5307 std::cout << i <<
") " << argvVector[i] << std::endl;
5310 char **argv = & (argvVector[0]);
5316 for (
int i = 0; i < argc; i++)
5317 delete [] argvVector[i];
5319 return rootclingReturnCode;
5328 const std::string &selectionFileName,
5329 const std::string &targetLibName,
5331 const std::vector<std::string> &pcmsNames,
5332 const std::vector<std::string> &includes,
5333 const std::vector<std::string> &preprocDefines,
5334 const std::vector<std::string> &preprocUndefines,
5335 const std::vector<std::string> &warnings,
5336 const std::string &rootmapFileName,
5337 const std::string &rootmapLibName,
5338 bool interpreteronly,
5342 bool writeEmptyRootPCM,
5344 bool noIncludePaths,
5345 const std::vector<std::string> &headersNames,
5346 bool failOnWarnings,
5347 const std::string &outputDirName_const =
"")
5349 std::string outputDirName(outputDirName_const);
5351 std::vector<std::string> ofilesNames;
5354 if (!outputDirName.empty() && !ROOT::TMetaUtils::EndsWith(outputDirName,
gPathSeparator)) {
5358 std::vector<std::string> namesSingleton(1);
5359 for (
unsigned int i = 0; i < headersNames.size(); ++i) {
5360 namesSingleton[0] = headersNames[i];
5361 std::string ofilenameFullPath(ofilesNames[i]);
5362 if (llvm::sys::path::parent_path(ofilenameFullPath) ==
"")
5363 ofilenameFullPath = outputDirName + ofilenameFullPath;
5385 if (returnCode != 0)
5400 std::vector<std::string> &values)
5403 if (options[oIndex]) {
5404 const int nVals = options[oIndex].count();
5405 values.reserve(nVals);
5406 int optionIndex = 0;
5409 << optionIndex <<
"/" << nVals <<
" "
5410 << opt->arg << std::endl;
5412 values.push_back(opt->arg);
5423 const char *descriptor)
5425 if (options[optionIndex]) {
5427 "*** genereflex: %s is not supported anymore.\n",
5440 isGood |= ROOT::TMetaUtils::EndsWith(
name,
".dylib");
5485 enum optionIndex { UNKNOWN,
5515 enum optionTypes { NOTYPE, STRING } ;
5518 const char *genreflexUsage =
5519 "Generates dictionary sources and related ROOT pcm starting from an header.\n"
5520 "Usage: genreflex headerfile.h [opts] [preproc. opts]\n\n"
5523 const char *selectionFilenameUsage =
5524 "-s, --selection_file\tSelection filename\n"
5525 " Class selection file to specify for which classes the dictionary\n"
5526 " will be generated. The final set can be crafted with exclusion and\n"
5527 " exclusion rules.\n"
5528 " Properties can be specified. Some have special meaning:\n"
5529 " - name [string] name of the entity to select with an exact matching\n"
5530 " - pattern [string] name with wildcards (*) to select entities\n"
5531 " - file_name/file_pattern [string]: as name/pattern but referring to\n"
5532 " file where the C++ entities reside and not to C++ entities themselves.\n"
5533 " - transient/persistent [string: true/false] The fields to which they are\n"
5534 " applied will not be persistified if requested.\n"
5535 " - comment [string]: what you could write in code after an inline comment\n"
5536 " without \"//\". For example comment=\"!\" or \"||\".\n"
5537 " - noStreamer [true/false]: turns off streamer generation if set to 'true.'\n"
5538 " Default value is 'false'\n"
5539 " - noInputOperator [true/false]: turns off input operator generation if set\n"
5540 " to 'true'. Default value is 'false'\n"
5544 " <class [name=\"classname\"] [pattern=\"wildname\"]\n"
5545 " [file_name=\"filename\"] [file_pattern=\"wildname\"]\n"
5546 " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n"
5547 " [noInputOperator=\"true/false\"] />\n"
5548 " <class name=\"classname\" >\n"
5549 " <field name=\"m_transient\" transient=\"true\"/>\n"
5550 " <field name=\"m_anothertransient\" persistent=\"false\"/>\n"
5551 " <field name=\"m_anothertransient\" comment=\"||\"/>\n"
5552 " <properties prop1=\"value1\" [prop2=\"value2\"]/>\n"
5554 " <function [name=\"funcname\"] [pattern=\"wildname\"] />\n"
5555 " <enum [name=\"enumname\"] [pattern=\"wildname\"] />\n"
5556 " <variable [name=\"varname\"] [pattern=\"wildname\"] />\n"
5559 " <class [name=\"classname\"] [pattern=\"wildname\"] />\n"
5560 " <method name=\"unwanted\" />\n"
5565 " If no selection file is specified, the class with the filename without\n"
5566 " extension will be selected, i.e. myClass.h as argument without any\n"
5567 " selection xml comes with an implicit selection rule for class \"myClass\".\n";
5569 const char *outputFilenameUsage =
5570 "-o, --output\tOutput filename\n"
5571 " Output file name. If an existing directory is specified instead of a file,\n"
5572 " then a filename will be build using the name of the input file and will\n"
5573 " be placed in the given directory. <headerfile>_rflx.cpp.\n"
5574 " NOTA BENE: the dictionaries that will be used within the same project must\n"
5575 " have unique names.\n";
5578 const char *targetLib =
5579 "-l, --library\tTarget library\n"
5580 " The flag -l must be followed by the name of the library that will\n"
5581 " contain the object file corresponding to the dictionary produced by\n"
5582 " this invocation of genreflex.\n"
5583 " The name takes priority over the one specified for the rootmapfile.\n"
5584 " The name influences the name of the created pcm:\n"
5585 " 1) If it is not specified, the pcm is called libINPUTHEADER_rdict.pcm\n"
5586 " 2) If it is specified, the pcm is called libTARGETLIBRARY_rdict.pcm\n"
5587 " Any \"liblib\" occurence is transformed in the expected \"lib\".\n"
5588 " 3) If this is specified in conjunction with --multiDict, the output is\n"
5589 " libTARGETLIBRARY_DICTIONARY_rdict.pcm\n";
5591 const char *rootmapUsage =
5592 "--rootmap\tGenerate the rootmap file to be used by ROOT.\n"
5593 " This file lists the autoload keys. For example classes for which the\n"
5594 " reflection information is provided.\n"
5595 " The format of the rootmap is the following:\n"
5596 " - Forward declarations section\n"
5597 " - Libraries sections\n"
5598 " Rootmaps can be concatenated together, for example with the cat util.\n"
5599 " In order for ROOT to pick up the information in the rootmaps, they\n"
5600 " have to be located in the library path and have the .rootmap extension.\n"
5601 " An example rootmap file could be:\n"
5603 " template <class T> class A;\n"
5604 " [ libMyLib.so ]\n"
5605 " class A<double>\n"
5610 const char *rootmapLibUsage =
5611 "--rootmap-lib\tLibrary name for the rootmap file.\n";
5644 "--multiDict\tSupport for many dictionaries in one library\n"
5645 " Form correct pcm names if multiple dictionaries will be in the same\n"
5646 " library (needs target library switch. See its documentation).\n"
5652 "s" ,
"selection_file" ,
5654 selectionFilenameUsage
5668 "" ,
"rootmap-lib" ,
5676 "" ,
"interpreteronly",
5678 "--interpreteronly\tDo not generate I/O related information.\n"
5679 " Generate minimal dictionary required for interactivity.\n"
5687 "--split\tSplit the dictionary\n"
5688 " Split in two the dictionary, isolating the part with\n"
5689 " ClassDef related functions in a separate file.\n"
5697 "-m \tPcm file loaded before any header (option can be repeated).\n"
5714 "-v, --verbose\tPrint some debug information.\n"
5722 "--debug\tPrint all debug information.\n"
5730 "--quiet\tPrint only warnings and errors (default).\n"
5738 "--silent\tPrint no information at all.\n"
5744 "" ,
"writeEmptyPCM",
5746 "--writeEmptyPCM\tWrite an empty ROOT pcm.\n"
5754 "--cxxmodule\tGenerates a PCM for C++ Modules.\n"
5763 "--help\tPrint usage and exit.\n"
5769 "",
"fail_on_warnings",
5771 "--fail_on_warnings\tFail on warnings and errors.\n"
5777 "",
"selSyntaxOnly",
5779 "--selSyntaxOnly\tValidate selection file w/o generating the dictionary.\n"
5785 "" ,
"noIncludePaths",
5787 "--noIncludePaths\tDo not store the headers' directories in the dictionary. Instead, rely on the environment variable $ROOT_INCLUDE_PATH at runtime.\n"
5826 "" ,
"no_membertypedefs" ,
5834 "" ,
"no_templatetypedefs" ,
5842 std::vector<std::string> headersNames;
5843 const int originalArgc = argc;
5845 const int extractedArgs =
extractArgs(argc, argv, headersNames);
5847 const int offset = 1;
5848 argc -= offset + extractedArgs;
5853 std::vector<ROOT::option::Option> options(stats.
options_max);
5854 std::vector<ROOT::option::Option> buffer(stats.
buffer_max);
5860 if (parse.
error()) {
5866 if (options[HELP] || originalArgc == 1) {
5872 if (0 == numberOfHeaders) {
5877 ROOT::TMetaUtils::GetErrorIgnoreLevel() = ROOT::TMetaUtils::kNote;
5881 std::string verbosityOption(
"-v2");
5882 if (options[SILENT]) verbosityOption =
"-v0";
5883 if (options[
VERBOSE] || getenv (
"VERBOSE")) verbosityOption =
"-v3";
5884 if (options[
DEBUG]) verbosityOption =
"-v4";
5889 std::string selectionFileName;
5890 if (options[SELECTIONFILENAME]) {
5891 selectionFileName = options[SELECTIONFILENAME].arg;
5892 if (!ROOT::TMetaUtils::EndsWith(selectionFileName,
".xml")) {
5894 "Invalid selection file extension: filename is %s and extension .xml is expected!\n",
5895 selectionFileName.c_str());
5910 std::string rootmapFileName(options[ROOTMAP].arg ? options[ROOTMAP].arg :
"");
5911 std::string rootmapLibName(options[ROOTMAPLIB].arg ? options[ROOTMAPLIB].arg :
"");
5914 std::string targetLibName;
5915 if (options[TARGETLIB]) {
5916 targetLibName = options[TARGETLIB].arg;
5919 "Invalid target library extension: filename is %s and extension %s is expected!\n",
5920 targetLibName.c_str(),
5924 if (options[ROOTMAP]) {
5929 bool isCxxmodule = options[CXXMODULE];
5931 bool multidict =
false;
5932 if (options[MULTIDICT]) multidict =
true;
5934 if (multidict && targetLibName.empty()) {
5936 "Multilib support is requested but no target lib is specified. A sane pcm name cannot be formed.\n");
5940 bool interpreteronly =
false;
5941 if (options[INTERPRETERONLY])
5942 interpreteronly =
true;
5944 bool doSplit =
false;
5948 bool writeEmptyRootPCM =
false;
5949 if (options[WRITEEMPTYROOTPCM])
5950 writeEmptyRootPCM =
true;
5952 bool selSyntaxOnly =
false;
5953 if (options[SELSYNTAXONLY]) {
5954 selSyntaxOnly =
true;
5957 bool noIncludePaths =
false;
5958 if (options[NOINCLUDEPATHS]) {
5959 noIncludePaths =
true;
5962 bool failOnWarnings =
false;
5963 if (options[FAILONWARNINGS]) {
5964 failOnWarnings =
true;
5973 std::vector<std::string> pcmsNames;
5977 std::vector<std::string> preprocDefines;
5981 std::vector<std::string> preprocUndefines;
5985 std::vector<std::string> includes;
5989 std::vector<std::string> warnings;
6000 int returnValue = 0;
6001 std::string ofileName(options[OFILENAME] ? options[OFILENAME].arg :
"");
6004 bool isDeep =
false;
6008 if (!ofileName.empty() && !llvm::sys::fs::is_directory(ofileName)) {
6065 assert(!
gDriverConfig &&
"Driver configuration already set!");
6079 if (std::string::npos != exeName.find(
"rootcling")) {
6081 }
else if (std::string::npos != exeName.find(
"genreflex")) {
6089 auto nerrors = ROOT::TMetaUtils::GetNumberOfErrors();
Select classes and assign properties using C++ syntax.
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,...
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes) const
const std::string & GetUmbrellaName() const
const std::vector< std::string > & GetIncludePaths() 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.
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.
Namespace for new ROOT classes and functions.
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)
char * DemangleName(const char *mangled_name, int &errorCode)
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".
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 isDeep, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, const std::vector< std::string > &headersNames, bool failOnWarnings, const std::string &ofilename)
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)
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!
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 isDeep, bool isCxxmodule, bool writeEmptyRootPCM, bool selSyntaxOnly, bool noIncludePaths, 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 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).
void RiseWarningIfPresent(std::vector< ROOT::option::Option > &options, int optionIndex, const char *descriptor)
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.
int ShouldIgnoreClingArgument(const std::string &argument)
Returns >0 if argument is to be ignored.
std::string ExtractFileName(const std::string &path)
Extract the filename from a fullpath.
static void GetCurrentDirectory(std::string &output)
void CheckForMinusW(const char *arg, std::list< std::string > &diagnosticPragmas)
Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" For example -Wno-deprecat...
bool IsImplementationName(const std::string &filename)
const std::string gLibraryExtension(".so")
int GenReflexMain(int argc, char **argv)
Translate the arguments of genreflex into rootcling ones and forward them to the RootCling function.
int RootClingMain(int argc, char **argv, bool isDeep=false, bool isGenreflex=false)
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 AnnotateFieldDecl(clang::FieldDecl &decl, const std::list< VariableSelectionRule > &fieldSelRules, bool isGenreflex)
map< string, string > gAutoloads
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())
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.
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.
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 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)
bool ProcessAndAppendIfNotThere(const std::string &el, std::list< std::string > &el_list, std::unordered_set< std::string > &el_set)
Separate multiline strings.
const ROOT::Internal::RootCling::DriverConfig * gDriverConfig
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)
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)
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.
void ParseRootMapFile(ifstream &file, map< string, string > &autoloads)
Parse the rootmap and add entries to the autoload map.
std::pair< std::string, std::string > GetExternalNamespaceAndContainedEntities(const std::string line)
Performance is not critical here.
void AddPlatformDefines(std::vector< std::string > &clingArgs)
std::string GenerateFwdDeclString(const RScanner &scan, const cling::Interpreter &interp)
Generate the fwd declarations of the selected entities.
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...
void WriteAutoStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream)
static std::string GetRelocatableHeaderName(const std::string &header, const std::string ¤tDirectory)
Convert to path relative to $PWD If that's not what the caller wants, she should pass -I to rootcling...
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)
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)
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...
void CallWriteStreamer(const ROOT::TMetaUtils::AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
void GenerateLinkdef(int *argc, char **argv, int firstInputFile, std::string &code_for_parser)
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)
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.
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)
bool HasPath(const std::string &name)
Check if file has a path.
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)
static void output(int code)