24#include <unordered_set>
27#include "RConfigure.h"
36#include "clang/AST/ASTContext.h"
37#include "clang/AST/Attr.h"
38#include "clang/AST/CXXInheritance.h"
39#include "clang/AST/Decl.h"
40#include "clang/AST/DeclTemplate.h"
41#include "clang/AST/Mangle.h"
42#include "clang/AST/Type.h"
43#include "clang/AST/TypeVisitor.h"
44#include "clang/Frontend/CompilerInstance.h"
45#include "clang/Lex/HeaderSearch.h"
46#include "clang/Lex/ModuleMap.h"
47#include "clang/Lex/Preprocessor.h"
48#include "clang/AST/QualTypeNames.h"
49#include "clang/Lex/PreprocessorOptions.h"
51#include "clang/Sema/Lookup.h"
52#include "clang/Sema/Sema.h"
53#include "clang/Sema/SemaDiagnostic.h"
55#include "cling/Interpreter/LookupHelper.h"
56#include "cling/Interpreter/Transaction.h"
57#include "cling/Interpreter/Interpreter.h"
58#include "cling/Utils/AST.h"
59#include "cling/Interpreter/InterpreterAccessRAII.h"
61#include "llvm/Support/Path.h"
62#include "llvm/Support/FileSystem.h"
67#define strncasecmp _strnicmp
78 llvm::SmallString<256> result_path;
79 llvm::sys::fs::real_path(path, result_path,
true);
80 return result_path.str().str();
87 using DeclsCont_t = TNormalizedCtxt::Config_t::SkipCollection;
104 bool replace =
false);
114static clang::NestedNameSpecifier AddDefaultParametersNNS(
const clang::ASTContext& Ctx,
115 clang::NestedNameSpecifier scope,
116 const cling::Interpreter &interpreter,
118 if (scope.getKind() == clang::NestedNameSpecifier::Kind::Type) {
119 const clang::Type* scope_type = scope.getAsType();
121 clang::NestedNameSpecifier outer_scope = scope.getAsType()->getPrefix();
123 outer_scope = AddDefaultParametersNNS(Ctx, outer_scope, interpreter, normCtxt);
126 clang::QualType addDefault =
129 if (addDefault.getTypePtr() != scope_type)
130 return clang::NestedNameSpecifier(addDefault.getTypePtr());
137static bool CheckDefinition(
const clang::CXXRecordDecl *cl,
const clang::CXXRecordDecl *context)
139 if (!cl->hasDefinition()) {
142 "Missing definition for class %s, please #include its header in the header of %s\n",
143 cl->getName().str().c_str(), context->getName().str().c_str());
146 "Missing definition for class %s\n",
147 cl->getName().str().c_str());
156static bool IsTypeInt(
const clang::Type *
type)
158 const clang::BuiltinType * builtin = llvm::dyn_cast<clang::BuiltinType>(
type->getCanonicalTypeInternal().getTypePtr());
160 return builtin->isInteger();
168static bool IsFieldDeclInt(
const clang::FieldDecl *field)
170 return IsTypeInt(field->getType().getTypePtr());
176static const clang::FieldDecl *GetDataMemberFromAll(
const clang::CXXRecordDecl &cl, llvm::StringRef
what)
178 clang::ASTContext &
C = cl.getASTContext();
179 clang::DeclarationName DName = &
C.Idents.get(
what);
180 auto R = cl.lookup(DName);
181 for (
const clang::NamedDecl *D :
R)
182 if (auto FD =
llvm::dyn_cast<const
clang::FieldDecl>(D))
190static const clang::FieldDecl *GetDataMemberFromAllParents(clang::Sema &SemaR,
const clang::CXXRecordDecl &cl,
const char *
what)
192 clang::DeclarationName DName = &SemaR.Context.Idents.get(
what);
193 clang::LookupResult
R(SemaR, DName, clang::SourceLocation(),
194 clang::Sema::LookupOrdinaryName,
195 RedeclarationKind::ForExternalRedeclaration);
196 SemaR.LookupInSuper(
R, &
const_cast<clang::CXXRecordDecl&
>(cl));
199 return llvm::dyn_cast<const clang::FieldDecl>(
R.getFoundDecl());
203cling::LookupHelper::DiagSetting ToLHDS(
bool wantDiags) {
205 ? cling::LookupHelper::WithDiagnostics
206 : cling::LookupHelper::NoDiagnostics;
213namespace TMetaUtils {
222 Error(
"TNormalizedCtxt::AddTemplAndNargsToKeep",
223 "Tring to specify a number of template arguments to keep for a null pointer. Exiting without assigning any value.\n");
227 const clang::ClassTemplateDecl* canTempl = templ->getCanonicalDecl();
231 const std::string templateName (canTempl->getNameAsString());
232 const std::string i_str (std::to_string(i));
234 Error(
"TNormalizedCtxt::AddTemplAndNargsToKeep",
235 "Tring to specify for template %s %s arguments to keep, while before this number was %s\n",
236 canTempl->getNameAsString().c_str(),
238 previousArgsToKeep.c_str());
249 const clang::ClassTemplateDecl* constTempl = templ->getCanonicalDecl();
293 const std::string &normalizedName)
297 if (normalizedName.find(
"Double32_t") != std::string::npos
298 || normalizedName.find(
"Float16_t") != std::string::npos)
300 std::unique_ptr<clang::MangleContext> mangleCtx(rDecl->getASTContext().createMangleContext());
301 std::string mangledName;
303 llvm::raw_string_ostream sstr(mangledName);
304 if (
const clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(rDecl)) {
305 mangleCtx->mangleCXXRTTI(rDecl->getASTContext().getTypeDeclType(TD), sstr);
308 if (!mangledName.empty()) {
311 if (mangledName[0] ==
'\01')
312 mangledName.erase(0, 1);
314 if (!errDemangle && demangledTIName) {
315 static const char typeinfoNameFor[] =
" `RTTI Type Descriptor'";
316 if (strstr(demangledTIName, typeinfoNameFor)) {
317 std::string demangledName = demangledTIName;
318 demangledName.erase(demangledName.end() - strlen(typeinfoNameFor), demangledName.end());
321 if (!errDemangle && demangledTIName) {
322 static const char typeinfoNameFor[] =
"typeinfo for ";
323 if (!strncmp(demangledTIName, typeinfoNameFor, strlen(typeinfoNameFor))) {
324 std::string demangledName = demangledTIName + strlen(typeinfoNameFor);
326 free(demangledTIName);
327 return demangledName;
331 "Demangled typeinfo name '%s' does not contain `RTTI Type Descriptor'\n",
335 "Demangled typeinfo name '%s' does not start with 'typeinfo for'\n",
340 free(demangledTIName);
352 const clang::RecordDecl *decl,
355 bool rRequestNoInputOperator,
356 bool rRequestOnlyTClass,
357 int rRequestedVersionNumber,
358 int rRequestedRNTupleSerializationMode,
359 const std::string &rRequestedRNTupleSoARecord,
360 const cling::Interpreter &interpreter,
382 const clang::Type *requestedType,
383 const clang::RecordDecl *decl,
384 const char *requestName,
385 unsigned int nTemplateArgsToSkip,
388 bool rRequestNoInputOperator,
389 bool rRequestOnlyTClass,
390 int rRequestVersionNumber,
391 int rRequestedRNTupleSerializationMode,
392 const std::string &rRequestedRNTupleSoARecord,
393 const cling::Interpreter &interpreter,
398 fRequestStreamerInfo(rStreamerInfo),
399 fRequestNoStreamer(rNoStreamer),
400 fRequestNoInputOperator(rRequestNoInputOperator),
401 fRequestOnlyTClass(rRequestOnlyTClass),
402 fRequestedVersionNumber(rRequestVersionNumber),
403 fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode),
404 fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord)
414 "Could not remove the requested template arguments.\n");
424 const clang::Type *requestedType,
425 const clang::RecordDecl *decl,
426 const char *requestName,
429 bool rRequestNoInputOperator,
430 bool rRequestOnlyTClass,
431 int rRequestVersionNumber,
432 int rRequestedRNTupleSerializationMode,
433 const std::string &rRequestedRNTupleSoARecord,
434 const cling::Interpreter &interpreter,
439 fRequestStreamerInfo(rStreamerInfo),
440 fRequestNoStreamer(rNoStreamer),
441 fRequestNoInputOperator(rRequestNoInputOperator),
442 fRequestOnlyTClass(rRequestOnlyTClass),
443 fRequestedVersionNumber(rRequestVersionNumber),
444 fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode),
445 fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord)
461 const clang::RecordDecl *decl,
462 const char *requestName,
465 bool rRequestNoInputOperator,
466 bool rRequestOnlyTClass,
467 int rRequestVersionNumber,
468 int rRequestedRNTupleSerializationMode,
469 const std::string &rRequestedRNTupleSoARecord,
470 const cling::Interpreter &interpreter,
475 fRequestStreamerInfo(rStreamerInfo),
476 fRequestNoStreamer(rNoStreamer),
477 fRequestNoInputOperator(rRequestNoInputOperator),
478 fRequestOnlyTClass(rRequestOnlyTClass),
479 fRequestedVersionNumber(rRequestVersionNumber),
480 fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode),
481 fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord)
491 if (requestName && requestName[0]) {
505 ExistingTypeCheck_t existingTypeCheck, CheckInClassTable_t CheckInClassTable,
506 AutoParse_t autoParse,
bool *shuttingDownPtr,
const int *pgDebug )
507 : fInterpreter(&interpreter),
508 fNormalizedCtxt(&normCtxt),
509 fExistingTypeCheck(existingTypeCheck),
510 fCheckInClassTable(CheckInClassTable),
511 fAutoParse(autoParse),
512 fInterpreterIsShuttingDownPtr(shuttingDownPtr),
524 if (tname.empty())
return false;
545 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
546 clang::QualType t = lh.findType(nameLong, ToLHDS(
WantDiags()));
549 if (!
dest.isNull() && (
dest != t)) {
552 dest.getAsStringInternal(nameLong,
fInterpreter->getCI()->getASTContext().getPrintingPolicy());
560 const std::string &nameLong)
565 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
566 clang::QualType t = lh.findType(nondef.c_str(), ToLHDS(
WantDiags()));
569 if (!
dest.isNull() && (
dest != t) &&
570 nameLong == t.getAsString(
fInterpreter->getCI()->getASTContext().getPrintingPolicy()))
583 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
584 const clang::Decl *scope = lh.findScope(base.c_str(), ToLHDS(
WantDiags()),
nullptr);
591 const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(scope);
592 isInlined = nsdecl && nsdecl->isInline();
604 if (tname.empty())
return false;
624 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
625 clang::QualType t = lh.findType(tname.c_str(), ToLHDS(
WantDiags()));
636 clang::PrintingPolicy policy(
fInterpreter->getCI()->getASTContext().getPrintingPolicy());
637 policy.SuppressTagKeyword =
true;
638 policy.SuppressTagKeywordInAnonNames =
true;
643 policy.SuppressUnwrittenScope =
true;
650 if (strncmp(
result.c_str(),
"const ", 6) == 0) {
653 if (dropstd && strncmp(
result.c_str()+
offset,
"std::", 5) == 0) {
656 for(
unsigned int i = 1; i<
result.length(); ++i) {
659 if (dropstd &&
result.compare(i,5,
"std::",5) == 0) {
668 }
else if ( (i+1) <
result.length() &&
695 if (!
dest.isNull()) {
696 for (std::string_view kw : {
"class ",
"struct ",
"enum "}) {
697 if (tname.compare(0, kw.size(), kw) == 0) {
698 result = tname.substr(kw.size());
727 clang::QualType toSkip = lh.findType(
name, cling::LookupHelper::WithDiagnostics);
728 if (
const clang::Type* T = toSkip.getTypePtr()) {
729 const clang::TypedefType *
tt = llvm::dyn_cast<clang::TypedefType>(T);
731 clang::Decl* D =
tt->getDecl();
732 fConfig.m_toSkip.insert(D);
734 clang::QualType canon = toSkip->getCanonicalTypeInternal();
735 fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),T));
737 fTypeWithAlternative.insert(T);
750 keepTypedef(lh,
"Double32_t");
751 keepTypedef(lh,
"Float16_t");
752 keepTypedef(lh,
"Long64_t",
true);
753 keepTypedef(lh,
"ULong64_t",
true);
755 clang::QualType toSkip = lh.findType(
"string", cling::LookupHelper::WithDiagnostics);
756 if (!toSkip.isNull()) {
757 if (
const clang::TypedefType* TT
758 = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
759 fConfig.m_toSkip.insert(TT->getDecl());
761 toSkip = lh.findType(
"std::string", cling::LookupHelper::WithDiagnostics);
762 if (!toSkip.isNull()) {
763 if (
const clang::TypedefType* TT
764 = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
765 fConfig.m_toSkip.insert(TT->getDecl());
767 clang::QualType canon = toSkip->getCanonicalTypeInternal();
768 fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),toSkip.getTypePtr()));
779 return (cl.getKind() == clang::Decl::ClassTemplatePartialSpecialization
780 || cl.getKind() == clang::Decl::ClassTemplateSpecialization);
787 const cling::Interpreter& interp)
789 clang::Sema* S = &interp.getSema();
790 const clang::NamedDecl* ND = cling::utils::Lookup::Named(S,
name, cl);
791 if (ND == (clang::NamedDecl*)-1)
792 return (clang::FunctionDecl*)-1;
793 return llvm::dyn_cast_or_null<clang::FunctionDecl>(ND);
799const clang::CXXRecordDecl *
801 bool ,
const clang::Type** resultType)
803 const cling::LookupHelper& lh = interp.getLookupHelper();
806 const clang::CXXRecordDecl *
result
807 = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
808 (lh.findScope(
name, cling::LookupHelper::NoDiagnostics, resultType));
810 std::string std_name(
"std::");
814 result = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
815 (lh.findScope(std_name, cling::LookupHelper::NoDiagnostics, resultType));
825 clang::QualType qType = cl->getASTContext().getCanonicalTagType(cl);
833 clang::Sema& S = interp.getCI()->getSema();
836 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interp));
837 return S.RequireCompleteType(Loc, Type, clang::diag::err_incomplete_type);
843 const clang::CXXRecordDecl *context,
const cling::Interpreter &interp)
849 if (!cl->getDefinition() || !cl->isCompleteDefinition()) {
853 if (!CheckDefinition(cl, context) || !CheckDefinition(base, context)) {
857 if (!base->hasDefinition()) {
861 return cl->isDerivedFrom(base);
873 const clang::NamedDecl *base
877 return IsBase(CRD, llvm::dyn_cast<clang::CXXRecordDecl>( base ),
878 llvm::dyn_cast<clang::CXXRecordDecl>(
m.getDeclContext()),interp);
886 const clang::NamedDecl &forcontext,
887 const clang::QualType &qti,
888 const char *R__t,
int rwmode,
889 const cling::Interpreter &interp,
892 static const clang::CXXRecordDecl *TObject_decl
895 kBIT_ISTOBJECT = 0x10000000,
896 kBIT_HASSTREAMER = 0x20000000,
897 kBIT_ISSTRING = 0x40000000,
899 kBIT_ISPOINTER = 0x00001000,
900 kBIT_ISFUNDAMENTAL = 0x00000020,
901 kBIT_ISENUM = 0x00000008
904 const clang::Type &ti( * qti.getTypePtr() );
914 clang::CXXRecordDecl *cxxtype = rawtype->getAsCXXRecordDecl() ;
916 int isTObj = cxxtype && (
IsBase(cxxtype,TObject_decl,
nullptr,interp) || rawname ==
"TObject");
920 if (ti.isPointerType()) kase |= kBIT_ISPOINTER;
921 if (rawtype->isFundamentalType()) kase |= kBIT_ISFUNDAMENTAL;
922 if (rawtype->isEnumeralType()) kase |= kBIT_ISENUM;
925 if (isTObj) kase |= kBIT_ISTOBJECT;
926 if (isStre) kase |= kBIT_HASSTREAMER;
927 if (tiName ==
"string") kase |= kBIT_ISSTRING;
928 if (tiName ==
"string*") kase |= kBIT_ISSTRING;
932 tcl =
" internal error in rootcling ";
937 if (R__t) finalString <<
" " << tiName <<
" " << R__t <<
";" << std::endl;
940 case kBIT_ISFUNDAMENTAL:
942 finalString <<
" R__b >> " << R__t <<
";" << std::endl;
945 case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
947 finalString <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl;
956 finalString <<
" Int_t readtemp;" << std::endl
957 <<
" R__b >> readtemp;" << std::endl
958 <<
" " << R__t <<
" = static_cast<" << tiName <<
">(readtemp);" << std::endl;
961 case kBIT_HASSTREAMER:
962 case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
964 finalString <<
" " << R__t <<
".Streamer(R__b);" << std::endl;
967 case kBIT_HASSTREAMER|kBIT_ISPOINTER:
970 finalString <<
" if (R__b.GetInfo() && R__b.GetInfo()->GetOldVersion()<=3) {" << std::endl;
971 if (cxxtype && cxxtype->isAbstract()) {
972 finalString <<
" R__ASSERT(0);// " << objType <<
" is abstract. We assume that older file could not be produced using this streaming method." << std::endl;
974 finalString <<
" " << R__t <<
" = new " << objType <<
";" << std::endl
975 <<
" " << R__t <<
"->Streamer(R__b);" << std::endl;
977 finalString <<
" } else {" << std::endl
978 <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl
979 <<
" }" << std::endl;
984 finalString <<
" {TString R__str;" << std::endl
985 <<
" R__str.Streamer(R__b);" << std::endl
986 <<
" " << R__t <<
" = R__str.Data();}" << std::endl;
989 case kBIT_ISSTRING|kBIT_ISPOINTER:
991 finalString <<
" {TString R__str;" << std::endl
992 <<
" R__str.Streamer(R__b);" << std::endl
993 <<
" " << R__t <<
" = new string(R__str.Data());}" << std::endl;
998 finalString <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl;
1002 if (!R__t)
return 1;
1003 finalString <<
" R__b.StreamObject(&" << R__t <<
"," << tcl <<
");" << std::endl;
1011 case kBIT_ISFUNDAMENTAL:
1012 case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
1013 if (!R__t)
return 0;
1014 finalString <<
" R__b << " << R__t <<
";" << std::endl;
1018 if (!R__t)
return 0;
1019 finalString <<
" { void *ptr_enum = (void*)&" << R__t <<
";\n";
1020 finalString <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_enum); }" << std::endl;
1023 case kBIT_HASSTREAMER:
1024 case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
1025 if (!R__t)
return 0;
1026 finalString <<
" ((" << objType <<
"&)" << R__t <<
").Streamer(R__b);" << std::endl;
1029 case kBIT_HASSTREAMER|kBIT_ISPOINTER:
1030 if (!R__t)
return 1;
1031 finalString <<
" R__b.WriteObjectAny(" << R__t <<
"," << tcl <<
");" << std::endl;
1035 if (!R__t)
return 0;
1036 finalString <<
" {TString R__str(" << R__t <<
".c_str());" << std::endl
1037 <<
" R__str.Streamer(R__b);};" << std::endl;
1040 case kBIT_ISSTRING|kBIT_ISPOINTER:
1041 if (!R__t)
return 0;
1042 finalString <<
" {TString R__str(" << R__t <<
"->c_str());" << std::endl
1043 <<
" R__str.Streamer(R__b);}" << std::endl;
1046 case kBIT_ISPOINTER:
1047 if (!R__t)
return 1;
1048 finalString <<
" R__b.WriteObjectAny(" << R__t <<
"," << tcl <<
");" << std::endl;
1052 if (!R__t)
return 1;
1053 finalString <<
" R__b.StreamObject((" << objType <<
"*)&" << R__t <<
"," << tcl <<
");" << std::endl;
1065 clang::CXXRecordDecl* ncCl =
const_cast<clang::CXXRecordDecl*
>(cl);
1068 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
1070 if (
auto* Ctor = interpreter.getCI()->getSema().LookupDefaultConstructor(ncCl)) {
1071 if (Ctor->getAccess() == clang::AS_public && !Ctor->isDeleted()) {
1084 const char *typeOfArg,
1085 const clang::CXXRecordDecl *expectedArgType,
1086 const cling::Interpreter& interpreter)
1088 if (typeOfArg && !expectedArgType) {
1089 const cling::LookupHelper& lh = interpreter.getLookupHelper();
1092 clang::QualType instanceType = lh.findType(typeOfArg, cling::LookupHelper::WithDiagnostics);
1093 if (!instanceType.isNull())
1094 expectedArgType = instanceType->getAsCXXRecordDecl();
1097 if (!expectedArgType)
1098 return EIOCtorCategory::kAbsent;
1101 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
1102 for (
auto iter = cl->ctor_begin(), end = cl->ctor_end(); iter != end; ++iter)
1104 if ((iter->getAccess() != clang::AS_public) || (iter->getNumParams() != 1))
1108 clang::QualType argType((*iter->param_begin())->getType());
1109 argType = argType.getDesugaredType(cl->getASTContext());
1111 auto ioCtorCategory = EIOCtorCategory::kAbsent;
1112 if (argType->isPointerType()) {
1113 ioCtorCategory = EIOCtorCategory::kIOPtrType;
1114 argType = argType->getPointeeType();
1115 }
else if (argType->isReferenceType()) {
1116 ioCtorCategory = EIOCtorCategory::kIORefType;
1117 argType = argType.getNonReferenceType();
1121 argType = argType.getDesugaredType(cl->getASTContext());
1122 const clang::CXXRecordDecl *argDecl = argType->getAsCXXRecordDecl();
1124 if (argDecl->getCanonicalDecl() == expectedArgType->getCanonicalDecl()) {
1125 return ioCtorCategory;
1128 std::string realArg = argType.getAsString();
1129 std::string clarg(
"class ");
1131 if (realArg == clarg)
1132 return ioCtorCategory;
1136 return EIOCtorCategory::kAbsent;
1145 const cling::Interpreter& interpreter)
1147 const char *arg = ioctortype.
GetName();
1149 if (!ioctortype.
GetType() && (!arg || !arg[0])) {
1162 const char *method,
const char *proto,
1163 const cling::Interpreter &interp,
1166 const clang::FunctionDecl* funcD
1167 = interp.getLookupHelper().findFunctionProto(cinfo, method, proto,
1168 diagnose ? cling::LookupHelper::WithDiagnostics
1169 : cling::LookupHelper::NoDiagnostics);
1171 return llvm::dyn_cast<const clang::CXXMethodDecl>(funcD);
1180 namespace TMetaUtils {
1183 const cling::LookupHelper& lh = interp.getLookupHelper();
1186 clang::QualType instanceType = lh.findType(type_of_arg, cling::LookupHelper::WithDiagnostics);
1187 if (!instanceType.isNull())
1188 fArgType = instanceType->getAsCXXRecordDecl();
1202 const cling::Interpreter &interp)
1204 if (cl->isAbstract())
return false;
1206 for (
auto & ctorType : ctorTypes) {
1210 if (EIOCtorCategory::kAbsent == ioCtorCat)
1213 std::string proto( ctorType.GetName() );
1214 bool defaultCtor = proto.empty();
1220 if (EIOCtorCategory::kIOPtrType == ioCtorCat) {
1222 }
else if (EIOCtorCategory::kIORefType == ioCtorCat) {
1226 arg +=
")nullptr )";
1229 const clang::CXXMethodDecl *method
1231 cling::LookupHelper::NoDiagnostics);
1232 if (method && method->getAccess() != clang::AS_public) {
1246 const cling::Interpreter& interp)
1248 if (!cl)
return false;
1250 if (cl->hasUserDeclaredDestructor()) {
1252 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interp));
1253 clang::CXXDestructorDecl *
dest = cl->getDestructor();
1255 return (
dest->getAccess() == clang::AS_public);
1267 const char *methodname,
1269 const cling::Interpreter &interp,
1272 const clang::CXXMethodDecl *method
1274 diagnose ? cling::LookupHelper::WithDiagnostics
1275 : cling::LookupHelper::NoDiagnostics);
1276 return (method && method->getAccess() == clang::AS_public);
1287 const char *proto =
"TDirectory*";
1288 const char *
name =
"DirectoryAutoAdd";
1302 const char *proto =
"TCollection*,TFileMergeInfo*";
1303 const char *
name =
"Merge";
1316 const char *proto =
"TCollection*";
1317 const char *
name =
"Merge";
1332 const char *proto =
"TFileMergeInfo*";
1333 const char *
name =
"ResetAfterMerge";
1343 const clang::CXXRecordDecl* clxx,
1344 const cling::Interpreter &interp,
1347 static const char *proto =
"TBuffer&";
1349 const clang::CXXMethodDecl *method
1351 cling::LookupHelper::NoDiagnostics);
1352 const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1354 return (method && method->getDeclContext() == clxx_as_context
1362 const clang::CXXRecordDecl* clxx,
1363 const cling::Interpreter &interp,
1366 static const char *proto =
"TBuffer&,TClass*";
1368 const clang::CXXMethodDecl *method
1370 cling::LookupHelper::NoDiagnostics);
1371 const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1373 return (method && method->getDeclContext() == clxx_as_context
1403 clang::QualType qualType(&
type,0);
1435 llvm::raw_string_ostream stream(qual_name);
1436 clang::PrintingPolicy policy( cl.getASTContext().getPrintingPolicy() );
1437 policy.SuppressTagKeyword =
true;
1438 policy.SuppressTagKeywordInAnonNames =
true;
1439 policy.SuppressUnwrittenScope =
true;
1441 cl.getNameForDiagnostic(stream,policy,
true);
1444 if ( qual_name ==
"(anonymous " || qual_name ==
"(unnamed" ) {
1445 size_t pos = qual_name.find(
':');
1446 qual_name.erase(0,pos+2);
1462 clang::QualType qualType = recordDecl.getASTContext().getCanonicalTagType(&recordDecl);
1496 std::stringstream dims;
1497 std::string typenameStr;
1499 const clang::ASTContext& astContext = cl.getASTContext();
1502 for(clang::RecordDecl::field_iterator field_iter = cl.field_begin(), end = cl.field_end();
1510 typenameStr.clear();
1514 clang::QualType fieldType(field_iter->getType());
1515 if (fieldType->isConstantArrayType()) {
1516 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(fieldType.getTypePtr());
1518 dims <<
"[" << arrayType->getSize().getLimitedValue() <<
"]";
1519 fieldType = arrayType->getElementType();
1520 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1530 for(clang::CXXRecordDecl::base_class_const_iterator iter = cl.bases_begin(), end = cl.bases_end();
1533 std::string basename( iter->getType()->getAsCXXRecordDecl()->getNameAsString() );
1543 const cling::Interpreter &interp,
1546 return interp.getLookupHelper().findFunctionProto(cinfo, method, proto,
1547 diagnose ? cling::LookupHelper::WithDiagnostics
1548 : cling::LookupHelper::NoDiagnostics);
1582 clang::SourceLocation sourceLocation = decl->getLocation();
1583 clang::SourceManager& sourceManager = decl->getASTContext().getSourceManager();
1585 if (!sourceLocation.isValid() ) {
1589 if (!sourceLocation.isFileID()) {
1590 sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
1593 if (sourceLocation.isValid() && sourceLocation.isFileID()) {
1594 return sourceManager.getLineNumber(sourceManager.getFileID(sourceLocation),sourceManager.getFileOffset(sourceLocation));
1607 while (llvm::isa<clang::PointerType>(instanceType.getTypePtr())
1608 || llvm::isa<clang::ReferenceType>(instanceType.getTypePtr()))
1610 instanceType = instanceType->getPointeeType();
1623 const clang::CXXRecordDecl* clxx = instanceType->getAsCXXRecordDecl();
1624 if (clxx && clxx->getTemplateSpecializationKind() != clang::TSK_Undeclared) {
1626 const clang::TemplateSpecializationType* TST
1627 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
1634 for (
const clang::TemplateArgument &
TA : TST->template_arguments()) {
1635 if (
TA.getKind() == clang::TemplateArgument::Type) {
1647 const cling::Interpreter &interp,
1650 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1651 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return false;
1653 clang::QualType instanceType = interp.getLookupHelper().findType(cl.
GetNormalizedName(),
1654 cling::LookupHelper::WithDiagnostics);
1655 if (instanceType.isNull()) {
1668 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(attribute);
1673 attrString = annAttr->getAnnotation().str();
1682 size_t substrFound (attributeStr.find(propNames::separator));
1683 if (substrFound==std::string::npos) {
1687 size_t EndPart1 = attributeStr.find_first_of(propNames::separator) ;
1688 attrName = attributeStr.substr(0, EndPart1);
1689 const int separatorLength(propNames::separator.
size());
1690 attrValue = attributeStr.substr(EndPart1 + separatorLength);
1698 std::string attrString;
1700 if (0!=ret)
return ret;
1708 const std::string& propName,
1709 std::string& propValue)
1711 for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1712 attrIt!=decl.attr_end();++attrIt){
1713 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1714 if (!annAttr)
continue;
1716 llvm::StringRef attribute = annAttr->getAnnotation();
1717 std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1718 if (split.first != propName.c_str())
continue;
1720 propValue = split.second.str();
1731 const std::string& propName,
1734 for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1735 attrIt!=decl.attr_end();++attrIt){
1736 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1737 if (!annAttr)
continue;
1739 llvm::StringRef attribute = annAttr->getAnnotation();
1740 std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1741 if (split.first != propName.c_str())
continue;
1743 return split.second.getAsInteger(10,propValue);
1754 const clang::CXXRecordDecl *decl,
1755 const cling::Interpreter &interp,
1758 bool& needCollectionProxy)
1762 std::string mappedname;
1764 std::string csymbol = classname;
1772 csymbol.insert(0,
"::");
1778 bool isStd = TMetaUtils::IsStdClass(*decl);
1779 const cling::LookupHelper& lh = interp.getLookupHelper();
1780 bool isString = TMetaUtils::IsOfType(*decl,
"std::string",lh);
1782 bool isStdNotString = isStd && !isString;
1784 finalString <<
"namespace ROOT {" <<
"\n";
1788 finalString <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();\n"
1789 <<
" static void " << mappedname.c_str() <<
"_TClassManip(TClass*);\n";
1795 finalString <<
" static void *new_" << mappedname.c_str() <<
"(void *p = nullptr);" <<
"\n";
1799 finalString <<
" static void *newArray_";
1800 finalString << mappedname.c_str();
1801 finalString <<
"(Long_t size, void *p);";
1802 finalString <<
"\n";
1807 finalString <<
" static void delete_" << mappedname.c_str() <<
"(void *p);" <<
"\n" <<
" static void deleteArray_" << mappedname.c_str() <<
"(void *p);" <<
"\n" <<
" static void destruct_" << mappedname.c_str() <<
"(void *p);" <<
"\n";
1810 finalString <<
" static void directoryAutoAdd_" << mappedname.c_str() <<
"(void *obj, TDirectory *dir);" <<
"\n";
1813 finalString <<
" static void streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj);" <<
"\n";
1816 finalString <<
" static void conv_streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj, const TClass*);" <<
"\n";
1819 finalString <<
" static Long64_t merge_" << mappedname.c_str() <<
"(void *obj, TCollection *coll,TFileMergeInfo *info);" <<
"\n";
1822 finalString <<
" static void reset_" << mappedname.c_str() <<
"(void *obj, TFileMergeInfo *info);" <<
"\n";
1829 ROOT::SchemaRuleClassMap_t::iterator rulesIt1 =
ROOT::gReadRules.find( classname.c_str() );
1830 ROOT::SchemaRuleClassMap_t::iterator rulesIt2 =
ROOT::gReadRawRules.find( classname.c_str() );
1841 finalString <<
"\n // Schema evolution read functions\n";
1842 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt1->second.fRules.begin();
1843 while (rIt != rulesIt1->second.fRules.end()) {
1849 std::string error_string;
1851 Warning(
nullptr,
"%s", error_string.c_str());
1852 rIt = rulesIt1->second.fRules.erase(rIt);
1860 if( rIt->find(
"code" ) != rIt->end() ) {
1876 finalString <<
"\n // Schema evolution read raw functions\n";
1877 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt2->second.fRules.begin();
1878 while (rIt != rulesIt2->second.fRules.end()) {
1884 std::string error_string;
1886 Warning(
nullptr,
"%s", error_string.c_str());
1887 rIt = rulesIt2->second.fRules.erase(rIt);
1895 if( rIt->find(
"code" ) == rIt->end() )
1903 finalString <<
"\n" <<
" // Function generating the singleton type initializer" <<
"\n";
1905 finalString <<
" static TGenericClassInfo *GenerateInitInstanceLocal(const " << csymbol <<
"*)" <<
"\n" <<
" {" <<
"\n";
1907 finalString <<
" " << csymbol <<
" *ptr = nullptr;" <<
"\n";
1911 finalString <<
" static ::TVirtualIsAProxy* isa_proxy = new ::TInstrumentedIsAProxy< " << csymbol <<
" >(nullptr);" <<
"\n";
1914 finalString <<
" static ::TVirtualIsAProxy* isa_proxy = new ::TIsAProxy(typeid(" << csymbol <<
"));" <<
"\n";
1916 finalString <<
" static ::ROOT::TGenericClassInfo " <<
"\n" <<
" instance(\"" << classname.c_str() <<
"\", ";
1919 finalString << csymbol <<
"::Class_Version(), ";
1921 finalString <<
"2, ";
1923 finalString <<
"-2, ";
1929 static const char *versionFunc =
"GetClassVersion";
1933 std::string proto = classname +
"*";
1934 const clang::Decl* ctxt = llvm::dyn_cast<clang::Decl>((*cl).getDeclContext());
1935 const clang::FunctionDecl *methodinfo
1937 interp, cling::LookupHelper::NoDiagnostics);
1945 finalString <<
"GetClassVersion< ";
1946 finalString << classname.c_str();
1947 finalString <<
" >(), ";
1956 for (
unsigned int i=0; i<
filename.length(); i++) {
1961 <<
"," <<
"\n" <<
" typeid(" << csymbol
1962 <<
"), ::ROOT::Internal::DefineBehavior(ptr, ptr)," <<
"\n" <<
" ";
1965 finalString <<
"&" << csymbol <<
"::Dictionary, ";
1967 finalString <<
"&" << mappedname <<
"_Dictionary, ";
1971 TClassTable__kHasCustomStreamerMember = 0x10
1976 rootflag = rootflag | TClassTable__kHasCustomStreamerMember;
1978 finalString <<
"isa_proxy, " << rootflag <<
"," <<
"\n"
1979 <<
" sizeof(" << csymbol <<
"), alignof(" << csymbol <<
") );" <<
"\n";
1981 finalString <<
" instance.SetNew(&new_" << mappedname.c_str() <<
");" <<
"\n";
1983 finalString <<
" instance.SetNewArray(&newArray_" << mappedname.c_str() <<
");" <<
"\n";
1986 finalString <<
" instance.SetDelete(&delete_" << mappedname.c_str() <<
");" <<
"\n" <<
" instance.SetDeleteArray(&deleteArray_" << mappedname.c_str() <<
");" <<
"\n" <<
" instance.SetDestructor(&destruct_" << mappedname.c_str() <<
");" <<
"\n";
1989 finalString <<
" instance.SetDirectoryAutoAdd(&directoryAutoAdd_" << mappedname.c_str() <<
");" <<
"\n";
1993 finalString <<
" instance.SetStreamerFunc(&streamer_" << mappedname.c_str() <<
");" <<
"\n";
1997 finalString <<
" instance.SetConvStreamerFunc(&conv_streamer_" << mappedname.c_str() <<
");" <<
"\n";
2000 finalString <<
" instance.SetMerge(&merge_" << mappedname.c_str() <<
");" <<
"\n";
2003 finalString <<
" instance.SetResetAfterMerge(&reset_" << mappedname.c_str() <<
");" <<
"\n";
2006 finalString <<
" instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" <<
"Pushback" <<
"<Internal::TStdBitsetHelper< " << classname.c_str() <<
" > >()));" <<
"\n";
2008 needCollectionProxy =
true;
2009 }
else if (stl != 0 &&
2012 int idx = classname.find(
"<");
2014 const char* methodTCP =
nullptr;
2020 methodTCP=
"Pushback";
2023 methodTCP=
"Pushfront";
2029 methodTCP=
"MapInsert";
2042 finalString <<
" static_assert(alignof(" << csymbol <<
"::value_type) <= 4096,\n";
2043 finalString <<
" \"Class with alignment strictly greater than 4096 are currently not supported in "
2044 "CollectionProxy. \"\n";
2045 finalString <<
" \"Please report this case to the developers\");\n";
2046 finalString <<
" instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP <<
"< " << classNameForIO.c_str() <<
" >()));" <<
"\n";
2048 needCollectionProxy =
true;
2056 finalString <<
"\n" <<
" instance.AdoptAlternate(::ROOT::AddClassAlternate(\""
2063 finalString <<
"\n" <<
" instance.AdoptAlternate(::ROOT::AddClassAlternate(\""
2081 finalString <<
"\n" <<
" ::ROOT::Internal::TSchemaHelper* rule;" <<
"\n";
2085 finalString <<
"\n" <<
" // the io read rules" <<
"\n" <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrules(" << rulesIt1->second.size() <<
");" <<
"\n";
2087 finalString <<
" instance.SetReadRules( readrules );" <<
"\n";
2088 rulesIt1->second.fGenerated =
true;
2092 finalString <<
"\n" <<
" // the io read raw rules" <<
"\n" <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrawrules(" << rulesIt2->second.size() <<
");" <<
"\n";
2094 finalString <<
" instance.SetReadRawRules( readrawrules );" <<
"\n";
2095 rulesIt2->second.fGenerated =
true;
2098 finalString <<
" return &instance;" <<
"\n" <<
" }" <<
"\n";
2102 finalString <<
" TGenericClassInfo *GenerateInitInstance(const " << csymbol <<
"*)" <<
"\n" <<
" {\n return GenerateInitInstanceLocal(static_cast<" << csymbol <<
"*>(nullptr));\n }" <<
"\n";
2105 finalString <<
" // Static variable to force the class initialization" <<
"\n";
2109 finalString <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstanceLocal(static_cast<const " << csymbol <<
"*>(nullptr)); R__UseDummy(_R__UNIQUE_DICT_(Init));" <<
"\n";
2112 finalString <<
"\n" <<
" // Dictionary for non-ClassDef classes" <<
"\n"
2113 <<
" static TClass *" << mappedname <<
"_Dictionary() {\n"
2114 <<
" TClass* theClass ="
2115 <<
"::ROOT::GenerateInitInstanceLocal(static_cast<const " << csymbol <<
"*>(nullptr))->GetClass();\n"
2116 <<
" " << mappedname <<
"_TClassManip(theClass);\n";
2117 finalString <<
" return theClass;\n";
2118 finalString <<
" }\n\n";
2122 std::string manipString;
2123 std::string attribute_s;
2124 std::string attrName, attrValue;
2126 bool attrMapExtracted =
false;
2127 if (decl->hasAttrs()){
2129 for (clang::Decl::attr_iterator attrIt = decl->attr_begin();
2130 attrIt!=decl->attr_end();++attrIt){
2137 if (attrName ==
"name" ||
2138 attrName ==
"pattern" ||
2139 attrName ==
"rootmap")
continue;
2145 if (!attrMapExtracted){
2146 manipString+=
" theClass->CreateAttributeMap();\n";
2147 manipString+=
" TDictAttributeMap* attrMap( theClass->GetAttributeMap() );\n";
2148 attrMapExtracted=
true;
2150 manipString+=
" attrMap->AddProperty(\""+attrName +
"\",\""+attrValue+
"\");\n";
2156 for(clang::CXXRecordDecl::decl_iterator internalDeclIt = decl->decls_begin();
2157 internalDeclIt != decl->decls_end(); ++internalDeclIt){
2158 if (!(!(*internalDeclIt)->isImplicit()
2159 && (clang::isa<clang::FieldDecl>(*internalDeclIt) ||
2160 clang::isa<clang::VarDecl>(*internalDeclIt))))
continue;
2163 if (!internalDeclIt->hasAttrs())
continue;
2165 attrMapExtracted =
false;
2166 bool memberPtrCreated =
false;
2168 for (clang::Decl::attr_iterator attrIt = internalDeclIt->attr_begin();
2169 attrIt!=internalDeclIt->attr_end();++attrIt){
2177 clang::NamedDecl* namedInternalDecl = clang::dyn_cast<clang::NamedDecl> (*internalDeclIt);
2178 if (!namedInternalDecl) {
2179 TMetaUtils::Error(
nullptr,
"Cannot convert field declaration to clang::NamedDecl");
2182 const std::string memberName(namedInternalDecl->getName());
2183 const std::string cppMemberName =
"theMember_"+memberName;
2186 const std::string dataMemberCreation=
" TDataMember* "+cppMemberName+
" = theClass->GetDataMember(\""+memberName+
"\");\n";
2195 if (attrName == propNames::comment ||
2196 attrName == propNames::iotype ||
2197 attrName == propNames::ioname )
continue;
2199 if (!memberPtrCreated){
2200 manipString+=dataMemberCreation;
2201 memberPtrCreated=
true;
2204 if (!attrMapExtracted){
2205 manipString+=
" "+cppMemberName+
"->CreateAttributeMap();\n";
2206 manipString+=
" TDictAttributeMap* memberAttrMap_"+memberName+
"( theMember_"+memberName+
"->GetAttributeMap() );\n";
2207 attrMapExtracted=
true;
2210 manipString+=
" memberAttrMap_"+memberName+
"->AddProperty(\""+attrName +
"\",\""+attrValue+
"\");\n";
2217 finalString <<
" static void " << mappedname <<
"_TClassManip(TClass* " << (manipString.empty() ?
"":
"theClass") <<
"){\n"
2222 finalString <<
"} // end of namespace ROOT" <<
"\n" <<
"\n";
2226 std::vector<std::string> &standaloneTargets,
2227 const cling::Interpreter &interp)
2230 if (!rulesIt1.second.fGenerated) {
2231 const clang::Type *typeptr =
nullptr;
2232 const clang::CXXRecordDecl *
target =
2235 if (!
target && !rulesIt1.second.fTargetDecl) {
2236 auto &&nRules = rulesIt1.second.size();
2237 std::string rule{nRules > 1 ?
"rules" :
"rule"};
2238 std::string verb{nRules > 1 ?
"were" :
"was"};
2240 rulesIt1.first.c_str(), verb.c_str());
2250 std::string mappedname;
2253 finalString <<
"namespace ROOT {" <<
"\n";
2256 finalString <<
"\n // Schema evolution read functions\n";
2257 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt1.second.fRules.begin();
2258 while (rIt != rulesIt1.second.fRules.end()) {
2264 std::string error_string;
2267 rIt = rulesIt1.second.fRules.erase(rIt);
2275 if (rIt->find(
"code") != rIt->end()) {
2283 finalString <<
"} // namespace ROOT" <<
"\n";
2285 standaloneTargets.push_back(rulesIt1.first);
2286 rulesIt1.second.fGenerated =
true;
2292 const std::vector<std::string> &standaloneTargets)
2294 std::string functionname(
"RecordReadRules_");
2295 functionname += dictName;
2297 finalString <<
"namespace ROOT {" <<
"\n";
2298 finalString <<
" // Registration Schema evolution read functions\n";
2299 finalString <<
" int " << functionname <<
"() {" <<
"\n";
2300 if (!standaloneTargets.empty())
2302 <<
" ::ROOT::Internal::TSchemaHelper* rule;" <<
"\n";
2303 for (
const auto &
target : standaloneTargets) {
2308 finalString <<
" {\n";
2310 finalString <<
" // the io read rules for " <<
target <<
"\n";
2311 finalString <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrules(" << rulesIt1->second.size()
2314 finalString <<
" TClass::RegisterReadRules(TSchemaRule::kReadRule, \"" <<
name
2315 <<
"\", std::move(readrules));\n";
2316 rulesIt1->second.fGenerated =
true;
2320 finalString <<
"\n // the io read raw rules for " <<
target <<
"\n";
2321 finalString <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrawrules(" << rulesIt2->second.size()
2324 finalString <<
" TClass::RegisterReadRules(TSchemaRule::kReadRawRule, \"" <<
name
2325 <<
"\", std::move(readrawrules));\n";
2326 rulesIt2->second.fGenerated =
true;
2328 finalString <<
" }\n";
2330 finalString <<
" return 0;\n";
2331 finalString <<
" }\n";
2332 finalString <<
" static int _R__UNIQUE_DICT_(ReadRules_" << dictName <<
") = " << functionname <<
"();";
2333 finalString <<
"R__UseDummy(_R__UNIQUE_DICT_(ReadRules_" << dictName <<
"));" <<
"\n";
2334 finalString <<
"} // namespace ROOT" <<
"\n";
2344 std::string &clsname,
2345 std::string &nsname,
2346 const clang::CXXRecordDecl *cl)
2356 auto ctxt = cl->getEnclosingNamespaceContext();
2357 while(ctxt && ctxt!=cl && ctxt->isInlineNamespace()) {
2358 ctxt = ctxt->getParent();
2361 const clang::NamedDecl *namedCtxt = llvm::dyn_cast<clang::NamedDecl>(ctxt);
2362 if (namedCtxt && namedCtxt!=cl) {
2363 const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(namedCtxt);
2364 if (nsdecl && !nsdecl->isAnonymousNamespace()) {
2366 clsname.erase (0, nsname.size() + 2);
2378 const clang::DeclContext *ctxt = cl.getDeclContext();
2379 while(ctxt && !ctxt->isNamespace()) {
2380 ctxt = ctxt->getParent();
2394 int closing_brackets = 0;
2398 if (ctxt && ctxt->isNamespace()) {
2400 const clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(ctxt);
2406 out <<
"namespace " << ns->getNameAsString() <<
" {" << std::endl;
2411 return closing_brackets;
2425 clang::TemplateSpecializationKind kind = cl->getTemplateSpecializationKind();
2426 if (kind == clang::TSK_Undeclared ) {
2429 }
else if (kind == clang::TSK_ExplicitSpecialization) {
2443 const char *
name = which;
2444 const char *proto =
"size_t";
2445 const char *protoPlacement =
"size_t,void*";
2448 const clang::FunctionDecl *operatornew
2450 name, proto, interp,
2451 cling::LookupHelper::NoDiagnostics);
2452 const clang::FunctionDecl *operatornewPlacement
2454 name, protoPlacement, interp,
2455 cling::LookupHelper::NoDiagnostics);
2457 const clang::DeclContext *ctxtnew =
nullptr;
2458 const clang::DeclContext *ctxtnewPlacement =
nullptr;
2461 ctxtnew = operatornew->getParent();
2463 if (operatornewPlacement) {
2464 ctxtnewPlacement = operatornewPlacement->getParent();
2470 operatornewPlacement
2475 ctxtnew = operatornew->getParent();
2477 if (operatornewPlacement) {
2478 ctxtnewPlacement = operatornewPlacement->getParent();
2481 if (!ctxtnewPlacement) {
2489 if (ctxtnew == ctxtnewPlacement) {
2493 const clang::CXXRecordDecl* clnew = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnew);
2494 const clang::CXXRecordDecl* clnewPlacement = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnewPlacement);
2495 if (!clnew && !clnewPlacement) {
2501 if (clnew && !clnewPlacement) {
2505 if (!clnew && clnewPlacement) {
2510 if (clnew->isDerivedFrom(clnewPlacement)) {
2540 const clang::CXXRecordDecl *decl,
2541 const cling::Interpreter &interp,
2547 std::string mappedname;
2565 classname.insert(0,
"::");
2568 finalString <<
"namespace ROOT {" <<
"\n";
2573 finalString <<
" // Wrappers around operator new" <<
"\n";
2574 finalString <<
" static void *new_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" return p ? ";
2576 finalString <<
"new(p) ";
2577 finalString << classname.c_str();
2578 finalString << args;
2579 finalString <<
" : ";
2581 finalString <<
"::new(static_cast<::ROOT::Internal::TOperatorNewHelper*>(p)) ";
2582 finalString << classname.c_str();
2583 finalString << args;
2584 finalString <<
" : ";
2586 finalString <<
"new " << classname.c_str() << args <<
";" <<
"\n";
2587 finalString <<
" }" <<
"\n";
2591 finalString <<
" static void *newArray_";
2592 finalString << mappedname.c_str();
2593 finalString <<
"(Long_t nElements, void *p) {";
2594 finalString <<
"\n";
2595 finalString <<
" return p ? ";
2597 finalString <<
"new(p) ";
2598 finalString << classname.c_str();
2599 finalString <<
"[nElements] : ";
2601 finalString <<
"::new(static_cast<::ROOT::Internal::TOperatorNewHelper*>(p)) ";
2602 finalString << classname.c_str();
2603 finalString <<
"[nElements] : ";
2605 finalString <<
"new ";
2606 finalString << classname.c_str();
2607 finalString <<
"[nElements];";
2608 finalString <<
"\n";
2609 finalString <<
" }";
2610 finalString <<
"\n";
2615 finalString <<
" // Wrapper around operator delete" <<
"\n" <<
" static void delete_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" delete (static_cast<" << classname.c_str() <<
"*>(p));" <<
"\n" <<
" }" <<
"\n" <<
" static void deleteArray_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" delete [] (static_cast<" << classname.c_str() <<
"*>(p));" <<
"\n" <<
" }" <<
"\n" <<
" static void destruct_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" typedef " << classname.c_str() <<
" current_t;" <<
"\n" <<
" (static_cast<current_t*>(p))->~current_t();" <<
"\n" <<
" }" <<
"\n";
2619 finalString <<
" // Wrapper around the directory auto add." <<
"\n" <<
" static void directoryAutoAdd_" << mappedname.c_str() <<
"(void *p, TDirectory *dir) {" <<
"\n" <<
" ((" << classname.c_str() <<
"*)p)->DirectoryAutoAdd(dir);" <<
"\n" <<
" }" <<
"\n";
2623 finalString <<
" // Wrapper around a custom streamer member function." <<
"\n" <<
" static void streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj) {" <<
"\n" <<
" ((" << classname.c_str() <<
"*)obj)->" << classname.c_str() <<
"::Streamer(buf);" <<
"\n" <<
" }" <<
"\n";
2627 finalString <<
" // Wrapper around a custom streamer member function." <<
"\n" <<
" static void conv_streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj, const TClass *onfile_class) {" <<
"\n" <<
" ((" << classname.c_str() <<
"*)obj)->" << classname.c_str() <<
"::Streamer(buf,onfile_class);" <<
"\n" <<
" }" <<
"\n";
2631 finalString <<
" // Wrapper around the merge function." <<
"\n" <<
" static Long64_t merge_" << mappedname.c_str() <<
"(void *obj,TCollection *coll,TFileMergeInfo *info) {" <<
"\n" <<
" return ((" << classname.c_str() <<
"*)obj)->Merge(coll,info);" <<
"\n" <<
" }" <<
"\n";
2633 finalString <<
" // Wrapper around the merge function." <<
"\n" <<
" static Long64_t merge_" << mappedname.c_str() <<
"(void *obj,TCollection *coll,TFileMergeInfo *) {" <<
"\n" <<
" return ((" << classname.c_str() <<
"*)obj)->Merge(coll);" <<
"\n" <<
" }" <<
"\n";
2637 finalString <<
" // Wrapper around the Reset function." <<
"\n" <<
" static void reset_" << mappedname.c_str() <<
"(void *obj,TFileMergeInfo *info) {" <<
"\n" <<
" ((" << classname.c_str() <<
"*)obj)->ResetAfterMerge(info);" <<
"\n" <<
" }" <<
"\n";
2639 finalString <<
"} // end of namespace ROOT for class " << classname.c_str() <<
"\n" <<
"\n";
2646 const cling::Interpreter &interp,
2653 if (version == 0)
return;
2657 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
2661 for(clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
2667 Internal::RStl::Instance().GenerateTClassFor( iter->getType(), interp, normCtxt);
2672 for(clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
2676 std::string mTypename;
2682 if (!strcmp(shortTypeName,
"string")) {
2694 Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
2704 const clang::Type *rawtype =
m.getType()->getCanonicalTypeInternal().getTypePtr();
2705 if (rawtype->isArrayType()) {
2706 rawtype = rawtype->getBaseElementTypeUnsafe ();
2720 const clang::CXXRecordDecl* CRD = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
2729 if (!funcCV)
return -1;
2732 if (funcCV == (clang::FunctionDecl*)-1)
return 1;
2747 using res_t = std::pair<bool, int>;
2749 const clang::CompoundStmt* FuncBody
2750 = llvm::dyn_cast_or_null<clang::CompoundStmt>(funcCV->getBody());
2752 return res_t{
false, -1};
2753 if (FuncBody->size() != 1) {
2757 return res_t{
false, -1};
2759 const clang::ReturnStmt* RetStmt
2760 = llvm::dyn_cast<clang::ReturnStmt>(FuncBody->body_back());
2762 return res_t{
false, -1};
2763 const clang::Expr* RetExpr = RetStmt->getRetValue();
2769 if (
auto RetRes = RetExpr->getIntegerConstantExpr(funcCV->getASTContext())) {
2770 if (RetRes->isSigned())
2771 return res_t{
true, (
Version_t)RetRes->getSExtValue()};
2772 return res_t{
true, (
Version_t)RetRes->getZExtValue()};
2774 return res_t{
false, -1};
2790 clang::QualType
type =
m.getType();
2793 if (decl)
return TMetaUtils::IsSTLCont(*decl);
2802 clang::QualType
type = base.getType();
2805 if (decl)
return TMetaUtils::IsSTLCont(*decl);
2815 const std::function<
void(
const clang::Module::Header &)> &closure,
2816 bool includeDirectlyUsedModules)
2823 llvm::SetVector<const clang::Module *> modules;
2824 modules.insert(&module);
2825 for (
size_t i = 0; i < modules.size(); ++i) {
2826 const clang::Module *M = modules[i];
2827 for (
const clang::Module *subModule : M->submodules())
2828 modules.insert(subModule);
2831 for (
const clang::Module *
m : modules) {
2832 if (includeDirectlyUsedModules) {
2833 for (clang::Module *used :
m->DirectUses) {
2839 for (
auto HK : {clang::Module::HK_Normal, clang::Module::HK_Textual, clang::Module::HK_Private,
2840 clang::Module::HK_PrivateTextual}) {
2841 const auto &headerList =
m->getHeaders(HK);
2842 for (
const clang::Module::Header &moduleHeader : headerList) {
2843 closure(moduleHeader);
2857 static char t[4096];
2858 static const char* constwd =
"const ";
2859 static const char* constwdend =
"const";
2864 for (s=typeDesc;*s;s++) {
2867 if (lev==0 && *s==
'*')
continue;
2868 if (lev==0 && (strncmp(constwd,s,strlen(constwd))==0
2869 ||strcmp(constwdend,s)==0 ) ) {
2870 s+=strlen(constwd)-1;
2873 if (lev==0 && *s==
' ' && *(s+1)!=
'*') {
p = t;
continue;}
2874 if (
p - t > (
long)
sizeof(t)) {
2875 printf(
"ERROR (rootcling): type name too long for StortTypeName: %s\n",
2888 const cling::Interpreter& interp)
2893 if (!comment.empty() && comment[0] ==
'!')
2896 clang::QualType
type =
m.getType();
2898 if (
type->isReferenceType()) {
2903 std::string mTypeName =
type.getAsString(
m.getASTContext().getPrintingPolicy());
2904 if (!strcmp(mTypeName.c_str(),
"string") || !strcmp(mTypeName.c_str(),
"string*")) {
2907 if (!strcmp(mTypeName.c_str(),
"std::string") || !strcmp(mTypeName.c_str(),
"std::string*")) {
2915 const clang::Type *rawtype =
type.getTypePtr()->getBaseElementTypeUnsafe ();
2917 if (rawtype->isPointerType()) {
2919 clang::QualType pointee;
2920 while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
2922 rawtype = pointee.getTypePtr();
2926 if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2931 const clang::CXXRecordDecl *cxxdecl = rawtype->getAsCXXRecordDecl();
2935 if (version > 0)
return true;
2948 const clang::Type *rawtype =
m.getType().getTypePtr();
2951 clang::QualType pointee;
2952 while ( rawtype->isPointerType() && ((pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull()) && pointee.getTypePtr() != rawtype)
2954 rawtype = pointee.getTypePtr();
2968 if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2972 return rawtype->getAsCXXRecordDecl();
2981 const cling::Interpreter &interp,
2983 std::ostream& dictStream,
2985 bool isGenreflex=
false)
2987 const clang::CXXRecordDecl* decl = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
2989 if (!decl || !decl->isCompleteDefinition()) {
2993 std::string fullname;
2996 Internal::RStl::Instance().GenerateTClassFor(cl.
GetNormalizedName(), llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl()), interp, normCtxt);
3005 (*WriteStreamerFunc)(cl, interp, normCtxt, dictStream, isGenreflex || cl.RequestStreamerInfo());
3007 ROOT::TMetaUtils::Info(
nullptr,
"Class %s: Do not generate Streamer() [*** custom streamer ***]\n",fullname.c_str());
3029 const cling::Interpreter &interpreter,
3032 const clang::ASTContext& Ctx = interpreter.getCI()->getASTContext();
3034 clang::QualType originalType = instanceType;
3038 if (llvm::isa<clang::PointerType>(instanceType.getTypePtr())) {
3040 clang::Qualifiers quals = instanceType.getQualifiers();
3041 clang::QualType newPointee =
AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
3042 if (newPointee != instanceType->getPointeeType()) {
3043 instanceType = Ctx.getPointerType(newPointee);
3045 instanceType = Ctx.getQualifiedType(instanceType, quals);
3047 return instanceType;
3052 if (llvm::isa<clang::ReferenceType>(instanceType.getTypePtr())) {
3054 bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(instanceType.getTypePtr());
3055 clang::Qualifiers quals = instanceType.getQualifiers();
3056 clang::QualType newPointee =
AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
3058 if (newPointee != instanceType->getPointeeType()) {
3061 instanceType = Ctx.getLValueReferenceType(newPointee);
3063 instanceType = Ctx.getRValueReferenceType(newPointee);
3065 instanceType = Ctx.getQualifiedType(instanceType, quals);
3067 return instanceType;
3071 bool prefix_changed =
false;
3072 clang::NestedNameSpecifier prefix = std::nullopt;
3073 clang::Qualifiers prefix_qualifiers = instanceType.getLocalQualifiers();
3074 clang::NestedNameSpecifier desugaredPrefix = instanceType->getPrefix();
3075 if (desugaredPrefix) {
3077 prefix = AddDefaultParametersNNS(Ctx, desugaredPrefix, interpreter, normCtxt);
3078 prefix_changed = prefix != desugaredPrefix;
3086 const clang::TemplateSpecializationType* TST
3087 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
3089 const clang::ClassTemplateSpecializationDecl* TSTdecl
3090 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instanceType.getTypePtr()->getAsCXXRecordDecl());
3102 bool mightHaveChanged =
false;
3103 if (TST && TSTdecl) {
3105 clang::Sema& S = interpreter.getCI()->getSema();
3106 clang::TemplateDecl *Template = TSTdecl->getSpecializedTemplate()->getMostRecentDecl();
3107 clang::TemplateParameterList *Params = Template->getTemplateParameters();
3108 clang::TemplateParameterList::iterator Param = Params->
begin();
3112 unsigned int dropDefault = normCtxt.
GetConfig().DropDefaultArg(*Template);
3114 llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
3115 llvm::SmallVector<clang::TemplateArgument, 4> canonArgs;
3116 llvm::ArrayRef<clang::TemplateArgument> template_arguments = TST->template_arguments();
3117 unsigned int Idecl = 0, Edecl = TSTdecl->getTemplateArgs().size();
3120 if (template_arguments.size() > Edecl) {
3121 Edecl = template_arguments.size();
3123 unsigned int maxAddArg = Edecl - dropDefault;
3124 for (
const clang::TemplateArgument *I = template_arguments.begin(), *E = template_arguments.end(); Idecl != Edecl;
3125 I != E ? ++I :
nullptr, ++Idecl, ++Param) {
3129 if (I->getKind() == clang::TemplateArgument::Template) {
3130 clang::TemplateName templateName = I->getAsTemplate();
3131 clang::TemplateDecl* templateDecl = templateName.getAsTemplateDecl();
3133 clang::DeclContext* declCtxt = templateDecl->getDeclContext();
3135 if (declCtxt && !templateName.getAsQualifiedTemplateName()){
3136 clang::NamespaceDecl* ns = clang::dyn_cast<clang::NamespaceDecl>(declCtxt);
3137 clang::NestedNameSpecifier nns;
3139 nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx, ns);
3140 }
else if (clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(declCtxt)) {
3141 nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx,TD,
false );
3144 desArgs.push_back(*I);
3147 clang::TemplateName UnderlyingTN(templateDecl);
3148 if (clang::UsingShadowDecl *USD = templateName.getAsUsingShadowDecl())
3149 UnderlyingTN = clang::TemplateName(USD);
3150 clang::TemplateName templateNameWithNSS ( Ctx.getQualifiedTemplateName(nns,
false, UnderlyingTN) );
3151 desArgs.push_back(clang::TemplateArgument(templateNameWithNSS));
3152 mightHaveChanged =
true;
3158 if (I->getKind() != clang::TemplateArgument::Type) {
3159 desArgs.push_back(*I);
3163 clang::QualType SubTy = I->getAsType();
3172 if (SubTy != newSubTy) {
3173 mightHaveChanged =
true;
3174 desArgs.push_back(clang::TemplateArgument(newSubTy));
3176 desArgs.push_back(*I);
3179 }
else if (!isStdDropDefault && Idecl < maxAddArg) {
3181 mightHaveChanged =
true;
3183 const clang::TemplateArgument& templateArg
3184 = TSTdecl->getTemplateArgs().get(Idecl);
3185 if (templateArg.getKind() != clang::TemplateArgument::Type) {
3186 desArgs.push_back(templateArg);
3189 clang::QualType SubTy = templateArg.getAsType();
3191 clang::SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3192 clang::SourceLocation RAngleLoc = TSTdecl->getSourceRange().getBegin();
3194 clang::TemplateTypeParmDecl *TTP = llvm::dyn_cast<clang::TemplateTypeParmDecl>(*Param);
3197 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
3198 bool HasDefaultArgs;
3199 clang::TemplateArgumentLoc ArgType = S.SubstDefaultTemplateArgumentIfAvailable(
3201 clang::SourceLocation(),
3210 if (ArgType.getArgument().isNull()
3211 || ArgType.getArgument().getKind() != clang::TemplateArgument::Type) {
3213 "Template parameter substitution failed for %s around %s\n",
3214 instanceType.getAsString().c_str(), SubTy.getAsString().c_str());
3217 clang::QualType BetterSubTy = ArgType.getArgument().getAsType();
3218 SubTy = cling::utils::Transform::GetPartiallyDesugaredType(Ctx,BetterSubTy,normCtxt.
GetConfig(),
true);
3221 desArgs.push_back(clang::TemplateArgument(SubTy));
3230 if (mightHaveChanged) {
3231 instanceType = Ctx.getTemplateSpecializationType(TST->getKeyword(),
3232 TST->getTemplateName(),
3235 TST->getCanonicalTypeInternal());
3239 if (!prefix_changed && !mightHaveChanged)
return originalType;
3243 instanceType = cling::utils::TypeName::QualifyTypeUnderPrefix(Ctx, instanceType, prefix);
3244 instanceType = Ctx.getQualifiedType(instanceType,prefix_qualifiers);
3246 return instanceType;
3266 llvm::StringRef title;
3269 if (clang::AnnotateAttr *A =
m.getAttr<clang::AnnotateAttr>())
3270 title = A->getAnnotation();
3282 if (errnum) *errnum =
VALID;
3284 if (title.size() == 0 || (title[0] !=
'['))
return llvm::StringRef();
3285 size_t rightbracket = title.find(
']');
3286 if (rightbracket == llvm::StringRef::npos)
return llvm::StringRef();
3288 std::string working;
3289 llvm::StringRef indexvar(title.data()+1,rightbracket-1);
3296 size_t indexvarlen = indexvar.size();
3297 for ( i=0; i<indexvarlen; i++) {
3298 if (!isspace(indexvar[i])) {
3299 working += indexvar[i];
3304 const char *tokenlist =
"*+-";
3305 char *current =
const_cast<char*
>(working.c_str());
3306 current = strtok(current,tokenlist);
3310 if (isdigit(current[0])) {
3311 for(i=0;i<strlen(current);i++) {
3312 if (!isdigit(current[i])) {
3317 if (errstr) *errstr = current;
3318 if (errnum) *errnum =
NOT_INT;
3319 return llvm::StringRef();
3324 const clang::CXXRecordDecl *parent_clxx = llvm::dyn_cast<clang::CXXRecordDecl>(
m.getDeclContext());
3325 const clang::FieldDecl *index1 =
nullptr;
3327 index1 = GetDataMemberFromAll(*parent_clxx, current );
3329 if ( IsFieldDeclInt(index1) ) {
3334 for(clang::RecordDecl::field_iterator field_iter = parent_clxx->field_begin(), end = parent_clxx->field_end();
3338 if ( field_iter->getNameAsString() ==
m.getNameAsString() ) {
3344 if (errstr) *errstr = current;
3345 if (errnum) *errnum =
NOT_DEF;
3346 return llvm::StringRef();
3348 if ( field_iter->getNameAsString() == index1->getNameAsString() ) {
3356 if (errstr) *errstr = current;
3357 if (errnum) *errnum =
NOT_INT;
3358 return llvm::StringRef();
3365 clang::Sema& SemaR =
const_cast<cling::Interpreter&
>(interp).getSema();
3366 index1 = GetDataMemberFromAllParents(SemaR, *parent_clxx, current);
3369 if ( IsFieldDeclInt(index1) ) {
3376 if (errnum) *errnum =
NOT_INT;
3377 if (errstr) *errstr = current;
3381 if (errnum) *errnum =
NOT_INT;
3382 if (errstr) *errstr = current;
3383 return llvm::StringRef();
3385 if ( found && (index1->getAccess() == clang::AS_private) ) {
3388 if (errstr) *errstr = current;
3390 return llvm::StringRef();
3397 if (errstr) *errstr = indexvar;
3398 if (errnum) *errnum =
UNKNOWN;
3399 return llvm::StringRef();
3404 current = strtok(
nullptr, tokenlist);
3420 while((
c = in[i++])) {
3421 const char *repl =
nullptr;
3423 case '+': repl =
"pL";
break;
3424 case '-': repl =
"mI";
break;
3425 case '*': repl =
"mU";
break;
3426 case '/': repl =
"dI";
break;
3427 case '&': repl =
"aN";
break;
3428 case '%': repl =
"pE";
break;
3429 case '|': repl =
"oR";
break;
3430 case '^': repl =
"hA";
break;
3431 case '>': repl =
"gR";
break;
3432 case '<': repl =
"lE";
break;
3433 case '=': repl =
"eQ";
break;
3434 case '~': repl =
"wA";
break;
3435 case '.': repl =
"dO";
break;
3436 case '(': repl =
"oP";
break;
3437 case ')': repl =
"cP";
break;
3438 case '[': repl =
"oB";
break;
3439 case ']': repl =
"cB";
break;
3440 case '{': repl =
"lB";
break;
3441 case '}': repl =
"rB";
break;
3442 case ';': repl =
"sC";
break;
3443 case '#': repl =
"hS";
break;
3444 case '?': repl =
"qM";
break;
3445 case '`': repl =
"bT";
break;
3446 case '!': repl =
"nO";
break;
3447 case ',': repl =
"cO";
break;
3448 case '$': repl =
"dA";
break;
3449 case ' ': repl =
"sP";
break;
3450 case ':': repl =
"cL";
break;
3451 case '"': repl =
"dQ";
break;
3452 case '@': repl =
"aT";
break;
3453 case '\'': repl =
"sQ";
break;
3454 case '\\': repl =
"fI";
break;
3463 if (out.empty() || isdigit(out[0]))
3464 out.insert(out.begin(),
'_');
3467static clang::SourceLocation
3469 clang::SourceLocation sourceLoc) {
3471 if (!sourceLoc.isFileID()) {
3472 return sourceManager.getExpansionRange(sourceLoc).getEnd();
3481 const cling::Interpreter& interp)
3511 using namespace clang;
3512 SourceLocation headerLoc = decl.getLocation();
3514 static const char invalidFilename[] =
"";
3515 if (!headerLoc.isValid())
return invalidFilename;
3517 HeaderSearch& HdrSearch = interp.getCI()->getPreprocessor().getHeaderSearchInfo();
3519 SourceManager& sourceManager = decl.getASTContext().getSourceManager();
3521 FileID headerFID = sourceManager.getFileID(headerLoc);
3522 SourceLocation includeLoc
3524 sourceManager.getIncludeLoc(headerFID));
3526 OptionalFileEntryRef headerFE = sourceManager.getFileEntryRefForID(headerFID);
3527 while (includeLoc.isValid() && sourceManager.isInSystemHeader(includeLoc)) {
3528 ConstSearchDirIterator *foundDir =
nullptr;
3531 assert(headerFE &&
"Couldn't find FileEntry from FID!");
3533 = HdrSearch.LookupFile(llvm::sys::path::filename(headerFE->getName()),
3535 true ,
nullptr, foundDir,
3536 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>>(),
3544 headerFID = sourceManager.getFileID(includeLoc);
3545 headerFE = sourceManager.getFileEntryRefForID(headerFID);
3550 if (interp.getCI()->getLangOpts().Modules && !headerFE) {
3551 assert(decl.isFirstDecl() &&
"Couldn't trace back include from a decl"
3552 " that is not from an AST file");
3553 assert(StringRef(includeLoc.printToString(sourceManager)).starts_with(
"<module-includes>"));
3557 sourceManager.getIncludeLoc(headerFID));
3560 if (!headerFE)
return invalidFilename;
3562 llvm::SmallString<256> headerFileName(headerFE->getName());
3565 llvm::sys::path::remove_dots(headerFileName,
true);
3576 bool isAbsolute = llvm::sys::path::is_absolute(headerFileName);
3577 clang::OptionalFileEntryRef FELong;
3579 for (llvm::sys::path::const_iterator
3580 IDir = llvm::sys::path::begin(headerFileName),
3581 EDir = llvm::sys::path::end(headerFileName);
3582 !FELong && IDir != EDir; ++IDir) {
3588 size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3589 llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3590 assert(trailingPart.data() + trailingPart.size()
3591 == headerFileName.data() + headerFileName.size()
3592 &&
"Mismatched partitioning of file name!");
3593 ConstSearchDirIterator* FoundDir =
nullptr;
3594 FELong = HdrSearch.LookupFile(trailingPart, SourceLocation(),
3595 true ,
nullptr, FoundDir,
3596 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>>(),
3604 return invalidFilename;
3608 for (llvm::sys::path::reverse_iterator
3609 IDir = llvm::sys::path::rbegin(headerFileName),
3610 EDir = llvm::sys::path::rend(headerFileName);
3611 IDir != EDir; ++IDir) {
3612 size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3613 llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3614 assert(trailingPart.data() + trailingPart.size()
3615 == headerFileName.data() + headerFileName.size()
3616 &&
"Mismatched partitioning of file name!");
3617 ConstSearchDirIterator* FoundDir =
nullptr;
3620 if (HdrSearch.LookupFile(trailingPart, SourceLocation(),
3621 true ,
nullptr, FoundDir,
3622 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>>(),
3625 nullptr,
nullptr ) == FELong) {
3626 return trailingPart.str();
3630 return invalidFilename;
3636 const clang::QualType &qtype,
3637 const clang::ASTContext &astContext)
3639 std::string fqname = cling::utils::TypeName::GetFullyQualifiedName(qtype, astContext);
3648 const clang::QualType &qtype,
3649 const cling::Interpreter &interpreter)
3654 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interpreter));
3658 interpreter.getCI()->getASTContext());
3666 clang::ClassTemplateDecl*& ctd,
3667 clang::ClassTemplateSpecializationDecl*& ctsd)
3669 using namespace clang;
3670 const Type* theType = qt.getTypePtr();
3677 if (theType->isPointerType()) {
3681 if (
const RecordType* rType = llvm::dyn_cast<RecordType>(theType)) {
3682 ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(rType->getDecl());
3684 ctd = ctsd->getSpecializedTemplate();
3689 if (
const SubstTemplateTypeParmType* sttpType = llvm::dyn_cast<SubstTemplateTypeParmType>(theType)){
3694 ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(qt->getAsCXXRecordDecl());
3696 ctd = ctsd->getSpecializedTemplate();
3711 using namespace clang;
3712 ClassTemplateSpecializationDecl* ctsd;
3713 ClassTemplateDecl* ctd;
3727 using namespace clang;
3729 const Type* theType = qt.getTypePtr();
3731 if (
const TemplateSpecializationType* tst = llvm::dyn_cast_or_null<const TemplateSpecializationType>(theType)) {
3732 theTemplateName = tst->getTemplateName();
3733 theKeyword = tst->getKeyword();
3736 theTemplateName = TemplateName(ctd);
3743 llvm::SmallVectorImpl<clang::TemplateArgument>& preceedingTArgs,
3744 const clang::NamedDecl& tPar,
3745 const cling::Interpreter& interp,
3749 using namespace clang;
3752 TemplateTypeParmDecl* ttpdPtr =
const_cast<TemplateTypeParmDecl*
>(llvm::dyn_cast<TemplateTypeParmDecl>(&tPar));
3753 if (!ttpdPtr)
return false;
3754 if (!ttpdPtr->hasDefaultArgument())
return false;
3757 QualType tParQualType = ttpdPtr->getDefaultArgument().getArgument().getAsType();
3758 const QualType tArgQualType = tArg.getAsType();
3765 if (tParQualType.getTypePtr() == tArgQualType.getTypePtr())
return true;
3776 const TemplateSpecializationType* tst =
3777 llvm::dyn_cast<TemplateSpecializationType>(tParQualType.getTypePtr());
3782 ClassTemplateSpecializationDecl* TSTdecl
3783 = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(tArgQualType->getAsCXXRecordDecl());
3788 TemplateDecl *Template = tst->getTemplateName().getAsTemplateDecl();
3791 SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3794 SourceLocation LAngleLoc = TSTdecl->getSourceRange().getBegin();
3799 TemplateArgument newArg = tArg;
3801 clang::Sema& S = interp.getCI()->getSema();
3802 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interp));
3803 llvm::SmallVector<clang::TemplateArgument, 4> canonArgs;
3804 bool HasDefaultArgs;
3805 TemplateArgumentLoc defTArgLoc = S.SubstDefaultTemplateArgumentIfAvailable(Template,
3806 clang::SourceLocation(),
3815 newArg = defTArgLoc.getArgument();
3816 if (newArg.isNull() ||
3817 newArg.getKind() != clang::TemplateArgument::Type) {
3819 "Template parameter substitution failed!");
3822 ClassTemplateSpecializationDecl* nTSTdecl
3823 = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(newArg.getAsType()->getAsCXXRecordDecl());
3826 isEqual = (nTSTdecl && nTSTdecl->getMostRecentDecl() == TSTdecl->getMostRecentDecl()) ||
3827 (tParQualType.getTypePtr() == newArg.getAsType().getTypePtr());
3839 const clang::NamedDecl& tPar)
3841 using namespace clang;
3842 const NonTypeTemplateParmDecl* nttpdPtr = llvm::dyn_cast<NonTypeTemplateParmDecl>(&tPar);
3843 if (!nttpdPtr)
return false;
3844 const NonTypeTemplateParmDecl& nttpd = *nttpdPtr;
3846 if (!nttpd.hasDefaultArgument())
3850 llvm::APSInt defaultValueAPSInt(64,
false);
3851 if (Expr* defArgExpr = nttpd.getDefaultArgument().getArgument().getAsExpr()) {
3852 const ASTContext& astCtxt = nttpdPtr->getASTContext();
3853 if (
auto Value = defArgExpr->getIntegerConstantExpr(astCtxt))
3854 defaultValueAPSInt = *Value;
3857 const int value = tArg.getAsIntegral().getLimitedValue();
3860 return value == defaultValueAPSInt;
3870 using namespace clang;
3871 if (!nDecl)
return false;
3872 if (
const TemplateTypeParmDecl* ttpd = llvm::dyn_cast<TemplateTypeParmDecl>(nDecl))
3873 return ttpd->hasDefaultArgument();
3874 if (
const NonTypeTemplateParmDecl* nttpd = llvm::dyn_cast<NonTypeTemplateParmDecl>(nDecl))
3875 return nttpd->hasDefaultArgument();
3880static void KeepNParams(clang::QualType& normalizedType,
3881 const clang::QualType& vanillaType,
3882 const cling::Interpreter& interp,
3887 const clang::TemplateArgument &tArg,
3888 const cling::Interpreter& interp,
3890 const clang::ASTContext& astCtxt)
3893 using namespace clang;
3900 if (tArg.getKind() == clang::TemplateArgument::Type) {
3901 QualType thisNormQualType = normTArg.getAsType();
3902 QualType thisArgQualType = tArg.getAsType();
3907 normTArg = TemplateArgument(thisNormQualType);
3908 return (thisNormQualType != thisArgQualType);
3909 }
else if (normTArg.getKind() == clang::TemplateArgument::Pack) {
3910 assert( tArg.getKind() == clang::TemplateArgument::Pack );
3912 SmallVector<TemplateArgument, 2> desArgs;
3913 bool mightHaveChanged =
true;
3914 for (
auto I = normTArg.pack_begin(), E = normTArg.pack_end(),
3915 FI = tArg.pack_begin(), FE = tArg.pack_end();
3916 I != E && FI != FE; ++I, ++FI)
3918 TemplateArgument pack_arg(*I);
3920 desArgs.push_back(pack_arg);
3922 if (mightHaveChanged) {
3923 ASTContext &mutableCtx(
const_cast<ASTContext&
>(astCtxt) );
3924 normTArg = TemplateArgument::CreatePackCopy(mutableCtx, desArgs);
3926 return mightHaveChanged;
3937 const clang::QualType& vanillaType,
3938 const cling::Interpreter& interp,
3942 using namespace clang;
3946 ClassTemplateSpecializationDecl* ctsd;
3947 ClassTemplateDecl* ctd;
3948 if (! QualType2Template(vanillaType, ctd, ctsd)) return ;
3954 QualType originalNormalizedType = normalizedType;
3956 const ASTContext& astCtxt = ctsd->getASTContext();
3961 if (llvm::isa<clang::PointerType>(normalizedType.getTypePtr())) {
3963 clang::Qualifiers quals = normalizedType.getQualifiers();
3964 auto valNormalizedType = normalizedType->getPointeeType();
3965 KeepNParams(valNormalizedType,vanillaType, interp, normCtxt);
3966 normalizedType = astCtxt.getPointerType(valNormalizedType);
3968 normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3974 if (llvm::isa<clang::ReferenceType>(normalizedType.getTypePtr())) {
3976 bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(normalizedType.getTypePtr());
3977 clang::Qualifiers quals = normalizedType.getQualifiers();
3978 auto valNormType = normalizedType->getPointeeType();
3979 KeepNParams(valNormType, vanillaType, interp, normCtxt);
3983 normalizedType = astCtxt.getLValueReferenceType(valNormType);
3985 normalizedType = astCtxt.getRValueReferenceType(valNormType);
3987 normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3992 bool prefix_changed =
false;
3993 clang::NestedNameSpecifier prefix = std::nullopt;
3994 clang::Qualifiers prefix_qualifiers = normalizedType.getLocalQualifiers();
3995 NestedNameSpecifier desugaredPrefix = normalizedType->getPrefix();
3996 if (desugaredPrefix) {
3999 prefix = AddDefaultParametersNNS(astCtxt, desugaredPrefix, interp, normCtxt);
4000 prefix_changed = prefix != desugaredPrefix;
4008 const clang::ClassTemplateDecl* ctdWithDefaultArgs = ctd;
4009 for (
const RedeclarableTemplateDecl* rd: ctdWithDefaultArgs->redecls()) {
4010 clang::TemplateParameterList* tpl = rd->getTemplateParameters();
4011 if (tpl->getMinRequiredArguments () < tpl->size()) {
4012 ctdWithDefaultArgs = llvm::dyn_cast<clang::ClassTemplateDecl>(rd);
4017 if (!ctdWithDefaultArgs) {
4018 Error(
"KeepNParams",
"Not found template default arguments\n");
4019 normalizedType=originalNormalizedType;
4023 TemplateParameterList* tParsPtr = ctdWithDefaultArgs->getTemplateParameters();
4024 const TemplateParameterList& tPars = *tParsPtr;
4025 const TemplateArgumentList& tArgs = ctsd->getTemplateArgs();
4028 TemplateName theTemplateName;
4029 ElaboratedTypeKeyword theKeyword = ElaboratedTypeKeyword::None;
4030 ExtractTemplateNameFromQualType(normalizedType, theTemplateName, theKeyword);
4031 if (theTemplateName.isNull()) {
4032 normalizedType=originalNormalizedType;
4036 const TemplateSpecializationType* normalizedTst =
4037 llvm::dyn_cast<TemplateSpecializationType>(normalizedType.getTypePtr());
4038 if (!normalizedTst) {
4039 normalizedType=originalNormalizedType;
4043 const clang::ClassTemplateSpecializationDecl* TSTdecl
4044 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(normalizedType.getTypePtr()->getAsCXXRecordDecl());
4045 bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
4052 llvm::SmallVector<TemplateArgument, 4> argsToKeep;
4054 const int nArgs = tArgs.size();
4055 const auto &normArgs = normalizedTst->template_arguments();
4056 const int nNormArgs = normArgs.size();
4058 bool mightHaveChanged =
false;
4059 int latestNonDefaultArg = -1;
4062 for (
int formal = 0, inst = 0; formal != nArgs; ++formal, ++inst) {
4063 const NamedDecl* tParPtr = tPars.getParam(formal);
4065 Error(
"KeepNParams",
"The parameter number %s is null.\n", formal);
4072 if (formal == nNormArgs || inst == nNormArgs)
break;
4074 const TemplateArgument& tArg = tArgs.get(formal);
4075 TemplateArgument normTArg(normArgs[inst]);
4077 bool shouldKeepArg = nArgsToKeep < 0 || inst < nArgsToKeep;
4078 if (isStdDropDefault) shouldKeepArg =
false;
4087 if ( tParPtr->isTemplateParameterPack() ) {
4092 for( ; inst != nNormArgs; ++inst) {
4093 normTArg = normArgs[inst];
4095 argsToKeep.push_back(normTArg);
4098 latestNonDefaultArg = -1;
4102 argsToKeep.push_back(normTArg);
4103 latestNonDefaultArg = formal;
4106 if (!isStdDropDefault) {
4108 mightHaveChanged =
true;
4118 auto argKind = tArg.getKind();
4119 if (argKind == clang::TemplateArgument::Type){
4121 equal =
areEqualTypes(tArg, argsToKeep, *tParPtr, interp, normCtxt);
4122 }
else if (argKind == clang::TemplateArgument::Integral){
4126 argsToKeep.push_back(normTArg);
4128 latestNonDefaultArg = formal;
4131 mightHaveChanged =
true;
4137 if (latestNonDefaultArg >= 0)
4138 argsToKeep.resize(latestNonDefaultArg + 1);
4140 if (!prefix_changed && !mightHaveChanged) {
4141 normalizedType = originalNormalizedType;
4146 if (mightHaveChanged) {
4147 Qualifiers qualifiers = normalizedType.getLocalQualifiers();
4148 normalizedType = astCtxt.getTemplateSpecializationType(theKeyword,
4152 normalizedType.getTypePtr()->getCanonicalTypeInternal());
4153 normalizedType = astCtxt.getQualifiedType(normalizedType, qualifiers);
4161 normalizedType = cling::utils::TypeName::QualifyTypeUnderPrefix(astCtxt, normalizedType, prefix);
4162 normalizedType = astCtxt.getQualifiedType(normalizedType,prefix_qualifiers);
4175 clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4178 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interpreter));
4179 clang::QualType normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt,
type, normCtxt.
GetConfig(),
true );
4187 return normalizedType;
4201 if (
type.isNull()) {
4208 clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4209 clang::PrintingPolicy policy(ctxt.getPrintingPolicy());
4210 policy.SuppressTagKeyword =
true;
4211 policy.SuppressTagKeywordInAnonNames =
true;
4212 policy.AnonymousTagLocations =
false;
4217 policy.SuppressUnwrittenScope =
true;
4219 std::string normalizedNameStep1;
4222 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
4223 normalizedType.getAsStringInternal(normalizedNameStep1,policy);
4241 if (norm_name.length()>2 && norm_name[0]==
':' && norm_name[1]==
':') {
4242 norm_name.erase(0,2);
4250 const clang::TypeDecl* typeDecl,
4251 const cling::Interpreter &interpreter)
4254 const clang::Sema &sema = interpreter.getSema();
4255 clang::ASTContext& astCtxt = sema.getASTContext();
4256 clang::QualType qualType = astCtxt.getTypeDeclType(typeDecl);
4265std::pair<std::string,clang::QualType>
4267 const cling::Interpreter &interpreter,
4271 std::string thisTypeName;
4272 GetNormalizedName(thisTypeName, thisType, interpreter, normCtxt );
4275 if (!hasChanged)
return std::make_pair(thisTypeName,thisType);
4279 "Name changed from %s to %s\n", thisTypeName.c_str(), thisTypeNameForIO.c_str());
4282 auto& lookupHelper = interpreter.getLookupHelper();
4284 const clang::Type* typePtrForIO;
4285 lookupHelper.findScope(thisTypeNameForIO,
4286 cling::LookupHelper::DiagSetting::NoDiagnostics,
4290 if (!typePtrForIO) {
4292 "Type not found: %s.",thisTypeNameForIO.c_str());
4295 clang::QualType typeForIO(typePtrForIO,0);
4298 if (!typeForIO->isRecordType()) {
4299 return std::make_pair(thisTypeNameForIO,typeForIO);
4302 auto thisDeclForIO = typeForIO->getAsCXXRecordDecl();
4303 if (!thisDeclForIO) {
4305 "The type for IO corresponding to %s is %s and it could not be found in the AST as class.\n", thisTypeName.c_str(), thisTypeNameForIO.c_str());
4306 return std::make_pair(thisTypeName,thisType);
4309 return std::make_pair(thisTypeNameForIO,typeForIO);
4315 const cling::Interpreter &interpreter,
4327 std::string dictFileName(moduleName);
4328 dictFileName +=
"_rdict.pcm";
4329 return dictFileName;
4333 llvm::errs() << llvm::StringRef(commentStart, 80) <<
'\n';
4359 clang::SourceManager& sourceManager = decl.getASTContext().getSourceManager();
4360 clang::SourceLocation sourceLocation = decl.getEndLoc();
4363 sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
4371 if (!decl.hasOwningModule() && sourceManager.isLoadedSourceLocation(sourceLocation)) {
4377 const char *commentStart = sourceManager.getCharacterData(sourceLocation, &invalid);
4381 bool skipToSemi =
true;
4382 if (
const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(&decl)) {
4383 if (FD->isImplicit()) {
4387 if (FD->isExplicitlyDefaulted() || FD->isDeletedAsWritten()) {
4391 }
else if (FD->doesThisDeclarationHaveABody()) {
4394 assert((decl.getEndLoc() != sourceLocation || *commentStart ==
'}'
4396 &&
"Expected macro or end of body at '}'");
4397 if (*commentStart) ++commentStart;
4400 while (*commentStart && isspace(*commentStart)
4401 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4404 if (*commentStart ==
';') ++commentStart;
4408 }
else if (
const clang::EnumConstantDecl* ECD
4409 = clang::dyn_cast<clang::EnumConstantDecl>(&decl)) {
4411 if (ECD->getNextDeclInContext())
4412 while (*commentStart && *commentStart !=
',' && *commentStart !=
'\r' && *commentStart !=
'\n')
4420 while (*commentStart && *commentStart !=
';' && *commentStart !=
'\r' && *commentStart !=
'\n')
4422 if (*commentStart ==
';') ++commentStart;
4426 while ( *commentStart && isspace(*commentStart)
4427 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4431 if (commentStart[0] !=
'/' ||
4432 (commentStart[1] !=
'/' && commentStart[1] !=
'*')) {
4442 unsigned int skipChars = 2;
4443 if (commentStart[0] ==
'/' &&
4444 commentStart[1] ==
'/' &&
4445 (commentStart[2] ==
'/' || commentStart[2] ==
'!') &&
4446 commentStart[3] ==
'<') {
4448 }
else if (commentStart[0] ==
'/' &&
4449 commentStart[1] ==
'*' &&
4450 (commentStart[2] ==
'*' || commentStart[2] ==
'!') &&
4451 commentStart[3] ==
'<') {
4455 commentStart += skipChars;
4458 while ( *commentStart && isspace(*commentStart)
4459 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4462 const char* commentEnd = commentStart;
4464 while (*commentEnd && *commentEnd !=
'\n' && *commentEnd !=
'\r') {
4470 while (commentEnd > commentStart && isspace(commentEnd[-1])) {
4476 unsigned offset = commentStart - sourceManager.getCharacterData(sourceLocation);
4477 *loc = sourceLocation.getLocWithOffset(
offset - 1);
4480 return llvm::StringRef(commentStart, commentEnd - commentStart);
4488 if (!decl)
return false;
4490 auto& sema = interpreter.getCI()->getSema();
4491 auto maybeMacroLoc = decl->getLocation();
4493 if (!maybeMacroLoc.isMacroID())
return false;
4495 static const std::vector<std::string> signatures =
4496 {
"ClassDef",
"ClassDefOverride",
"ClassDefNV",
"ClassDefInline",
"ClassDefInlineOverride",
"ClassDefInlineNV" };
4498 for (
auto &
name : signatures)
4499 if (sema.findMacroSpelling(maybeMacroLoc,
name))
4513 clang::SourceLocation *loc,
4514 const cling::Interpreter &interpreter)
4516 using namespace clang;
4518 const Decl* DeclFileLineDecl
4519 = interpreter.getLookupHelper().findFunctionProto(&decl,
"DeclFileLine",
"",
4520 cling::LookupHelper::NoDiagnostics);
4524 SourceLocation commentSLoc;
4526 if (comment.size()) {
4533 return llvm::StringRef();
4542 const clang::Type *rawtype =
type.getTypePtr();
4545 if (rawtype->isElaboratedTypeSpecifier() ) {
4546 rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4548 if (rawtype->isArrayType()) {
4549 rawtype =
type.getTypePtr()->getBaseElementTypeUnsafe ();
4551 if (rawtype->isPointerType() || rawtype->isReferenceType() ) {
4553 clang::QualType pointee;
4554 while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
4556 rawtype = pointee.getTypePtr();
4558 if (rawtype->isElaboratedTypeSpecifier() ) {
4559 rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4561 if (rawtype->isArrayType()) {
4562 rawtype = rawtype->getBaseElementTypeUnsafe ();
4566 if (rawtype->isArrayType()) {
4567 rawtype = rawtype->getBaseElementTypeUnsafe ();
4578 if (ctxt.isNamespace() || ctxt.isTranslationUnit())
4580 else if(
const auto parentdecl = llvm::dyn_cast<clang::CXXRecordDecl>(&ctxt))
4593 const clang::DeclContext *ctxt = decl.getDeclContext();
4594 switch (decl.getAccess()) {
4595 case clang::AS_public:
4597 case clang::AS_protected:
4599 case clang::AS_private:
4601 case clang::AS_none:
4605 assert(
false &&
"Unexpected value for the access property value in Clang");
4615 return cling::utils::Analyze::IsStdClass(cl);
4625 if (cling::utils::Analyze::IsStdClass(cl)) {
4626 static const char *names[] =
4627 {
"shared_ptr",
"__shared_ptr",
4628 "vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset"};
4629 llvm::StringRef clname(cl.getName());
4630 for(
auto &&
name : names) {
4631 if (clname ==
name)
return true;
4641 const clang::CXXRecordDecl ¤tCl)
4644 if (&cl == ¤tCl)
return true;
4646 const clang::CXXRecordDecl* previous = currentCl.getPreviousDecl();
4649 if (
nullptr == previous){
4668 const clang::CXXRecordDecl *thisDecl =
4669 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(typ, cling::LookupHelper::WithDiagnostics));
4673 Error(
"IsOfType",
"Record decl of type %s not found in the AST.", typ.c_str());
4678 const clang::CXXRecordDecl *mostRecentDecl = thisDecl->getMostRecentDecl();
4703 if (!IsStdClass(cl)) {
4704 auto *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(cl.getDeclContext());
4705 if (cl.getName() !=
"RVec" || nsDecl ==
nullptr || nsDecl->getName() !=
"VecOps")
4708 auto *parentNsDecl = llvm::dyn_cast<clang::NamespaceDecl>(cl.getDeclContext()->getParent());
4709 if (parentNsDecl ==
nullptr || parentNsDecl->getName() !=
"ROOT")
4713 return STLKind(cl.getName());
4717 using namespace clang;
4718 struct SearchTypedef:
public TypeVisitor<SearchTypedef, bool> {
4719 bool VisitTypedefType(
const TypedefType* TD) {
4722 bool VisitArrayType(
const ArrayType* AT) {
4723 return Visit(AT->getElementType().getTypePtr());
4725 bool VisitDecltypeType(
const DecltypeType* DT) {
4726 return Visit(DT->getUnderlyingType().getTypePtr());
4728 bool VisitPointerType(
const PointerType* PT) {
4729 return Visit(PT->getPointeeType().getTypePtr());
4731 bool VisitReferenceType(
const ReferenceType* RT) {
4732 return Visit(RT->getPointeeType().getTypePtr());
4734 bool VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType* STST) {
4735 return Visit(STST->getReplacementType().getTypePtr());
4737 bool VisitTemplateSpecializationType(
const TemplateSpecializationType* TST) {
4738 for (
const TemplateArgument &
TA : TST->template_arguments()) {
4739 if (
TA.getKind() == TemplateArgument::Type && Visit(
TA.getAsType().getTypePtr()))
4744 bool VisitTemplateTypeParmType(
const TemplateTypeParmType* TTPT) {
4747 bool VisitTypeOfType(
const TypeOfType* TOT) {
4748 return TOT->getUnmodifiedType().getTypePtr();
4769 using namespace llvm;
4770 using namespace clang;
4771 const clang::ASTContext &Ctxt =
instance->getAsCXXRecordDecl()->getASTContext();
4775 QualType QT =
input;
4779 if (isa<clang::PointerType>(QT.getTypePtr())) {
4781 Qualifiers quals = QT.getQualifiers();
4784 if (nQT == QT->getPointeeType())
return QT;
4786 QT = Ctxt.getPointerType(nQT);
4788 QT = Ctxt.getQualifiedType(QT, quals);
4794 if (isa<ReferenceType>(QT.getTypePtr())) {
4796 bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
4797 Qualifiers quals = QT.getQualifiers();
4800 if (nQT == QT->getPointeeType())
return QT;
4804 QT = Ctxt.getLValueReferenceType(nQT);
4806 QT = Ctxt.getRValueReferenceType(nQT);
4808 QT = Ctxt.getQualifiedType(QT, quals);
4814 if (isa<clang::ArrayType>(QT.getTypePtr())) {
4816 Qualifiers quals = QT.getQualifiers();
4818 if (
const auto arr = dyn_cast<ConstantArrayType>(QT.getTypePtr())) {
4821 if (newQT == arr->getElementType())
return QT;
4822 QT = Ctxt.getConstantArrayType(newQT,
4825 arr->getSizeModifier(),
4826 arr->getIndexTypeCVRQualifiers());
4828 }
else if (
const auto arr = dyn_cast<DependentSizedArrayType>(QT.getTypePtr())) {
4831 if (newQT == QT)
return QT;
4832 QT = Ctxt.getDependentSizedArrayType (newQT,
4834 arr->getSizeModifier(),
4835 arr->getIndexTypeCVRQualifiers());
4837 }
else if (
const auto arr = dyn_cast<IncompleteArrayType>(QT.getTypePtr())) {
4840 if (newQT == arr->getElementType())
return QT;
4841 QT = Ctxt.getIncompleteArrayType (newQT,
4842 arr->getSizeModifier(),
4843 arr->getIndexTypeCVRQualifiers());
4845 }
else if (
const auto arr = dyn_cast<VariableArrayType>(QT.getTypePtr())) {
4848 if (newQT == arr->getElementType())
return QT;
4849 QT = Ctxt.getVariableArrayType (newQT,
4851 arr->getSizeModifier(),
4852 arr->getIndexTypeCVRQualifiers());
4856 QT = Ctxt.getQualifiedType(QT, quals);
4860 const clang::TemplateSpecializationType* TST
4861 = llvm::dyn_cast<const clang::TemplateSpecializationType>(
instance);
4863 if (!TST)
return input;
4865 const clang::ClassTemplateSpecializationDecl* TSTdecl
4866 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(
instance->getAsCXXRecordDecl());
4868 if (!TSTdecl)
return input;
4870 const clang::SubstTemplateTypeParmType *substType
4871 = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(
input.getTypePtr());
4875 const clang::ClassTemplateDecl *replacedCtxt =
nullptr;
4877 const clang::DeclContext *replacedDeclCtxt = substType->getReplacedParameter()->getDeclContext();
4878 const clang::CXXRecordDecl *decl = llvm::dyn_cast<clang::CXXRecordDecl>(replacedDeclCtxt);
4879 unsigned int index = substType->getReplacedParameter()->getIndex();
4882 if (decl->getKind() == clang::Decl::ClassTemplatePartialSpecialization) {
4883 const clang::ClassTemplatePartialSpecializationDecl *spec = llvm::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(decl);
4885 unsigned int depth = substType->getReplacedParameter()->getDepth();
4887 const TemplateArgument *instanceArgs = spec->getTemplateArgs().data();
4888 unsigned int instanceNArgs = spec->getTemplateArgs().size();
4892 for(
unsigned int A = 0; A < instanceNArgs; ++A) {
4893 if (instanceArgs[A].getKind() == clang::TemplateArgument::Type) {
4894 clang::QualType argQualType = instanceArgs[A].getAsType();
4896 const clang::TemplateTypeParmType *replacementType;
4898 replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(argQualType);
4900 if (!replacementType) {
4901 const clang::SubstTemplateTypeParmType *argType
4902 = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(argQualType);
4904 clang::QualType replacementQT = argType->getReplacementType();
4905 replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(replacementQT);
4908 if (replacementType &&
4909 depth == replacementType->getDepth() &&
4910 index == replacementType->getIndex() )
4917 replacedCtxt = spec->getSpecializedTemplate();
4919 replacedCtxt = decl->getDescribedClassTemplate();
4921 }
else if (
auto const declguide = llvm::dyn_cast<clang::CXXDeductionGuideDecl>(replacedDeclCtxt)) {
4922 replacedCtxt = llvm::dyn_cast<clang::ClassTemplateDecl>(declguide->getDeducedTemplate());
4923 }
else if (
auto const ctdecl = llvm::dyn_cast<clang::ClassTemplateDecl>(replacedDeclCtxt)) {
4924 replacedCtxt = ctdecl;
4926 std::string astDump;
4927 llvm::raw_string_ostream ostream(astDump);
4930 ROOT::TMetaUtils::Warning(
"ReSubstTemplateArg",
"Unexpected type of declaration context for template parameter: %s.\n\tThe responsible class is:\n\t%s\n",
4931 replacedDeclCtxt->getDeclKindName(), astDump.c_str());
4932 replacedCtxt =
nullptr;
4935 if (replacedCtxt && replacedCtxt->getCanonicalDecl() == TSTdecl->getSpecializedTemplate()->getCanonicalDecl())
4937 const auto &TAs = TST->template_arguments();
4938 if (
index >= TAs.size()) {
4944 }
else if (TAs[
index].getKind() == clang::TemplateArgument::Type) {
4945 return TAs[
index].getAsType();
4954 const clang::TemplateSpecializationType* inputTST
4955 = llvm::dyn_cast<const clang::TemplateSpecializationType>(
input.getTypePtr());
4956 const clang::ASTContext& astCtxt = TSTdecl->getASTContext();
4959 bool mightHaveChanged =
false;
4960 llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
4961 for (
const clang::TemplateArgument &
TA : inputTST->template_arguments()) {
4962 if (
TA.getKind() != clang::TemplateArgument::Type) {
4963 desArgs.push_back(
TA);
4967 clang::QualType SubTy =
TA.getAsType();
4969 if (SubTy->getPrefix()
4970 || llvm::isa<clang::SubstTemplateTypeParmType>(SubTy)
4971 || llvm::isa<clang::TemplateSpecializationType>(SubTy)) {
4973 mightHaveChanged = SubTy != newSubTy;
4974 if (!newSubTy.isNull()) {
4975 desArgs.push_back(clang::TemplateArgument(newSubTy));
4978 desArgs.push_back(
TA);
4982 if (mightHaveChanged) {
4983 clang::Qualifiers qualifiers =
input.getLocalQualifiers();
4984 input = astCtxt.getTemplateSpecializationType(inputTST->getKeyword(),
4985 inputTST->getTemplateName(),
4988 inputTST->getCanonicalTypeInternal());
4989 input = astCtxt.getQualifiedType(
input, qualifiers);
5001 if ( nArgsToRemove == 0 ||
name ==
"")
5008 unsigned int nArgsRemoved=0;
5009 unsigned int nBraces=0;
5011 while (nArgsRemoved!=nArgsToRemove && cur<
length){
5013 if (
c ==
'<') nBraces++;
5014 if (
c ==
'>') nBraces--;
5015 if (
c ==
',' && nBraces==1 ) nArgsRemoved++;
5029 static const char *stls[] =
5030 {
"any",
"vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset",
5031 "forward_list",
"unordered_set",
"unordered_multiset",
"unordered_map",
"unordered_multimap",
"RVec",
nullptr};
5045 for (
int k = 1; stls[k]; k++) {
5046 if (
type == stls[k])
5059 TND = TND->getMostRecentDecl();
5060 while (TND && !(TND->hasAttrs()))
5061 TND = TND->getPreviousDecl();
5073 TD = TD->getMostRecentDecl();
5074 while (TD && !(TD->hasAttrs() && TD->isThisDeclarationADefinition()))
5075 TD = TD->getPreviousDecl();
5084 std::list<std::pair<std::string,bool> >& enclosingNamespaces)
5086 const clang::DeclContext* enclosingNamespaceDeclCtxt = decl.getDeclContext();
5087 if (!enclosingNamespaceDeclCtxt)
return;
5089 const clang::NamespaceDecl* enclosingNamespace =
5090 clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
5091 if (!enclosingNamespace)
return;
5093 enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
5094 enclosingNamespace->isInline()));
5104 std::list<std::pair<std::string,bool> >& enclosingNamespaces)
5106 const clang::DeclContext* enclosingNamespaceDeclCtxt = ctxt.getParent ();
5109 if (!enclosingNamespaceDeclCtxt) {
5115 const clang::NamespaceDecl* enclosingNamespace = clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
5116 if (!enclosingNamespace)
return;
5119 enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
5120 enclosingNamespace->isInline()));
5131 std::list<std::pair<std::string,unsigned int> >& enclosingSc)
5133 const clang::DeclContext* enclosingDeclCtxt = decl.getDeclContext();
5134 if (!enclosingDeclCtxt)
return nullptr;
5136 unsigned int scopeType;
5138 if (
auto enclosingNamespacePtr =
5139 clang::dyn_cast<clang::NamespaceDecl>(enclosingDeclCtxt)){
5140 scopeType= enclosingNamespacePtr->isInline() ? 1 : 0;
5141 enclosingSc.push_back(std::make_pair(enclosingNamespacePtr->getNameAsString(),scopeType));
5145 if (
auto enclosingClassPtr =
5146 clang::dyn_cast<clang::RecordDecl>(enclosingDeclCtxt)){
5147 return enclosingClassPtr;
5159 std::string::size_type beginVar = 0;
5160 std::string::size_type endVar = 0;
5161 while ((beginVar = txt.find(
'$', beginVar)) != std::string::npos
5162 && beginVar + 1 < txt.length()) {
5163 std::string::size_type beginVarName = beginVar + 1;
5164 std::string::size_type endVarName = std::string::npos;
5165 if (txt[beginVarName] ==
'(') {
5167 endVarName = txt.find(
')', beginVarName);
5169 if (endVarName == std::string::npos) {
5171 varname, txt.c_str() + beginVar);
5174 endVar = endVarName + 1;
5177 beginVarName = beginVar + 1;
5178 endVarName = beginVarName;
5179 while (isalnum(txt[endVarName]) || txt[endVarName] ==
'_')
5181 endVar = endVarName;
5184 const char* val = std::getenv(txt.substr(beginVarName,
5185 endVarName - beginVarName).c_str());
5188 txt.replace(beginVar, endVar - beginVar, val);
5189 int lenval = strlen(val);
5190 int delta = lenval - (endVar - beginVar);
5194 beginVar = endVar + 1;
5206 const char* envInclPath = std::getenv(
"ROOT_INCLUDE_PATH");
5212 constexpr char kPathSep =
';';
5214 constexpr char kPathSep =
':';
5217 std::istringstream envInclPathsStream(envInclPath);
5218 std::string inclPath;
5219 while (std::getline(envInclPathsStream, inclPath, kPathSep)) {
5222 if (!inclPath.empty()) {
5223 clingArgs.push_back(
"-I");
5224 clingArgs.push_back(inclPath);
5235 size_t start_pos = 0;
5240 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
5241 str.replace(start_pos, from.length(), to);
5242 start_pos += to.length();
5243 if (recurse) changed =
true;
5259 if (theString.size() < theSubstring.size())
return false;
5260 const unsigned int theSubstringSize = theSubstring.size();
5261 return 0 == theString.compare(theString.size() - theSubstringSize,
5270 if (theString.size() < theSubstring.size())
return false;
5271 const unsigned int theSubstringSize = theSubstring.size();
5272 return 0 == theString.compare(0,
5290 size_t linkdeflen = 9;
5292 if (0 == strncasecmp(
filename + (
len - linkdeflen),
"linkdef", linkdeflen - 2)
5308 return llvm::sys::path::extension(
filename) ==
".h" ||
5309 llvm::sys::path::extension(
filename) ==
".hh" ||
5310 llvm::sys::path::extension(
filename) ==
".hpp" ||
5311 llvm::sys::path::extension(
filename) ==
".H" ||
5312 llvm::sys::path::extension(
filename) ==
".h++" ||
5313 llvm::sys::path::extension(
filename) ==
"hxx" ||
5314 llvm::sys::path::extension(
filename) ==
"Hxx" ||
5315 llvm::sys::path::extension(
filename) ==
"HXX";
5321 cling::Interpreter::IgnoreFilesFunc_t ignoreFiles,
5322 const cling::Interpreter &interp,
5325 clang::Sema &sema = interp.getSema();
5326 cling::Transaction theTransaction(sema);
5327 std::set<clang::Decl *> addedDecls;
5328 for (
auto decl : decls) {
5330 clang::Decl *ncDecl =
const_cast<clang::Decl *
>(decl);
5331 theTransaction.append(ncDecl);
5333 std::string newFwdDecl;
5334 llvm::raw_string_ostream llvmOstr(newFwdDecl);
5336 std::string locallogs;
5337 llvm::raw_string_ostream llvmLogStr(locallogs);
5338 interp.forwardDeclare(theTransaction, sema.getPreprocessor(), sema.getASTContext(), llvmOstr,
true,
5339 logs ? &llvmLogStr : nullptr, ignoreFiles);
5343 logs->swap(locallogs);
5355 std::string& defString)
5367 std::string& defString)
5369 std::list<std::pair<std::string,unsigned int> > enclosingNamespaces;
5372 if (rcdPtr)
return rcdPtr;
5375 static const std::string scopeType [] = {
"namespace ",
"inline namespace ",
"class "};
5377 std::string scopeName;
5378 std::string scopeContent;
5379 unsigned int scopeIndex;
5380 for (
auto const & encScope : enclosingNamespaces){
5381 scopeIndex = encScope.second;
5382 scopeName = encScope.first;
5383 scopeContent =
" { " + defString +
" }";
5384 defString = scopeType[scopeIndex] +
5406 const clang::TemplateParameterList& tmplParamList,
5407 const cling::Interpreter& interpreter)
5410 for (
auto prmIt = tmplParamList.begin();
5411 prmIt != tmplParamList.end(); prmIt++){
5413 if (prmIt != tmplParamList.begin())
5414 templateArgs +=
", ";
5416 auto nDecl = *prmIt;
5417 std::string typeName;
5420 if (llvm::isa<clang::TemplateTypeParmDecl>(nDecl)){
5421 typeName =
"typename ";
5422 if (nDecl->isParameterPack())
5424 typeName += (*prmIt)->getNameAsString();
5427 else if (
auto nttpd = llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(nDecl)){
5428 auto theType = nttpd->getType();
5431 if (theType.getAsString().find(
"enum") != std::string::npos){
5432 std::string astDump;
5433 llvm::raw_string_ostream ostream(astDump);
5434 nttpd->dump(ostream);
5436 ROOT::TMetaUtils::Warning(
nullptr,
"Forward declarations of templates with enums as template parameters. The responsible class is: %s\n", astDump.c_str());
5445 else if (
auto ttpd = llvm::dyn_cast<clang::TemplateTemplateParmDecl>(nDecl)){
5448 std::string astDump;
5449 llvm::raw_string_ostream ostream(astDump);
5450 ttpd->dump(ostream);
5452 ROOT::TMetaUtils::Error(
nullptr,
"Cannot reconstruct template template parameter forward declaration for %s\n", astDump.c_str());
5457 templateArgs += typeName;
5468 const cling::Interpreter& interpreter,
5469 std::string& defString)
5471 std::string templatePrefixString;
5472 auto tmplParamList= templDecl.getTemplateParameters();
5473 if (!tmplParamList){
5475 "Cannot extract template parameter list for %s",
5476 templDecl.getNameAsString().c_str());
5483 "Problems with arguments for forward declaration of class %s\n",
5484 templDecl.getNameAsString().c_str());
5487 templatePrefixString =
"template " + templatePrefixString +
" ";
5489 defString = templatePrefixString +
"class ";
5490 if (templDecl.isParameterPack())
5491 defString +=
"... ";
5492 defString += templDecl.getNameAsString();
5493 if (llvm::isa<clang::TemplateTemplateParmDecl>(&templDecl)) {
5507 std::string& argFwdDecl,
5508 const cling::Interpreter& interpreter,
5509 bool acceptStl=
false)
5515 if (clang::TemplateArgument::Type != arg.getKind())
return 0;
5517 auto argQualType = arg.getAsType();
5520 while (llvm::isa<clang::PointerType>(argQualType.getTypePtr())) argQualType = argQualType->getPointeeType();
5522 auto argTypePtr = argQualType.getTypePtr();
5525 if (llvm::isa<clang::EnumType>(argTypePtr)){
5530 if (llvm::isa<clang::BuiltinType>(argTypePtr)){
5535 if (
auto tdTypePtr = llvm::dyn_cast<clang::TypedefType>(argTypePtr)) {
5536 FwdDeclFromTypeDefNameDecl(*tdTypePtr->getDecl(), interpreter, argFwdDecl);
5540 if (
auto argRecTypePtr = llvm::dyn_cast<clang::RecordType>(argTypePtr)){
5542 if (
auto argRecDeclPtr = argRecTypePtr->getDecl()){
5543 FwdDeclFromRcdDecl(*argRecDeclPtr,interpreter,argFwdDecl,acceptStl);
5555 const cling::Interpreter& interpreter,
5556 std::string& defString,
5557 const std::string &normalizedName)
5561 if (
auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)) {
5562 if (
const auto *specDef = tmplSpecDeclPtr->getDefinition()) {
5563 if (specDef->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization)
5567 std::cout <<
" Forward declaring template spec " << normalizedName <<
":\n";
5568 for (
auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()) {
5569 std::string argFwdDecl;
5572 std::cout <<
" o Template argument ";
5574 std::cout <<
"successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5576 std::cout <<
"could not be treated. Abort fwd declaration generation.\n";
5583 defString += argFwdDecl +
'\n';
5585 defString +=
"template <> class " + normalizedName +
';';
5599 const cling::Interpreter& interpreter,
5600 std::string& defString,
5608 if (!recordDecl.getIdentifier())
5612 std::string argsFwdDecl;
5614 if (
auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)){
5615 std::string argFwdDecl;
5617 std::cout <<
"Class " << recordDecl.getNameAsString()
5618 <<
" is a template specialisation. Treating its arguments.\n";
5619 for(
auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()){
5622 std::cout <<
" o Template argument ";
5624 std::cout <<
"successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5626 std::cout <<
"could not be treated. Abort fwd declaration generation.\n";
5633 argsFwdDecl+=argFwdDecl;
5637 defString=argsFwdDecl;
5642 if (
auto tmplDeclPtr = tmplSpecDeclPtr->getSpecializedTemplate()){
5645 defString = argsFwdDecl +
"\n" + defString;
5650 defString =
"class " + recordDecl.getNameAsString() +
";";
5651 const clang::RecordDecl* rcd =
EncloseInScopes(recordDecl, defString);
5659 defString = argsFwdDecl +
"\n" + defString;
5670 const cling::Interpreter& interpreter,
5671 std::string& fwdDeclString,
5672 std::unordered_set<std::string>* fwdDeclSetPtr)
5674 std::string buffer = tdnDecl.getNameAsString();
5675 std::string underlyingName;
5676 auto underlyingType = tdnDecl.getUnderlyingType().getCanonicalType();
5677 if (
const clang::TagType* TT
5678 = llvm::dyn_cast<clang::TagType>(underlyingType.getTypePtr())) {
5679 if (clang::NamedDecl* ND = TT->getDecl()) {
5680 if (!ND->getIdentifier()) {
5694 if (underlyingName.find(
">::") != std::string::npos)
5697 buffer=
"typedef "+underlyingName+
" "+buffer+
";";
5709 auto& ctxt = tdnDecl.getASTContext();
5710 auto immediatelyUnderlyingType = underlyingType.getSingleStepDesugaredType(ctxt);
5712 if (
auto underlyingTdnTypePtr = llvm::dyn_cast<clang::TypedefType>(immediatelyUnderlyingType.getTypePtr())){
5713 std::string tdnFwdDecl;
5714 auto underlyingTdnDeclPtr = underlyingTdnTypePtr->getDecl();
5719 if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(tdnFwdDecl).second)
5720 fwdDeclString+=tdnFwdDecl;
5721 }
else if (
auto CXXRcdDeclPtr = immediatelyUnderlyingType->getAsCXXRecordDecl()){
5722 std::string classFwdDecl;
5724 std::cout <<
"Typedef " << tdnDecl.getNameAsString() <<
" hides a class: "
5725 << CXXRcdDeclPtr->getNameAsString() << std::endl;
5734 if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(classFwdDecl).second)
5735 fwdDeclString+=classFwdDecl;
5738 fwdDeclString+=buffer;
5750 std::string& valAsString,
5751 const clang::PrintingPolicy& ppolicy)
5753 auto defArgExprPtr = par.getDefaultArg();
5754 auto& ctxt = par.getASTContext();
5755 if(!defArgExprPtr->isEvaluatable(ctxt)){
5759 auto defArgType = par.getType();
5762 if (defArgType->isBooleanType()){
5764 defArgExprPtr->EvaluateAsBooleanCondition (
result,ctxt);
5765 valAsString=std::to_string(
result);
5770 if (defArgType->isIntegerType()){
5771 clang::Expr::EvalResult evalResult;
5772 defArgExprPtr->EvaluateAsInt(evalResult, ctxt);
5773 llvm::APSInt
result = evalResult.Val.getInt();
5774 auto uintVal = *
result.getRawData();
5775 if (
result.isNegative()){
5776 long long int intVal=uintVal*-1;
5777 valAsString=std::to_string(intVal);
5779 valAsString=std::to_string(uintVal);
5786 llvm::raw_string_ostream rso(valAsString);
5787 defArgExprPtr->printPretty(rso,
nullptr,ppolicy);
5788 valAsString = rso.str();
The file contains utilities which are foundational and could be used across the core component of ROO...
#define R(a, b, c, d, e, f, g, h, i)
static Roo_reg_AGKInteg1D instance
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
short Version_t
Class version identifier (short)
static void indent(ostringstream &buf, int indent_level)
static bool RecurseKeepNParams(clang::TemplateArgument &normTArg, const clang::TemplateArgument &tArg, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const clang::ASTContext &astCtxt)
static clang::SourceLocation getFinalSpellingLoc(clang::SourceManager &sourceManager, clang::SourceLocation sourceLoc)
const clang::DeclContext * GetEnclosingSpace(const clang::RecordDecl &cl)
bool IsTemplate(const clang::Decl &cl)
static void KeepNParams(clang::QualType &normalizedType, const clang::QualType &vanillaType, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
This function allows to manipulate the number of arguments in the type of a template specialisation.
static void CreateNameTypeMap(const clang::CXXRecordDecl &cl, ROOT::MembersTypeMap_t &nameType)
Create the data member name-type map for given class.
const clang::CXXMethodDecl * GetMethodWithProto(const clang::Decl *cinfo, const char *method, const char *proto, const cling::Interpreter &interp, bool diagnose)
int dumpDeclForAssert(const clang::Decl &D, const char *commentStart)
static void replaceEnvVars(const char *varname, std::string &txt)
Reimplementation of TSystem::ExpandPathName() that cannot be used from TMetaUtils.
static bool areEqualValues(const clang::TemplateArgument &tArg, const clang::NamedDecl &tPar)
std::cout << "Are equal values?\n";
static bool isTypeWithDefault(const clang::NamedDecl *nDecl)
Check if this NamedDecl is a template parameter with a default argument.
static int TreatSingleTemplateArg(const clang::TemplateArgument &arg, std::string &argFwdDecl, const cling::Interpreter &interpreter, bool acceptStl=false)
static bool areEqualTypes(const clang::TemplateArgument &tArg, llvm::SmallVectorImpl< clang::TemplateArgument > &preceedingTArgs, const clang::NamedDecl &tPar, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
static bool hasSomeTypedefSomewhere(const clang::Type *T)
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
const_iterator begin() const
A RAII helper to remove and readd enclosing _Atomic() It expects no spaces at the beginning or end of...
const std::string & GetPathSeparator()
void WriteSchemaList(std::list< SchemaRuleMap_t > &rules, const std::string &listName, std::ostream &output)
Write schema rules.
std::map< std::string, ROOT::Internal::TSchemaType > MembersTypeMap_t
void WriteReadRuleFunc(SchemaRuleMap_t &rule, int index, std::string &mappedName, MembersTypeMap_t &members, std::ostream &output)
Write the conversion function for Read rule, the function name is being written to rule["funcname"].
R__EXTERN SchemaRuleClassMap_t gReadRules
bool HasValidDataMembers(SchemaRuleMap_t &rule, MembersTypeMap_t &members, std::string &error_string)
Check if given rule contains references to valid data members.
void WriteReadRawRuleFunc(SchemaRuleMap_t &rule, int index, std::string &mappedName, MembersTypeMap_t &members, std::ostream &output)
Write the conversion function for ReadRaw rule, the function name is being written to rule["funcname"...
R__EXTERN SchemaRuleClassMap_t gReadRawRules
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
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
char * DemangleName(const char *mangled_name, int &errorCode)
std::string GetNameForIO(const std::string &templateInstanceName, TClassEdit::EModType mode=TClassEdit::kNone, bool *hasChanged=nullptr)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
bool IsSTLBitset(const char *type)
Return true is the name is std::bitset<number> or bitset<number>
if(fPos !=fText.size()) Fail("unexpected trailing content")
constexpr Double_t C()
Velocity of light in .
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.