24#include <unordered_set>
26#include "RConfigure.h"
34#include "clang/AST/ASTContext.h"
35#include "clang/AST/Attr.h"
36#include "clang/AST/CXXInheritance.h"
37#include "clang/AST/Decl.h"
38#include "clang/AST/DeclTemplate.h"
39#include "clang/AST/Mangle.h"
40#include "clang/AST/Type.h"
41#include "clang/AST/TypeVisitor.h"
42#include "clang/Frontend/CompilerInstance.h"
43#include "clang/Lex/HeaderSearch.h"
44#include "clang/Lex/ModuleMap.h"
45#include "clang/Lex/Preprocessor.h"
46#include "clang/Lex/PreprocessorOptions.h"
48#include "clang/Sema/Lookup.h"
49#include "clang/Sema/Sema.h"
50#include "clang/Sema/SemaDiagnostic.h"
52#include "cling/Interpreter/LookupHelper.h"
53#include "cling/Interpreter/Transaction.h"
54#include "cling/Interpreter/Interpreter.h"
55#include "cling/Utils/AST.h"
57#include "llvm/Support/Path.h"
58#include "llvm/Support/FileSystem.h"
63#define strncasecmp _strnicmp
74 llvm::SmallString<256> result_path;
75 llvm::sys::fs::real_path(path, result_path,
true);
76 return result_path.str().str();
83 using DeclsCont_t = TNormalizedCtxt::Config_t::SkipCollection;
100 bool replace =
false);
110static clang::NestedNameSpecifier *AddDefaultParametersNNS(
const clang::ASTContext& Ctx,
111 clang::NestedNameSpecifier* scope,
112 const cling::Interpreter &interpreter,
114 if (!scope)
return nullptr;
116 const clang::Type* scope_type = scope->getAsType();
119 clang::NestedNameSpecifier* outer_scope = scope->getPrefix();
121 outer_scope = AddDefaultParametersNNS(Ctx, outer_scope, interpreter, normCtxt);
124 clang::QualType addDefault =
127 if (addDefault.getTypePtr() != scope_type)
128 return clang::NestedNameSpecifier::Create(Ctx,outer_scope,
130 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());
159static clang::NestedNameSpecifier *ReSubstTemplateArgNNS(
const clang::ASTContext &Ctxt,
160 clang::NestedNameSpecifier *scope,
163 if (!scope)
return nullptr;
165 const clang::Type* scope_type = scope->getAsType();
167 clang::NestedNameSpecifier* outer_scope = scope->getPrefix();
169 outer_scope = ReSubstTemplateArgNNS(Ctxt, outer_scope,
instance);
171 clang::QualType substScope =
174 scope = clang::NestedNameSpecifier::Create(Ctxt,outer_scope,
176 substScope.getTypePtr());
183static bool IsTypeInt(
const clang::Type *
type)
185 const clang::BuiltinType * builtin = llvm::dyn_cast<clang::BuiltinType>(
type->getCanonicalTypeInternal().getTypePtr());
187 return builtin->isInteger();
195static bool IsFieldDeclInt(
const clang::FieldDecl *field)
197 return IsTypeInt(field->getType().getTypePtr());
203static const clang::FieldDecl *GetDataMemberFromAll(
const clang::CXXRecordDecl &cl, llvm::StringRef
what)
205 clang::ASTContext &
C = cl.getASTContext();
206 clang::DeclarationName DName = &
C.Idents.get(
what);
207 auto R = cl.lookup(DName);
208 for (
const clang::NamedDecl *D :
R)
209 if (auto FD =
llvm::dyn_cast<const
clang::FieldDecl>(D))
217static const clang::FieldDecl *GetDataMemberFromAllParents(clang::Sema &SemaR,
const clang::CXXRecordDecl &cl,
const char *
what)
219 clang::DeclarationName DName = &SemaR.Context.Idents.get(
what);
220 clang::LookupResult
R(SemaR, DName, clang::SourceLocation(),
221 clang::Sema::LookupOrdinaryName,
222 clang::Sema::ForExternalRedeclaration);
223 SemaR.LookupInSuper(
R, &
const_cast<clang::CXXRecordDecl&
>(cl));
226 return llvm::dyn_cast<const clang::FieldDecl>(
R.getFoundDecl());
230cling::LookupHelper::DiagSetting ToLHDS(
bool wantDiags) {
232 ? cling::LookupHelper::WithDiagnostics
233 : cling::LookupHelper::NoDiagnostics;
240namespace TMetaUtils {
249 Error(
"TNormalizedCtxt::AddTemplAndNargsToKeep",
250 "Tring to specify a number of template arguments to keep for a null pointer. Exiting without assigning any value.\n");
254 const clang::ClassTemplateDecl* canTempl = templ->getCanonicalDecl();
258 const std::string templateName (canTempl->getNameAsString());
259 const std::string i_str (std::to_string(i));
261 Error(
"TNormalizedCtxt::AddTemplAndNargsToKeep",
262 "Tring to specify for template %s %s arguments to keep, while before this number was %s\n",
263 canTempl->getNameAsString().c_str(),
265 previousArgsToKeep.c_str());
276 const clang::ClassTemplateDecl* constTempl = templ->getCanonicalDecl();
320 const std::string &normalizedName)
324 if (normalizedName.find(
"Double32_t") != std::string::npos
325 || normalizedName.find(
"Float16_t") != std::string::npos)
327 std::unique_ptr<clang::MangleContext> mangleCtx(rDecl->getASTContext().createMangleContext());
328 std::string mangledName;
330 llvm::raw_string_ostream sstr(mangledName);
331 if (
const clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(rDecl)) {
332 mangleCtx->mangleCXXRTTI(clang::QualType(TD->getTypeForDecl(), 0), sstr);
335 if (!mangledName.empty()) {
338 if (mangledName[0] ==
'\01')
339 mangledName.erase(0, 1);
341 if (!errDemangle && demangledTIName) {
342 static const char typeinfoNameFor[] =
" `RTTI Type Descriptor'";
343 if (strstr(demangledTIName, typeinfoNameFor)) {
344 std::string demangledName = demangledTIName;
345 demangledName.erase(demangledName.end() - strlen(typeinfoNameFor), demangledName.end());
348 if (!errDemangle && demangledTIName) {
349 static const char typeinfoNameFor[] =
"typeinfo for ";
350 if (!strncmp(demangledTIName, typeinfoNameFor, strlen(typeinfoNameFor))) {
351 std::string demangledName = demangledTIName + strlen(typeinfoNameFor);
353 free(demangledTIName);
354 return demangledName;
358 "Demangled typeinfo name '%s' does not contain `RTTI Type Descriptor'\n",
362 "Demangled typeinfo name '%s' does not start with 'typeinfo for'\n",
367 free(demangledTIName);
379 const clang::RecordDecl *decl,
382 bool rRequestNoInputOperator,
383 bool rRequestOnlyTClass,
384 int rRequestedVersionNumber,
385 int rRequestedRNTupleSplitMode,
386 const cling::Interpreter &interpreter,
407 const clang::Type *requestedType,
408 const clang::RecordDecl *decl,
409 const char *requestName,
410 unsigned int nTemplateArgsToSkip,
413 bool rRequestNoInputOperator,
414 bool rRequestOnlyTClass,
415 int rRequestVersionNumber,
416 int rRequestedRNTupleSplitMode,
417 const cling::Interpreter &interpreter,
422 fRequestStreamerInfo(rStreamerInfo),
423 fRequestNoStreamer(rNoStreamer),
424 fRequestNoInputOperator(rRequestNoInputOperator),
425 fRequestOnlyTClass(rRequestOnlyTClass),
426 fRequestedVersionNumber(rRequestVersionNumber),
427 fRequestedRNTupleSplitMode(rRequestedRNTupleSplitMode)
437 "Could not remove the requested template arguments.\n");
447 const clang::Type *requestedType,
448 const clang::RecordDecl *decl,
449 const char *requestName,
452 bool rRequestNoInputOperator,
453 bool rRequestOnlyTClass,
454 int rRequestVersionNumber,
455 int rRequestedRNTupleSplitMode,
456 const cling::Interpreter &interpreter,
461 fRequestStreamerInfo(rStreamerInfo),
462 fRequestNoStreamer(rNoStreamer),
463 fRequestNoInputOperator(rRequestNoInputOperator),
464 fRequestOnlyTClass(rRequestOnlyTClass),
465 fRequestedVersionNumber(rRequestVersionNumber),
466 fRequestedRNTupleSplitMode(rRequestedRNTupleSplitMode)
482 const clang::RecordDecl *decl,
483 const char *requestName,
486 bool rRequestNoInputOperator,
487 bool rRequestOnlyTClass,
488 int rRequestVersionNumber,
489 int rRequestedRNTupleSplitMode,
490 const cling::Interpreter &interpreter,
495 fRequestStreamerInfo(rStreamerInfo),
496 fRequestNoStreamer(rNoStreamer),
497 fRequestNoInputOperator(rRequestNoInputOperator),
498 fRequestOnlyTClass(rRequestOnlyTClass),
499 fRequestedVersionNumber(rRequestVersionNumber),
500 fRequestedRNTupleSplitMode(rRequestedRNTupleSplitMode)
510 if (requestName && requestName[0]) {
525 ExistingTypeCheck_t existingTypeCheck,
526 AutoParse_t autoParse,
527 bool *shuttingDownPtr,
528 const int* pgDebug ):
529 fInterpreter(&interpreter),fNormalizedCtxt(&normCtxt),
530 fExistingTypeCheck(existingTypeCheck),
531 fAutoParse(autoParse),
532 fInterpreterIsShuttingDownPtr(shuttingDownPtr),
544 if (tname.empty())
return false;
554 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
555 clang::QualType t = lh.findType(nameLong, ToLHDS(
WantDiags()));
558 if (!
dest.isNull() && (
dest != t)) {
561 dest.getAsStringInternal(nameLong,
fInterpreter->getCI()->getASTContext().getPrintingPolicy());
569 const std::string &nameLong)
571 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
572 clang::QualType t = lh.findType(nondef.c_str(), ToLHDS(
WantDiags()));
575 if (!
dest.isNull() && (
dest != t) &&
576 nameLong == t.getAsString(
fInterpreter->getCI()->getASTContext().getPrintingPolicy()))
586 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
587 const clang::Decl *scope = lh.findScope(base.c_str(), ToLHDS(
WantDiags()),
nullptr);
594 const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(scope);
595 isInlined = nsdecl && nsdecl->isInline();
607 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.SuppressScope =
true;
647 if (strncmp(
result.c_str(),
"const ", 6) == 0) {
650 if (dropstd && strncmp(
result.c_str()+
offset,
"std::", 5) == 0) {
653 for(
unsigned int i = 1; i<
result.length(); ++i) {
656 if (dropstd &&
result.compare(i,5,
"std::",5) == 0) {
665 }
else if ( (i+1) <
result.length() &&
703 clang::QualType toSkip = lh.findType(
name, cling::LookupHelper::WithDiagnostics);
704 if (
const clang::Type* T = toSkip.getTypePtr()) {
705 const clang::TypedefType *
tt = llvm::dyn_cast<clang::TypedefType>(T);
707 clang::Decl* D =
tt->getDecl();
708 fConfig.m_toSkip.insert(D);
710 clang::QualType canon = toSkip->getCanonicalTypeInternal();
711 fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),T));
713 fTypeWithAlternative.insert(T);
726 keepTypedef(lh,
"Double32_t");
727 keepTypedef(lh,
"Float16_t");
728 keepTypedef(lh,
"Long64_t",
true);
729 keepTypedef(lh,
"ULong64_t",
true);
731 clang::QualType toSkip = lh.findType(
"string", cling::LookupHelper::WithDiagnostics);
732 if (!toSkip.isNull()) {
733 if (
const clang::TypedefType* TT
734 = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
735 fConfig.m_toSkip.insert(TT->getDecl());
737 toSkip = lh.findType(
"std::string", cling::LookupHelper::WithDiagnostics);
738 if (!toSkip.isNull()) {
739 if (
const clang::TypedefType* TT
740 = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
741 fConfig.m_toSkip.insert(TT->getDecl());
743 clang::QualType canon = toSkip->getCanonicalTypeInternal();
744 fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),toSkip.getTypePtr()));
755 return (cl.getKind() == clang::Decl::ClassTemplatePartialSpecialization
756 || cl.getKind() == clang::Decl::ClassTemplateSpecialization);
763 const cling::Interpreter& interp)
765 clang::Sema* S = &interp.getSema();
766 const clang::NamedDecl* ND = cling::utils::Lookup::Named(S,
name, cl);
767 if (ND == (clang::NamedDecl*)-1)
768 return (clang::FunctionDecl*)-1;
769 return llvm::dyn_cast_or_null<clang::FunctionDecl>(ND);
775const clang::CXXRecordDecl *
777 bool ,
const clang::Type** resultType)
779 const cling::LookupHelper& lh = interp.getLookupHelper();
782 const clang::CXXRecordDecl *
result
783 = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
784 (lh.findScope(
name, cling::LookupHelper::NoDiagnostics, resultType));
786 std::string std_name(
"std::");
790 result = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
791 (lh.findScope(std_name, cling::LookupHelper::NoDiagnostics, resultType));
801 clang::QualType qType(cl->getTypeForDecl(),0);
809 clang::Sema& S = interp.getCI()->getSema();
812 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interp));
813 return S.RequireCompleteType(Loc, Type, clang::diag::err_incomplete_type);
819 const clang::CXXRecordDecl *context,
const cling::Interpreter &interp)
825 if (!cl->getDefinition() || !cl->isCompleteDefinition()) {
829 if (!CheckDefinition(cl, context) || !CheckDefinition(base, context)) {
833 if (!base->hasDefinition()) {
837 return cl->isDerivedFrom(base);
849 const clang::NamedDecl *base
853 return IsBase(CRD, llvm::dyn_cast<clang::CXXRecordDecl>( base ),
854 llvm::dyn_cast<clang::CXXRecordDecl>(
m.getDeclContext()),interp);
862 const clang::NamedDecl &forcontext,
863 const clang::QualType &qti,
864 const char *R__t,
int rwmode,
865 const cling::Interpreter &interp,
868 static const clang::CXXRecordDecl *TObject_decl
871 kBIT_ISTOBJECT = 0x10000000,
872 kBIT_HASSTREAMER = 0x20000000,
873 kBIT_ISSTRING = 0x40000000,
875 kBIT_ISPOINTER = 0x00001000,
876 kBIT_ISFUNDAMENTAL = 0x00000020,
877 kBIT_ISENUM = 0x00000008
880 const clang::Type &ti( * qti.getTypePtr() );
890 clang::CXXRecordDecl *cxxtype = rawtype->getAsCXXRecordDecl() ;
892 int isTObj = cxxtype && (
IsBase(cxxtype,TObject_decl,
nullptr,interp) || rawname ==
"TObject");
896 if (ti.isPointerType()) kase |= kBIT_ISPOINTER;
897 if (rawtype->isFundamentalType()) kase |= kBIT_ISFUNDAMENTAL;
898 if (rawtype->isEnumeralType()) kase |= kBIT_ISENUM;
901 if (isTObj) kase |= kBIT_ISTOBJECT;
902 if (isStre) kase |= kBIT_HASSTREAMER;
903 if (tiName ==
"string") kase |= kBIT_ISSTRING;
904 if (tiName ==
"string*") kase |= kBIT_ISSTRING;
908 tcl =
" internal error in rootcling ";
913 if (R__t) finalString <<
" " << tiName <<
" " << R__t <<
";" << std::endl;
916 case kBIT_ISFUNDAMENTAL:
918 finalString <<
" R__b >> " << R__t <<
";" << std::endl;
921 case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
923 finalString <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl;
932 finalString <<
" Int_t readtemp;" << std::endl
933 <<
" R__b >> readtemp;" << std::endl
934 <<
" " << R__t <<
" = static_cast<" << tiName <<
">(readtemp);" << std::endl;
937 case kBIT_HASSTREAMER:
938 case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
940 finalString <<
" " << R__t <<
".Streamer(R__b);" << std::endl;
943 case kBIT_HASSTREAMER|kBIT_ISPOINTER:
946 finalString <<
" if (R__b.GetInfo() && R__b.GetInfo()->GetOldVersion()<=3) {" << std::endl;
947 if (cxxtype && cxxtype->isAbstract()) {
948 finalString <<
" R__ASSERT(0);// " << objType <<
" is abstract. We assume that older file could not be produced using this streaming method." << std::endl;
950 finalString <<
" " << R__t <<
" = new " << objType <<
";" << std::endl
951 <<
" " << R__t <<
"->Streamer(R__b);" << std::endl;
953 finalString <<
" } else {" << std::endl
954 <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl
955 <<
" }" << std::endl;
960 finalString <<
" {TString R__str;" << std::endl
961 <<
" R__str.Streamer(R__b);" << std::endl
962 <<
" " << R__t <<
" = R__str.Data();}" << std::endl;
965 case kBIT_ISSTRING|kBIT_ISPOINTER:
967 finalString <<
" {TString R__str;" << std::endl
968 <<
" R__str.Streamer(R__b);" << std::endl
969 <<
" " << R__t <<
" = new string(R__str.Data());}" << std::endl;
974 finalString <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl;
979 finalString <<
" R__b.StreamObject(&" << R__t <<
"," << tcl <<
");" << std::endl;
987 case kBIT_ISFUNDAMENTAL:
988 case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
990 finalString <<
" R__b << " << R__t <<
";" << std::endl;
995 finalString <<
" { void *ptr_enum = (void*)&" << R__t <<
";\n";
996 finalString <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_enum); }" << std::endl;
999 case kBIT_HASSTREAMER:
1000 case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
1001 if (!R__t)
return 0;
1002 finalString <<
" ((" << objType <<
"&)" << R__t <<
").Streamer(R__b);" << std::endl;
1005 case kBIT_HASSTREAMER|kBIT_ISPOINTER:
1006 if (!R__t)
return 1;
1007 finalString <<
" R__b.WriteObjectAny(" << R__t <<
"," << tcl <<
");" << std::endl;
1011 if (!R__t)
return 0;
1012 finalString <<
" {TString R__str(" << R__t <<
".c_str());" << std::endl
1013 <<
" R__str.Streamer(R__b);};" << std::endl;
1016 case kBIT_ISSTRING|kBIT_ISPOINTER:
1017 if (!R__t)
return 0;
1018 finalString <<
" {TString R__str(" << R__t <<
"->c_str());" << std::endl
1019 <<
" R__str.Streamer(R__b);}" << std::endl;
1022 case kBIT_ISPOINTER:
1023 if (!R__t)
return 1;
1024 finalString <<
" R__b.WriteObjectAny(" << R__t <<
"," << tcl <<
");" << std::endl;
1028 if (!R__t)
return 1;
1029 finalString <<
" R__b.StreamObject((" << objType <<
"*)&" << R__t <<
"," << tcl <<
");" << std::endl;
1041 clang::CXXRecordDecl* ncCl =
const_cast<clang::CXXRecordDecl*
>(cl);
1044 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
1046 if (
auto* Ctor = interpreter.getCI()->getSema().LookupDefaultConstructor(ncCl)) {
1047 if (Ctor->getAccess() == clang::AS_public && !Ctor->isDeleted()) {
1060 const char *typeOfArg,
1061 const clang::CXXRecordDecl *expectedArgType,
1062 const cling::Interpreter& interpreter)
1064 if (typeOfArg && !expectedArgType) {
1065 const cling::LookupHelper& lh = interpreter.getLookupHelper();
1068 clang::QualType instanceType = lh.findType(typeOfArg, cling::LookupHelper::WithDiagnostics);
1069 if (!instanceType.isNull())
1070 expectedArgType = instanceType->getAsCXXRecordDecl();
1073 if (!expectedArgType)
1074 return EIOCtorCategory::kAbsent;
1077 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
1078 for (
auto iter = cl->ctor_begin(), end = cl->ctor_end(); iter != end; ++iter)
1080 if ((iter->getAccess() != clang::AS_public) || (iter->getNumParams() != 1))
1084 clang::QualType argType((*iter->param_begin())->getType());
1085 argType = argType.getDesugaredType(cl->getASTContext());
1087 auto ioCtorCategory = EIOCtorCategory::kAbsent;
1088 if (argType->isPointerType()) {
1089 ioCtorCategory = EIOCtorCategory::kIOPtrType;
1090 argType = argType->getPointeeType();
1091 }
else if (argType->isReferenceType()) {
1092 ioCtorCategory = EIOCtorCategory::kIORefType;
1093 argType = argType.getNonReferenceType();
1097 argType = argType.getDesugaredType(cl->getASTContext());
1098 const clang::CXXRecordDecl *argDecl = argType->getAsCXXRecordDecl();
1100 if (argDecl->getCanonicalDecl() == expectedArgType->getCanonicalDecl()) {
1101 return ioCtorCategory;
1104 std::string realArg = argType.getAsString();
1105 std::string clarg(
"class ");
1107 if (realArg == clarg)
1108 return ioCtorCategory;
1112 return EIOCtorCategory::kAbsent;
1121 const cling::Interpreter& interpreter)
1123 const char *arg = ioctortype.
GetName();
1125 if (!ioctortype.
GetType() && (!arg || !arg[0])) {
1138 const char *method,
const char *
proto,
1139 const cling::Interpreter &interp,
1142 const clang::FunctionDecl* funcD
1143 = interp.getLookupHelper().findFunctionProto(cinfo, method,
proto,
1144 diagnose ? cling::LookupHelper::WithDiagnostics
1145 : cling::LookupHelper::NoDiagnostics);
1147 return llvm::dyn_cast<const clang::CXXMethodDecl>(funcD);
1156 namespace TMetaUtils {
1159 const cling::LookupHelper& lh = interp.getLookupHelper();
1162 clang::QualType instanceType = lh.findType(type_of_arg, cling::LookupHelper::WithDiagnostics);
1163 if (!instanceType.isNull())
1164 fArgType = instanceType->getAsCXXRecordDecl();
1178 const cling::Interpreter &interp)
1180 if (cl->isAbstract())
return false;
1182 for (
auto & ctorType : ctorTypes) {
1186 if (EIOCtorCategory::kAbsent == ioCtorCat)
1189 std::string
proto( ctorType.GetName() );
1190 bool defaultCtor =
proto.empty();
1196 if (EIOCtorCategory::kIOPtrType == ioCtorCat) {
1198 }
else if (EIOCtorCategory::kIORefType == ioCtorCat) {
1202 arg +=
")nullptr )";
1205 const clang::CXXMethodDecl *method
1207 cling::LookupHelper::NoDiagnostics);
1208 if (method && method->getAccess() != clang::AS_public) {
1222 const cling::Interpreter& interp)
1224 if (!cl)
return false;
1226 if (cl->hasUserDeclaredDestructor()) {
1228 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interp));
1229 clang::CXXDestructorDecl *
dest = cl->getDestructor();
1231 return (
dest->getAccess() == clang::AS_public);
1243 const char *methodname,
1245 const cling::Interpreter &interp,
1248 const clang::CXXMethodDecl *method
1250 diagnose ? cling::LookupHelper::WithDiagnostics
1251 : cling::LookupHelper::NoDiagnostics);
1252 return (method && method->getAccess() == clang::AS_public);
1263 const char *
proto =
"TDirectory*";
1264 const char *
name =
"DirectoryAutoAdd";
1278 const char *
proto =
"TCollection*,TFileMergeInfo*";
1279 const char *
name =
"Merge";
1292 const char *
proto =
"TCollection*";
1293 const char *
name =
"Merge";
1308 const char *
proto =
"TFileMergeInfo*";
1309 const char *
name =
"ResetAfterMerge";
1319 const clang::CXXRecordDecl* clxx,
1320 const cling::Interpreter &interp,
1323 static const char *
proto =
"TBuffer&";
1325 const clang::CXXMethodDecl *method
1327 cling::LookupHelper::NoDiagnostics);
1328 const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1330 return (method && method->getDeclContext() == clxx_as_context
1338 const clang::CXXRecordDecl* clxx,
1339 const cling::Interpreter &interp,
1342 static const char *
proto =
"TBuffer&,TClass*";
1344 const clang::CXXMethodDecl *method
1346 cling::LookupHelper::NoDiagnostics);
1347 const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1349 return (method && method->getDeclContext() == clxx_as_context
1379 clang::QualType qualType(&
type,0);
1411 llvm::raw_string_ostream stream(qual_name);
1412 clang::PrintingPolicy policy( cl.getASTContext().getPrintingPolicy() );
1413 policy.SuppressTagKeyword =
true;
1414 policy.SuppressUnwrittenScope =
true;
1416 cl.getNameForDiagnostic(stream,policy,
true);
1419 if ( qual_name ==
"(anonymous " || qual_name ==
"(unnamed" ) {
1420 size_t pos = qual_name.find(
':');
1421 qual_name.erase(0,pos+2);
1437 const clang::Type* declType ( recordDecl.getTypeForDecl() );
1438 clang::QualType qualType(declType,0);
1472 std::stringstream dims;
1473 std::string typenameStr;
1475 const clang::ASTContext& astContext = cl.getASTContext();
1478 for(clang::RecordDecl::field_iterator field_iter = cl.field_begin(), end = cl.field_end();
1486 typenameStr.clear();
1490 clang::QualType fieldType(field_iter->getType());
1491 if (fieldType->isConstantArrayType()) {
1492 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(fieldType.getTypePtr());
1494 dims <<
"[" << arrayType->getSize().getLimitedValue() <<
"]";
1495 fieldType = arrayType->getElementType();
1496 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1506 for(clang::CXXRecordDecl::base_class_const_iterator iter = cl.bases_begin(), end = cl.bases_end();
1509 std::string basename( iter->getType()->getAsCXXRecordDecl()->getNameAsString() );
1519 const cling::Interpreter &interp,
1522 return interp.getLookupHelper().findFunctionProto(cinfo, method,
proto,
1523 diagnose ? cling::LookupHelper::WithDiagnostics
1524 : cling::LookupHelper::NoDiagnostics);
1558 clang::SourceLocation sourceLocation = decl->getLocation();
1559 clang::SourceManager& sourceManager = decl->getASTContext().getSourceManager();
1561 if (!sourceLocation.isValid() ) {
1565 if (!sourceLocation.isFileID()) {
1566 sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
1569 if (sourceLocation.isValid() && sourceLocation.isFileID()) {
1570 return sourceManager.getLineNumber(sourceManager.getFileID(sourceLocation),sourceManager.getFileOffset(sourceLocation));
1583 while (llvm::isa<clang::PointerType>(instanceType.getTypePtr())
1584 || llvm::isa<clang::ReferenceType>(instanceType.getTypePtr()))
1586 instanceType = instanceType->getPointeeType();
1589 const clang::ElaboratedType* etype
1590 = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
1592 instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
1605 const clang::CXXRecordDecl* clxx = instanceType->getAsCXXRecordDecl();
1606 if (clxx && clxx->getTemplateSpecializationKind() != clang::TSK_Undeclared) {
1608 const clang::TemplateSpecializationType* TST
1609 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
1616 for (
const clang::TemplateArgument &
TA : TST->template_arguments()) {
1617 if (
TA.getKind() == clang::TemplateArgument::Type) {
1629 const cling::Interpreter &interp,
1632 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1633 if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return false;
1635 clang::QualType instanceType = interp.getLookupHelper().findType(cl.
GetNormalizedName(),
1636 cling::LookupHelper::WithDiagnostics);
1637 if (instanceType.isNull()) {
1650 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(attribute);
1655 attrString = annAttr->getAnnotation().str();
1664 size_t substrFound (attributeStr.find(propNames::separator));
1665 if (substrFound==std::string::npos) {
1669 size_t EndPart1 = attributeStr.find_first_of(propNames::separator) ;
1670 attrName = attributeStr.substr(0, EndPart1);
1671 const int separatorLength(propNames::separator.
size());
1672 attrValue = attributeStr.substr(EndPart1 + separatorLength);
1680 std::string attrString;
1682 if (0!=ret)
return ret;
1690 const std::string& propName,
1691 std::string& propValue)
1693 for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1694 attrIt!=decl.attr_end();++attrIt){
1695 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1696 if (!annAttr)
continue;
1698 llvm::StringRef attribute = annAttr->getAnnotation();
1699 std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1700 if (split.first != propName.c_str())
continue;
1702 propValue = split.second.str();
1713 const std::string& propName,
1716 for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1717 attrIt!=decl.attr_end();++attrIt){
1718 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1719 if (!annAttr)
continue;
1721 llvm::StringRef attribute = annAttr->getAnnotation();
1722 std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1723 if (split.first != propName.c_str())
continue;
1725 return split.second.getAsInteger(10,propValue);
1736 const clang::CXXRecordDecl *decl,
1737 const cling::Interpreter &interp,
1740 bool& needCollectionProxy)
1744 std::string mappedname;
1746 std::string csymbol = classname;
1754 csymbol.insert(0,
"::");
1760 bool isStd = TMetaUtils::IsStdClass(*decl);
1761 const cling::LookupHelper& lh = interp.getLookupHelper();
1762 bool isString = TMetaUtils::IsOfType(*decl,
"std::string",lh);
1764 bool isStdNotString = isStd && !isString;
1766 finalString <<
"namespace ROOT {" <<
"\n";
1770 finalString <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();\n"
1771 <<
" static void " << mappedname.c_str() <<
"_TClassManip(TClass*);\n";
1777 finalString <<
" static void *new_" << mappedname.c_str() <<
"(void *p = nullptr);" <<
"\n";
1781 finalString <<
" static void *newArray_";
1782 finalString << mappedname.c_str();
1783 finalString <<
"(Long_t size, void *p);";
1784 finalString <<
"\n";
1789 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";
1792 finalString <<
" static void directoryAutoAdd_" << mappedname.c_str() <<
"(void *obj, TDirectory *dir);" <<
"\n";
1795 finalString <<
" static void streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj);" <<
"\n";
1798 finalString <<
" static void conv_streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj, const TClass*);" <<
"\n";
1801 finalString <<
" static Long64_t merge_" << mappedname.c_str() <<
"(void *obj, TCollection *coll,TFileMergeInfo *info);" <<
"\n";
1804 finalString <<
" static void reset_" << mappedname.c_str() <<
"(void *obj, TFileMergeInfo *info);" <<
"\n";
1811 ROOT::SchemaRuleClassMap_t::iterator rulesIt1 =
ROOT::gReadRules.find( classname.c_str() );
1812 ROOT::SchemaRuleClassMap_t::iterator rulesIt2 =
ROOT::gReadRawRules.find( classname.c_str() );
1823 finalString <<
"\n // Schema evolution read functions\n";
1824 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt1->second.begin();
1825 while( rIt != rulesIt1->second.end() ) {
1831 std::string error_string;
1833 Warning(
nullptr,
"%s", error_string.c_str());
1834 rIt = rulesIt1->second.erase(rIt);
1842 if( rIt->find(
"code" ) != rIt->end() ) {
1858 finalString <<
"\n // Schema evolution read raw functions\n";
1859 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt2->second.begin();
1860 while( rIt != rulesIt2->second.end() ) {
1866 std::string error_string;
1868 Warning(
nullptr,
"%s", error_string.c_str());
1869 rIt = rulesIt2->second.erase(rIt);
1877 if( rIt->find(
"code" ) == rIt->end() )
1885 finalString <<
"\n" <<
" // Function generating the singleton type initializer" <<
"\n";
1887 finalString <<
" static TGenericClassInfo *GenerateInitInstanceLocal(const " << csymbol <<
"*)" <<
"\n" <<
" {" <<
"\n";
1889 finalString <<
" " << csymbol <<
" *ptr = nullptr;" <<
"\n";
1893 finalString <<
" static ::TVirtualIsAProxy* isa_proxy = new ::TInstrumentedIsAProxy< " << csymbol <<
" >(nullptr);" <<
"\n";
1896 finalString <<
" static ::TVirtualIsAProxy* isa_proxy = new ::TIsAProxy(typeid(" << csymbol <<
"));" <<
"\n";
1898 finalString <<
" static ::ROOT::TGenericClassInfo " <<
"\n" <<
" instance(\"" << classname.c_str() <<
"\", ";
1901 finalString << csymbol <<
"::Class_Version(), ";
1903 finalString <<
"2, ";
1905 finalString <<
"-2, ";
1911 static const char *versionFunc =
"GetClassVersion";
1915 std::string
proto = classname +
"*";
1916 const clang::Decl* ctxt = llvm::dyn_cast<clang::Decl>((*cl).getDeclContext());
1917 const clang::FunctionDecl *methodinfo
1919 interp, cling::LookupHelper::NoDiagnostics);
1927 finalString <<
"GetClassVersion< ";
1928 finalString << classname.c_str();
1929 finalString <<
" >(), ";
1938 for (
unsigned int i=0; i<
filename.length(); i++) {
1943 <<
"," <<
"\n" <<
" typeid(" << csymbol
1944 <<
"), ::ROOT::Internal::DefineBehavior(ptr, ptr)," <<
"\n" <<
" ";
1947 finalString <<
"&" << csymbol <<
"::Dictionary, ";
1949 finalString <<
"&" << mappedname <<
"_Dictionary, ";
1953 TClassTable__kHasCustomStreamerMember = 0x10
1958 rootflag = rootflag | TClassTable__kHasCustomStreamerMember;
1960 finalString <<
"isa_proxy, " << rootflag <<
"," <<
"\n" <<
" sizeof(" << csymbol <<
") );" <<
"\n";
1962 finalString <<
" instance.SetNew(&new_" << mappedname.c_str() <<
");" <<
"\n";
1964 finalString <<
" instance.SetNewArray(&newArray_" << mappedname.c_str() <<
");" <<
"\n";
1967 finalString <<
" instance.SetDelete(&delete_" << mappedname.c_str() <<
");" <<
"\n" <<
" instance.SetDeleteArray(&deleteArray_" << mappedname.c_str() <<
");" <<
"\n" <<
" instance.SetDestructor(&destruct_" << mappedname.c_str() <<
");" <<
"\n";
1970 finalString <<
" instance.SetDirectoryAutoAdd(&directoryAutoAdd_" << mappedname.c_str() <<
");" <<
"\n";
1974 finalString <<
" instance.SetStreamerFunc(&streamer_" << mappedname.c_str() <<
");" <<
"\n";
1978 finalString <<
" instance.SetConvStreamerFunc(&conv_streamer_" << mappedname.c_str() <<
");" <<
"\n";
1981 finalString <<
" instance.SetMerge(&merge_" << mappedname.c_str() <<
");" <<
"\n";
1984 finalString <<
" instance.SetResetAfterMerge(&reset_" << mappedname.c_str() <<
");" <<
"\n";
1987 finalString <<
" instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" <<
"Pushback" <<
"<Internal::TStdBitsetHelper< " << classname.c_str() <<
" > >()));" <<
"\n";
1989 needCollectionProxy =
true;
1990 }
else if (stl != 0 &&
1993 int idx = classname.find(
"<");
1995 const char* methodTCP =
nullptr;
2001 methodTCP=
"Pushback";
2004 methodTCP=
"Pushfront";
2010 methodTCP=
"MapInsert";
2022 finalString <<
" instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP <<
"< " << classNameForIO.c_str() <<
" >()));" <<
"\n";
2024 needCollectionProxy =
true;
2032 finalString <<
"\n" <<
" instance.AdoptAlternate(::ROOT::AddClassAlternate(\""
2039 finalString <<
"\n" <<
" instance.AdoptAlternate(::ROOT::AddClassAlternate(\""
2049 finalString <<
"\n" <<
" ::ROOT::Internal::TSchemaHelper* rule;" <<
"\n";
2053 finalString <<
"\n" <<
" // the io read rules" <<
"\n" <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrules(" << rulesIt1->second.size() <<
");" <<
"\n";
2055 finalString <<
" instance.SetReadRules( readrules );" <<
"\n";
2059 finalString <<
"\n" <<
" // the io read raw rules" <<
"\n" <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrawrules(" << rulesIt2->second.size() <<
");" <<
"\n";
2061 finalString <<
" instance.SetReadRawRules( readrawrules );" <<
"\n";
2064 finalString <<
" return &instance;" <<
"\n" <<
" }" <<
"\n";
2068 finalString <<
" TGenericClassInfo *GenerateInitInstance(const " << csymbol <<
"*)" <<
"\n" <<
" {\n return GenerateInitInstanceLocal(static_cast<" << csymbol <<
"*>(nullptr));\n }" <<
"\n";
2071 finalString <<
" // Static variable to force the class initialization" <<
"\n";
2075 finalString <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstanceLocal(static_cast<const " << csymbol <<
"*>(nullptr)); R__UseDummy(_R__UNIQUE_DICT_(Init));" <<
"\n";
2078 finalString <<
"\n" <<
" // Dictionary for non-ClassDef classes" <<
"\n"
2079 <<
" static TClass *" << mappedname <<
"_Dictionary() {\n"
2080 <<
" TClass* theClass ="
2081 <<
"::ROOT::GenerateInitInstanceLocal(static_cast<const " << csymbol <<
"*>(nullptr))->GetClass();\n"
2082 <<
" " << mappedname <<
"_TClassManip(theClass);\n";
2083 finalString <<
" return theClass;\n";
2084 finalString <<
" }\n\n";
2088 std::string manipString;
2089 std::string attribute_s;
2090 std::string attrName, attrValue;
2092 bool attrMapExtracted =
false;
2093 if (decl->hasAttrs()){
2095 for (clang::Decl::attr_iterator attrIt = decl->attr_begin();
2096 attrIt!=decl->attr_end();++attrIt){
2103 if (attrName ==
"name" ||
2104 attrName ==
"pattern" ||
2105 attrName ==
"rootmap")
continue;
2111 if (!attrMapExtracted){
2112 manipString+=
" theClass->CreateAttributeMap();\n";
2113 manipString+=
" TDictAttributeMap* attrMap( theClass->GetAttributeMap() );\n";
2114 attrMapExtracted=
true;
2116 manipString+=
" attrMap->AddProperty(\""+attrName +
"\",\""+attrValue+
"\");\n";
2122 for(clang::CXXRecordDecl::decl_iterator internalDeclIt = decl->decls_begin();
2123 internalDeclIt != decl->decls_end(); ++internalDeclIt){
2124 if (!(!(*internalDeclIt)->isImplicit()
2125 && (clang::isa<clang::FieldDecl>(*internalDeclIt) ||
2126 clang::isa<clang::VarDecl>(*internalDeclIt))))
continue;
2129 if (!internalDeclIt->hasAttrs())
continue;
2131 attrMapExtracted =
false;
2132 bool memberPtrCreated =
false;
2134 for (clang::Decl::attr_iterator attrIt = internalDeclIt->attr_begin();
2135 attrIt!=internalDeclIt->attr_end();++attrIt){
2143 clang::NamedDecl* namedInternalDecl = clang::dyn_cast<clang::NamedDecl> (*internalDeclIt);
2144 if (!namedInternalDecl) {
2145 TMetaUtils::Error(
nullptr,
"Cannot convert field declaration to clang::NamedDecl");
2148 const std::string memberName(namedInternalDecl->getName());
2149 const std::string cppMemberName =
"theMember_"+memberName;
2152 const std::string dataMemberCreation=
" TDataMember* "+cppMemberName+
" = theClass->GetDataMember(\""+memberName+
"\");\n";
2161 if (attrName == propNames::comment ||
2162 attrName == propNames::iotype ||
2163 attrName == propNames::ioname )
continue;
2165 if (!memberPtrCreated){
2166 manipString+=dataMemberCreation;
2167 memberPtrCreated=
true;
2170 if (!attrMapExtracted){
2171 manipString+=
" "+cppMemberName+
"->CreateAttributeMap();\n";
2172 manipString+=
" TDictAttributeMap* memberAttrMap_"+memberName+
"( theMember_"+memberName+
"->GetAttributeMap() );\n";
2173 attrMapExtracted=
true;
2176 manipString+=
" memberAttrMap_"+memberName+
"->AddProperty(\""+attrName +
"\",\""+attrValue+
"\");\n";
2183 finalString <<
" static void " << mappedname <<
"_TClassManip(TClass* " << (manipString.empty() ?
"":
"theClass") <<
"){\n"
2188 finalString <<
"} // end of namespace ROOT" <<
"\n" <<
"\n";
2198 std::string &clsname,
2199 std::string &nsname,
2200 const clang::CXXRecordDecl *cl)
2210 auto ctxt = cl->getEnclosingNamespaceContext();
2211 while(ctxt && ctxt!=cl && ctxt->isInlineNamespace()) {
2212 ctxt = ctxt->getParent();
2215 const clang::NamedDecl *namedCtxt = llvm::dyn_cast<clang::NamedDecl>(ctxt);
2216 if (namedCtxt && namedCtxt!=cl) {
2217 const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(namedCtxt);
2218 if (nsdecl && !nsdecl->isAnonymousNamespace()) {
2220 clsname.erase (0, nsname.size() + 2);
2232 const clang::DeclContext *ctxt = cl.getDeclContext();
2233 while(ctxt && !ctxt->isNamespace()) {
2234 ctxt = ctxt->getParent();
2248 int closing_brackets = 0;
2252 if (ctxt && ctxt->isNamespace()) {
2254 const clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(ctxt);
2260 out <<
"namespace " << ns->getNameAsString() <<
" {" << std::endl;
2265 return closing_brackets;
2279 clang::TemplateSpecializationKind kind = cl->getTemplateSpecializationKind();
2280 if (kind == clang::TSK_Undeclared ) {
2283 }
else if (kind == clang::TSK_ExplicitSpecialization) {
2297 const char *
name = which;
2298 const char *
proto =
"size_t";
2299 const char *protoPlacement =
"size_t,void*";
2302 const clang::FunctionDecl *operatornew
2305 cling::LookupHelper::NoDiagnostics);
2306 const clang::FunctionDecl *operatornewPlacement
2308 name, protoPlacement, interp,
2309 cling::LookupHelper::NoDiagnostics);
2311 const clang::DeclContext *ctxtnew =
nullptr;
2312 const clang::DeclContext *ctxtnewPlacement =
nullptr;
2315 ctxtnew = operatornew->getParent();
2317 if (operatornewPlacement) {
2318 ctxtnewPlacement = operatornewPlacement->getParent();
2324 operatornewPlacement
2329 ctxtnew = operatornew->getParent();
2331 if (operatornewPlacement) {
2332 ctxtnewPlacement = operatornewPlacement->getParent();
2335 if (!ctxtnewPlacement) {
2343 if (ctxtnew == ctxtnewPlacement) {
2347 const clang::CXXRecordDecl* clnew = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnew);
2348 const clang::CXXRecordDecl* clnewPlacement = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnewPlacement);
2349 if (!clnew && !clnewPlacement) {
2355 if (clnew && !clnewPlacement) {
2359 if (!clnew && clnewPlacement) {
2364 if (clnew->isDerivedFrom(clnewPlacement)) {
2394 const clang::CXXRecordDecl *decl,
2395 const cling::Interpreter &interp,
2401 std::string mappedname;
2419 classname.insert(0,
"::");
2422 finalString <<
"namespace ROOT {" <<
"\n";
2427 finalString <<
" // Wrappers around operator new" <<
"\n";
2428 finalString <<
" static void *new_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" return p ? ";
2430 finalString <<
"new(p) ";
2431 finalString << classname.c_str();
2432 finalString << args;
2433 finalString <<
" : ";
2435 finalString <<
"::new(static_cast<::ROOT::Internal::TOperatorNewHelper*>(p)) ";
2436 finalString << classname.c_str();
2437 finalString << args;
2438 finalString <<
" : ";
2440 finalString <<
"new " << classname.c_str() << args <<
";" <<
"\n";
2441 finalString <<
" }" <<
"\n";
2445 finalString <<
" static void *newArray_";
2446 finalString << mappedname.c_str();
2447 finalString <<
"(Long_t nElements, void *p) {";
2448 finalString <<
"\n";
2449 finalString <<
" return p ? ";
2451 finalString <<
"new(p) ";
2452 finalString << classname.c_str();
2453 finalString <<
"[nElements] : ";
2455 finalString <<
"::new(static_cast<::ROOT::Internal::TOperatorNewHelper*>(p)) ";
2456 finalString << classname.c_str();
2457 finalString <<
"[nElements] : ";
2459 finalString <<
"new ";
2460 finalString << classname.c_str();
2461 finalString <<
"[nElements];";
2462 finalString <<
"\n";
2463 finalString <<
" }";
2464 finalString <<
"\n";
2469 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";
2473 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";
2477 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";
2481 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";
2485 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";
2487 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";
2491 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";
2493 finalString <<
"} // end of namespace ROOT for class " << classname.c_str() <<
"\n" <<
"\n";
2500 const cling::Interpreter &interp,
2507 if (version == 0)
return;
2511 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
2515 for(clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
2521 Internal::RStl::Instance().GenerateTClassFor( iter->getType(), interp, normCtxt);
2526 for(clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
2530 std::string mTypename;
2536 if (!strcmp(shortTypeName,
"string")) {
2548 Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
2558 const clang::Type *rawtype =
m.getType()->getCanonicalTypeInternal().getTypePtr();
2559 if (rawtype->isArrayType()) {
2560 rawtype = rawtype->getBaseElementTypeUnsafe ();
2574 const clang::CXXRecordDecl* CRD = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
2583 if (!funcCV)
return -1;
2586 if (funcCV == (clang::FunctionDecl*)-1)
return 1;
2601 using res_t = std::pair<bool, int>;
2603 const clang::CompoundStmt* FuncBody
2604 = llvm::dyn_cast_or_null<clang::CompoundStmt>(funcCV->getBody());
2606 return res_t{
false, -1};
2607 if (FuncBody->size() != 1) {
2611 return res_t{
false, -1};
2613 const clang::ReturnStmt* RetStmt
2614 = llvm::dyn_cast<clang::ReturnStmt>(FuncBody->body_back());
2616 return res_t{
false, -1};
2617 const clang::Expr* RetExpr = RetStmt->getRetValue();
2623 if (
auto RetRes = RetExpr->getIntegerConstantExpr(funcCV->getASTContext())) {
2624 if (RetRes->isSigned())
2625 return res_t{
true, (
Version_t)RetRes->getSExtValue()};
2626 return res_t{
true, (
Version_t)RetRes->getZExtValue()};
2628 return res_t{
false, -1};
2644 clang::QualType
type =
m.getType();
2647 if (decl)
return TMetaUtils::IsSTLCont(*decl);
2656 clang::QualType
type = base.getType();
2659 if (decl)
return TMetaUtils::IsSTLCont(*decl);
2669 const std::function<
void(
const clang::Module::Header &)> &closure,
2670 bool includeDirectlyUsedModules)
2679 const std::size_t publicHeaderIndex = 4;
2682 const std::size_t maxArrayLength = ((
sizeof module.Headers) / (
sizeof *module.Headers));
2683 static_assert(publicHeaderIndex + 1 == maxArrayLength,
2684 "'Headers' has changed it's size, we need to update publicHeaderIndex");
2689 llvm::SetVector<const clang::Module *> modules;
2690 modules.insert(&module);
2691 for (
size_t i = 0; i < modules.size(); ++i) {
2692 const clang::Module *M = modules[i];
2693 for (
const clang::Module *subModule : M->submodules())
2694 modules.insert(subModule);
2697 for (
const clang::Module *
m : modules) {
2698 if (includeDirectlyUsedModules) {
2699 for (clang::Module *used :
m->DirectUses) {
2704 for (std::size_t i = 0; i < publicHeaderIndex; i++) {
2705 auto &headerList =
m->Headers[i];
2706 for (
const clang::Module::Header &moduleHeader : headerList) {
2707 closure(moduleHeader);
2721 static char t[4096];
2722 static const char* constwd =
"const ";
2723 static const char* constwdend =
"const";
2728 for (s=typeDesc;*s;s++) {
2731 if (lev==0 && *s==
'*')
continue;
2732 if (lev==0 && (strncmp(constwd,s,strlen(constwd))==0
2733 ||strcmp(constwdend,s)==0 ) ) {
2734 s+=strlen(constwd)-1;
2737 if (lev==0 && *s==
' ' && *(s+1)!=
'*') {
p = t;
continue;}
2738 if (
p - t > (
long)
sizeof(t)) {
2739 printf(
"ERROR (rootcling): type name too long for StortTypeName: %s\n",
2752 const cling::Interpreter& interp)
2757 if (!comment.empty() && comment[0] ==
'!')
2760 clang::QualType
type =
m.getType();
2762 if (
type->isReferenceType()) {
2767 std::string mTypeName =
type.getAsString(
m.getASTContext().getPrintingPolicy());
2768 if (!strcmp(mTypeName.c_str(),
"string") || !strcmp(mTypeName.c_str(),
"string*")) {
2771 if (!strcmp(mTypeName.c_str(),
"std::string") || !strcmp(mTypeName.c_str(),
"std::string*")) {
2779 const clang::Type *rawtype =
type.getTypePtr()->getBaseElementTypeUnsafe ();
2781 if (rawtype->isPointerType()) {
2783 clang::QualType pointee;
2784 while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
2786 rawtype = pointee.getTypePtr();
2790 if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2795 const clang::CXXRecordDecl *cxxdecl = rawtype->getAsCXXRecordDecl();
2799 if (version > 0)
return true;
2812 const clang::Type *rawtype =
m.getType().getTypePtr();
2815 clang::QualType pointee;
2816 while ( rawtype->isPointerType() && ((pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull()) && pointee.getTypePtr() != rawtype)
2818 rawtype = pointee.getTypePtr();
2832 if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2836 return rawtype->getAsCXXRecordDecl();
2845 const cling::Interpreter &interp,
2847 std::ostream& dictStream,
2849 bool isGenreflex=
false)
2851 const clang::CXXRecordDecl* decl = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
2853 if (!decl || !decl->isCompleteDefinition()) {
2857 std::string fullname;
2860 Internal::RStl::Instance().GenerateTClassFor(cl.
GetNormalizedName(), llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl()), interp, normCtxt);
2869 (*WriteStreamerFunc)(cl, interp, normCtxt, dictStream, isGenreflex || cl.RequestStreamerInfo());
2871 ROOT::TMetaUtils::Info(
nullptr,
"Class %s: Do not generate Streamer() [*** custom streamer ***]\n",fullname.c_str());
2893 const cling::Interpreter &interpreter,
2896 const clang::ASTContext& Ctx = interpreter.getCI()->getASTContext();
2898 clang::QualType originalType = instanceType;
2902 if (llvm::isa<clang::PointerType>(instanceType.getTypePtr())) {
2904 clang::Qualifiers quals = instanceType.getQualifiers();
2905 clang::QualType newPointee =
AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2906 if (newPointee != instanceType->getPointeeType()) {
2907 instanceType = Ctx.getPointerType(newPointee);
2909 instanceType = Ctx.getQualifiedType(instanceType, quals);
2911 return instanceType;
2916 if (llvm::isa<clang::ReferenceType>(instanceType.getTypePtr())) {
2918 bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(instanceType.getTypePtr());
2919 clang::Qualifiers quals = instanceType.getQualifiers();
2920 clang::QualType newPointee =
AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2922 if (newPointee != instanceType->getPointeeType()) {
2925 instanceType = Ctx.getLValueReferenceType(newPointee);
2927 instanceType = Ctx.getRValueReferenceType(newPointee);
2929 instanceType = Ctx.getQualifiedType(instanceType, quals);
2931 return instanceType;
2935 bool prefix_changed =
false;
2936 clang::NestedNameSpecifier *prefix =
nullptr;
2937 clang::Qualifiers prefix_qualifiers = instanceType.getLocalQualifiers();
2938 const clang::ElaboratedType* etype
2939 = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
2942 prefix = AddDefaultParametersNNS(Ctx, etype->getQualifier(), interpreter, normCtxt);
2943 prefix_changed = prefix != etype->getQualifier();
2944 instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
2950 const clang::TemplateSpecializationType* TST
2951 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
2953 const clang::ClassTemplateSpecializationDecl* TSTdecl
2954 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instanceType.getTypePtr()->getAsCXXRecordDecl());
2966 bool mightHaveChanged =
false;
2967 if (TST && TSTdecl) {
2969 clang::Sema& S = interpreter.getCI()->getSema();
2970 clang::TemplateDecl *Template = TSTdecl->getSpecializedTemplate()->getMostRecentDecl();
2971 clang::TemplateParameterList *Params = Template->getTemplateParameters();
2972 clang::TemplateParameterList::iterator Param = Params->
begin();
2976 unsigned int dropDefault = normCtxt.
GetConfig().DropDefaultArg(*Template);
2978 llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
2979 llvm::SmallVector<clang::TemplateArgument, 4> canonArgs;
2980 llvm::ArrayRef<clang::TemplateArgument> template_arguments = TST->template_arguments();
2981 unsigned int Idecl = 0, Edecl = TSTdecl->getTemplateArgs().size();
2982 unsigned int maxAddArg = TSTdecl->getTemplateArgs().size() - dropDefault;
2983 for (
const clang::TemplateArgument *
I = template_arguments.begin(), *E = template_arguments.end(); Idecl != Edecl;
2984 I != E ? ++
I :
nullptr, ++Idecl, ++Param) {
2988 if (
I->getKind() == clang::TemplateArgument::Template) {
2989 clang::TemplateName templateName =
I->getAsTemplate();
2990 clang::TemplateDecl* templateDecl = templateName.getAsTemplateDecl();
2992 clang::DeclContext* declCtxt = templateDecl->getDeclContext();
2994 if (declCtxt && !templateName.getAsQualifiedTemplateName()){
2995 clang::NamespaceDecl* ns = clang::dyn_cast<clang::NamespaceDecl>(declCtxt);
2996 clang::NestedNameSpecifier* nns;
2998 nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx, ns);
2999 }
else if (clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(declCtxt)) {
3000 nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx,TD,
false );
3003 desArgs.push_back(*
I);
3006 clang::TemplateName UnderlyingTN(templateDecl);
3007 if (clang::UsingShadowDecl *USD = templateName.getAsUsingShadowDecl())
3008 UnderlyingTN = clang::TemplateName(USD);
3009 clang::TemplateName templateNameWithNSS ( Ctx.getQualifiedTemplateName(nns,
false, UnderlyingTN) );
3010 desArgs.push_back(clang::TemplateArgument(templateNameWithNSS));
3011 mightHaveChanged =
true;
3017 if (
I->getKind() != clang::TemplateArgument::Type) {
3018 desArgs.push_back(*
I);
3022 clang::QualType SubTy =
I->getAsType();
3031 if (SubTy != newSubTy) {
3032 mightHaveChanged =
true;
3033 desArgs.push_back(clang::TemplateArgument(newSubTy));
3035 desArgs.push_back(*
I);
3038 }
else if (!isStdDropDefault && Idecl < maxAddArg) {
3040 mightHaveChanged =
true;
3042 const clang::TemplateArgument& templateArg
3043 = TSTdecl->getTemplateArgs().get(Idecl);
3044 if (templateArg.getKind() != clang::TemplateArgument::Type) {
3045 desArgs.push_back(templateArg);
3048 clang::QualType SubTy = templateArg.getAsType();
3050 clang::SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3051 clang::SourceLocation RAngleLoc = TSTdecl->getSourceRange().getBegin();
3053 clang::TemplateTypeParmDecl *TTP = llvm::dyn_cast<clang::TemplateTypeParmDecl>(*Param);
3056 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
3057 bool HasDefaultArgs;
3058 clang::TemplateArgumentLoc ArgType = S.SubstDefaultTemplateArgumentIfAvailable(
3068 if (ArgType.getArgument().isNull()
3069 || ArgType.getArgument().getKind() != clang::TemplateArgument::Type) {
3071 "Template parameter substitution failed for %s around %s\n",
3072 instanceType.getAsString().c_str(), SubTy.getAsString().c_str());
3075 clang::QualType BetterSubTy = ArgType.getArgument().getAsType();
3076 SubTy = cling::utils::Transform::GetPartiallyDesugaredType(Ctx,BetterSubTy,normCtxt.
GetConfig(),
true);
3079 desArgs.push_back(clang::TemplateArgument(SubTy));
3088 if (mightHaveChanged) {
3089 instanceType = Ctx.getTemplateSpecializationType(TST->getTemplateName(),
3091 TST->getCanonicalTypeInternal());
3095 if (!prefix_changed && !mightHaveChanged)
return originalType;
3097 instanceType = Ctx.getElaboratedType(clang::ETK_None,prefix,instanceType);
3098 instanceType = Ctx.getQualifiedType(instanceType,prefix_qualifiers);
3100 return instanceType;
3120 llvm::StringRef title;
3123 if (clang::AnnotateAttr *A =
m.getAttr<clang::AnnotateAttr>())
3124 title = A->getAnnotation();
3136 if (errnum) *errnum =
VALID;
3138 if (title.size() == 0 || (title[0] !=
'['))
return llvm::StringRef();
3139 size_t rightbracket = title.find(
']');
3140 if (rightbracket == llvm::StringRef::npos)
return llvm::StringRef();
3142 std::string working;
3143 llvm::StringRef indexvar(title.data()+1,rightbracket-1);
3150 size_t indexvarlen = indexvar.size();
3151 for ( i=0; i<indexvarlen; i++) {
3152 if (!isspace(indexvar[i])) {
3153 working += indexvar[i];
3158 const char *tokenlist =
"*+-";
3159 char *current =
const_cast<char*
>(working.c_str());
3160 current = strtok(current,tokenlist);
3164 if (isdigit(current[0])) {
3165 for(i=0;i<strlen(current);i++) {
3166 if (!isdigit(current[i])) {
3171 if (errstr) *errstr = current;
3172 if (errnum) *errnum =
NOT_INT;
3173 return llvm::StringRef();
3178 const clang::CXXRecordDecl *parent_clxx = llvm::dyn_cast<clang::CXXRecordDecl>(
m.getDeclContext());
3179 const clang::FieldDecl *index1 =
nullptr;
3181 index1 = GetDataMemberFromAll(*parent_clxx, current );
3183 if ( IsFieldDeclInt(index1) ) {
3188 for(clang::RecordDecl::field_iterator field_iter = parent_clxx->field_begin(), end = parent_clxx->field_end();
3192 if ( field_iter->getNameAsString() ==
m.getNameAsString() ) {
3198 if (errstr) *errstr = current;
3199 if (errnum) *errnum =
NOT_DEF;
3200 return llvm::StringRef();
3202 if ( field_iter->getNameAsString() == index1->getNameAsString() ) {
3210 if (errstr) *errstr = current;
3211 if (errnum) *errnum =
NOT_INT;
3212 return llvm::StringRef();
3219 clang::Sema& SemaR =
const_cast<cling::Interpreter&
>(interp).getSema();
3220 index1 = GetDataMemberFromAllParents(SemaR, *parent_clxx, current);
3223 if ( IsFieldDeclInt(index1) ) {
3230 if (errnum) *errnum =
NOT_INT;
3231 if (errstr) *errstr = current;
3235 if (errnum) *errnum =
NOT_INT;
3236 if (errstr) *errstr = current;
3237 return llvm::StringRef();
3239 if ( found && (index1->getAccess() == clang::AS_private) ) {
3242 if (errstr) *errstr = current;
3244 return llvm::StringRef();
3251 if (errstr) *errstr = indexvar;
3252 if (errnum) *errnum =
UNKNOWN;
3253 return llvm::StringRef();
3258 current = strtok(
nullptr, tokenlist);
3274 while((
c = in[i++])) {
3275 const char *repl =
nullptr;
3277 case '+': repl =
"pL";
break;
3278 case '-': repl =
"mI";
break;
3279 case '*': repl =
"mU";
break;
3280 case '/': repl =
"dI";
break;
3281 case '&': repl =
"aN";
break;
3282 case '%': repl =
"pE";
break;
3283 case '|': repl =
"oR";
break;
3284 case '^': repl =
"hA";
break;
3285 case '>': repl =
"gR";
break;
3286 case '<': repl =
"lE";
break;
3287 case '=': repl =
"eQ";
break;
3288 case '~': repl =
"wA";
break;
3289 case '.': repl =
"dO";
break;
3290 case '(': repl =
"oP";
break;
3291 case ')': repl =
"cP";
break;
3292 case '[': repl =
"oB";
break;
3293 case ']': repl =
"cB";
break;
3294 case '{': repl =
"lB";
break;
3295 case '}': repl =
"rB";
break;
3296 case ';': repl =
"sC";
break;
3297 case '#': repl =
"hS";
break;
3298 case '?': repl =
"qM";
break;
3299 case '`': repl =
"bT";
break;
3300 case '!': repl =
"nO";
break;
3301 case ',': repl =
"cO";
break;
3302 case '$': repl =
"dA";
break;
3303 case ' ': repl =
"sP";
break;
3304 case ':': repl =
"cL";
break;
3305 case '"': repl =
"dQ";
break;
3306 case '@': repl =
"aT";
break;
3307 case '\'': repl =
"sQ";
break;
3308 case '\\': repl =
"fI";
break;
3317 auto firstNonNumber = out.find_first_not_of(
"0123456789");
3318 if (firstNonNumber != std::string::npos)
3319 out.replace(0,firstNonNumber,
"");
3322static clang::SourceLocation
3324 clang::SourceLocation sourceLoc) {
3326 if (!sourceLoc.isFileID()) {
3327 return sourceManager.getExpansionRange(sourceLoc).getEnd();
3336 const cling::Interpreter& interp)
3366 using namespace clang;
3367 SourceLocation headerLoc = decl.getLocation();
3369 static const char invalidFilename[] =
"";
3370 if (!headerLoc.isValid())
return invalidFilename;
3372 HeaderSearch& HdrSearch = interp.getCI()->getPreprocessor().getHeaderSearchInfo();
3374 SourceManager& sourceManager = decl.getASTContext().getSourceManager();
3376 FileID headerFID = sourceManager.getFileID(headerLoc);
3377 SourceLocation includeLoc
3379 sourceManager.getIncludeLoc(headerFID));
3381 const FileEntry *headerFE = sourceManager.getFileEntryForID(headerFID);
3382 while (includeLoc.isValid() && sourceManager.isInSystemHeader(includeLoc)) {
3383 ConstSearchDirIterator *foundDir =
nullptr;
3386 assert(headerFE &&
"Couldn't find FileEntry from FID!");
3388 = HdrSearch.LookupFile(llvm::sys::path::filename(headerFE->getName()),
3390 true ,
nullptr, foundDir,
3391 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3399 headerFID = sourceManager.getFileID(includeLoc);
3400 headerFE = sourceManager.getFileEntryForID(headerFID);
3405 if (interp.getCI()->getLangOpts().Modules && !headerFE) {
3406 assert(decl.isFirstDecl() &&
"Couldn't trace back include from a decl"
3407 " that is not from an AST file");
3408 assert(StringRef(includeLoc.printToString(sourceManager)).startswith(
"<module-includes>"));
3412 sourceManager.getIncludeLoc(headerFID));
3415 if (!headerFE)
return invalidFilename;
3417 llvm::SmallString<256> headerFileName(headerFE->getName());
3420 llvm::sys::path::remove_dots(headerFileName,
true);
3431 bool isAbsolute = llvm::sys::path::is_absolute(headerFileName);
3432 clang::OptionalFileEntryRef FELong;
3434 for (llvm::sys::path::const_iterator
3435 IDir = llvm::sys::path::begin(headerFileName),
3436 EDir = llvm::sys::path::end(headerFileName);
3437 !FELong && IDir != EDir; ++IDir) {
3443 size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3444 llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3445 assert(trailingPart.data() + trailingPart.size()
3446 == headerFileName.data() + headerFileName.size()
3447 &&
"Mismatched partitioning of file name!");
3448 ConstSearchDirIterator* FoundDir =
nullptr;
3449 FELong = HdrSearch.LookupFile(trailingPart, SourceLocation(),
3450 true ,
nullptr, FoundDir,
3451 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3459 return invalidFilename;
3463 for (llvm::sys::path::reverse_iterator
3464 IDir = llvm::sys::path::rbegin(headerFileName),
3465 EDir = llvm::sys::path::rend(headerFileName);
3466 IDir != EDir; ++IDir) {
3467 size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3468 llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3469 assert(trailingPart.data() + trailingPart.size()
3470 == headerFileName.data() + headerFileName.size()
3471 &&
"Mismatched partitioning of file name!");
3472 ConstSearchDirIterator* FoundDir =
nullptr;
3475 if (HdrSearch.LookupFile(trailingPart, SourceLocation(),
3476 true ,
nullptr, FoundDir,
3477 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3480 nullptr,
nullptr ) == FELong) {
3481 return trailingPart.str();
3485 return invalidFilename;
3491 const clang::QualType &qtype,
3492 const clang::ASTContext &astContext)
3494 std::string fqname = cling::utils::TypeName::GetFullyQualifiedName(qtype, astContext);
3503 const clang::QualType &qtype,
3504 const cling::Interpreter &interpreter)
3509 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interpreter));
3513 interpreter.getCI()->getASTContext());
3521 clang::ClassTemplateDecl*& ctd,
3522 clang::ClassTemplateSpecializationDecl*& ctsd)
3524 using namespace clang;
3525 const Type* theType = qt.getTypePtr();
3532 if (theType->isPointerType()) {
3536 if (
const RecordType* rType = llvm::dyn_cast<RecordType>(theType)) {
3537 ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(rType->getDecl());
3539 ctd = ctsd->getSpecializedTemplate();
3544 if (
const SubstTemplateTypeParmType* sttpType = llvm::dyn_cast<SubstTemplateTypeParmType>(theType)){
3549 ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(qt->getAsCXXRecordDecl());
3551 ctd = ctsd->getSpecializedTemplate();
3566 using namespace clang;
3567 ClassTemplateSpecializationDecl* ctsd;
3568 ClassTemplateDecl* ctd;
3582 using namespace clang;
3583 TemplateName theTemplateName;
3585 const Type* theType = qt.getTypePtr();
3587 if (
const TemplateSpecializationType* tst = llvm::dyn_cast_or_null<const TemplateSpecializationType>(theType)) {
3588 theTemplateName = tst->getTemplateName();
3591 theTemplateName = TemplateName(ctd);
3594 return theTemplateName;
3600 llvm::SmallVectorImpl<clang::TemplateArgument>& preceedingTArgs,
3601 const clang::NamedDecl& tPar,
3602 const cling::Interpreter& interp,
3606 using namespace clang;
3609 TemplateTypeParmDecl* ttpdPtr =
const_cast<TemplateTypeParmDecl*
>(llvm::dyn_cast<TemplateTypeParmDecl>(&tPar));
3610 if (!ttpdPtr)
return false;
3611 if (!ttpdPtr->hasDefaultArgument())
return false;
3614 QualType tParQualType = ttpdPtr->getDefaultArgument();
3615 const QualType tArgQualType = tArg.getAsType();
3622 if (tParQualType.getTypePtr() == tArgQualType.getTypePtr())
return true;
3633 const clang::ElaboratedType* etype
3634 = llvm::dyn_cast<clang::ElaboratedType>(tParQualType.getTypePtr());
3636 tParQualType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3637 etype = llvm::dyn_cast<clang::ElaboratedType>(tParQualType.getTypePtr());
3640 const TemplateSpecializationType* tst =
3641 llvm::dyn_cast<TemplateSpecializationType>(tParQualType.getTypePtr());
3646 ClassTemplateSpecializationDecl* TSTdecl
3647 = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(tArgQualType->getAsCXXRecordDecl());
3652 TemplateDecl *Template = tst->getTemplateName().getAsTemplateDecl();
3655 SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3658 SourceLocation LAngleLoc = TSTdecl->getSourceRange().getBegin();
3663 TemplateArgument newArg = tArg;
3665 clang::Sema& S = interp.getCI()->getSema();
3666 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interp));
3667 llvm::SmallVector<clang::TemplateArgument, 4> canonArgs;
3668 bool HasDefaultArgs;
3669 TemplateArgumentLoc defTArgLoc = S.SubstDefaultTemplateArgumentIfAvailable(Template,
3678 newArg = defTArgLoc.getArgument();
3679 if (newArg.isNull() ||
3680 newArg.getKind() != clang::TemplateArgument::Type) {
3682 "Template parameter substitution failed!");
3685 ClassTemplateSpecializationDecl* nTSTdecl
3686 = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(newArg.getAsType()->getAsCXXRecordDecl());
3689 isEqual = (nTSTdecl && nTSTdecl->getMostRecentDecl() == TSTdecl->getMostRecentDecl()) ||
3690 (tParQualType.getTypePtr() == newArg.getAsType().getTypePtr());
3702 const clang::NamedDecl& tPar)
3704 using namespace clang;
3705 const NonTypeTemplateParmDecl* nttpdPtr = llvm::dyn_cast<NonTypeTemplateParmDecl>(&tPar);
3706 if (!nttpdPtr)
return false;
3707 const NonTypeTemplateParmDecl& nttpd = *nttpdPtr;
3709 if (!nttpd.hasDefaultArgument())
3713 llvm::APSInt defaultValueAPSInt(64,
false);
3714 if (Expr* defArgExpr = nttpd.getDefaultArgument()) {
3715 const ASTContext& astCtxt = nttpdPtr->getASTContext();
3716 if (
auto Value = defArgExpr->getIntegerConstantExpr(astCtxt))
3717 defaultValueAPSInt = *
Value;
3720 const int value = tArg.getAsIntegral().getLimitedValue();
3723 return value == defaultValueAPSInt;
3733 using namespace clang;
3734 if (!nDecl)
return false;
3735 if (
const TemplateTypeParmDecl* ttpd = llvm::dyn_cast<TemplateTypeParmDecl>(nDecl))
3736 return ttpd->hasDefaultArgument();
3737 if (
const NonTypeTemplateParmDecl* nttpd = llvm::dyn_cast<NonTypeTemplateParmDecl>(nDecl))
3738 return nttpd->hasDefaultArgument();
3743static void KeepNParams(clang::QualType& normalizedType,
3744 const clang::QualType& vanillaType,
3745 const cling::Interpreter& interp,
3750 const clang::TemplateArgument &tArg,
3751 const cling::Interpreter& interp,
3753 const clang::ASTContext& astCtxt)
3756 using namespace clang;
3763 if (tArg.getKind() == clang::TemplateArgument::Type) {
3764 QualType thisNormQualType = normTArg.getAsType();
3765 QualType thisArgQualType = tArg.getAsType();
3770 normTArg = TemplateArgument(thisNormQualType);
3771 return (thisNormQualType != thisArgQualType);
3772 }
else if (normTArg.getKind() == clang::TemplateArgument::Pack) {
3773 assert( tArg.getKind() == clang::TemplateArgument::Pack );
3775 SmallVector<TemplateArgument, 2> desArgs;
3776 bool mightHaveChanged =
true;
3777 for (
auto I = normTArg.pack_begin(), E = normTArg.pack_end(),
3778 FI = tArg.pack_begin(), FE = tArg.pack_end();
3779 I != E && FI != FE; ++
I, ++FI)
3781 TemplateArgument pack_arg(*
I);
3783 desArgs.push_back(pack_arg);
3785 if (mightHaveChanged) {
3786 ASTContext &mutableCtx(
const_cast<ASTContext&
>(astCtxt) );
3787 normTArg = TemplateArgument::CreatePackCopy(mutableCtx, desArgs);
3789 return mightHaveChanged;
3800 const clang::QualType& vanillaType,
3801 const cling::Interpreter& interp,
3805 using namespace clang;
3809 ClassTemplateSpecializationDecl* ctsd;
3810 ClassTemplateDecl* ctd;
3811 if (! QualType2Template(vanillaType, ctd, ctsd)) return ;
3817 QualType originalNormalizedType = normalizedType;
3819 const ASTContext& astCtxt = ctsd->getASTContext();
3824 if (llvm::isa<clang::PointerType>(normalizedType.getTypePtr())) {
3826 clang::Qualifiers quals = normalizedType.getQualifiers();
3827 auto valNormalizedType = normalizedType->getPointeeType();
3828 KeepNParams(valNormalizedType,vanillaType, interp, normCtxt);
3829 normalizedType = astCtxt.getPointerType(valNormalizedType);
3831 normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3837 if (llvm::isa<clang::ReferenceType>(normalizedType.getTypePtr())) {
3839 bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(normalizedType.getTypePtr());
3840 clang::Qualifiers quals = normalizedType.getQualifiers();
3841 auto valNormType = normalizedType->getPointeeType();
3842 KeepNParams(valNormType, vanillaType, interp, normCtxt);
3846 normalizedType = astCtxt.getLValueReferenceType(valNormType);
3848 normalizedType = astCtxt.getRValueReferenceType(valNormType);
3850 normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3855 bool prefix_changed =
false;
3856 clang::NestedNameSpecifier* prefix =
nullptr;
3857 clang::Qualifiers prefix_qualifiers = normalizedType.getLocalQualifiers();
3858 const clang::ElaboratedType* etype
3859 = llvm::dyn_cast<clang::ElaboratedType>(normalizedType.getTypePtr());
3863 prefix = AddDefaultParametersNNS(astCtxt, etype->getQualifier(), interp, normCtxt);
3864 prefix_changed = prefix != etype->getQualifier();
3865 normalizedType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3871 const clang::ClassTemplateDecl* ctdWithDefaultArgs = ctd;
3872 for (
const RedeclarableTemplateDecl* rd: ctdWithDefaultArgs->redecls()) {
3873 clang::TemplateParameterList* tpl = rd->getTemplateParameters();
3874 if (tpl->getMinRequiredArguments () < tpl->size()) {
3875 ctdWithDefaultArgs = llvm::dyn_cast<clang::ClassTemplateDecl>(rd);
3880 if (!ctdWithDefaultArgs) {
3881 Error(
"KeepNParams",
"Not found template default arguments\n");
3882 normalizedType=originalNormalizedType;
3886 TemplateParameterList* tParsPtr = ctdWithDefaultArgs->getTemplateParameters();
3887 const TemplateParameterList& tPars = *tParsPtr;
3888 const TemplateArgumentList& tArgs = ctsd->getTemplateArgs();
3891 TemplateName theTemplateName = ExtractTemplateNameFromQualType(normalizedType);
3892 if (theTemplateName.isNull()) {
3893 normalizedType=originalNormalizedType;
3897 const TemplateSpecializationType* normalizedTst =
3898 llvm::dyn_cast<TemplateSpecializationType>(normalizedType.getTypePtr());
3899 if (!normalizedTst) {
3900 normalizedType=originalNormalizedType;
3904 const clang::ClassTemplateSpecializationDecl* TSTdecl
3905 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(normalizedType.getTypePtr()->getAsCXXRecordDecl());
3906 bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
3913 llvm::SmallVector<TemplateArgument, 4> argsToKeep;
3915 const int nArgs = tArgs.size();
3916 const auto &normArgs = normalizedTst->template_arguments();
3917 const int nNormArgs = normArgs.size();
3919 bool mightHaveChanged =
false;
3922 for (
int formal = 0, inst = 0; formal != nArgs; ++formal, ++inst) {
3923 const NamedDecl* tParPtr = tPars.getParam(formal);
3925 Error(
"KeepNParams",
"The parameter number %s is null.\n", formal);
3932 if (formal == nNormArgs || inst == nNormArgs)
break;
3934 const TemplateArgument& tArg = tArgs.get(formal);
3935 TemplateArgument normTArg(normArgs[inst]);
3937 bool shouldKeepArg = nArgsToKeep < 0 || inst < nArgsToKeep;
3938 if (isStdDropDefault) shouldKeepArg =
false;
3947 if ( tParPtr->isTemplateParameterPack() ) {
3952 for( ; inst != nNormArgs; ++inst) {
3953 normTArg = normArgs[inst];
3955 argsToKeep.push_back(normTArg);
3961 argsToKeep.push_back(normTArg);
3964 if (!isStdDropDefault) {
3966 mightHaveChanged =
true;
3976 auto argKind = tArg.getKind();
3977 if (argKind == clang::TemplateArgument::Type){
3979 equal =
areEqualTypes(tArg, argsToKeep, *tParPtr, interp, normCtxt);
3980 }
else if (argKind == clang::TemplateArgument::Integral){
3985 argsToKeep.push_back(normTArg);
3987 mightHaveChanged =
true;
3993 if (!prefix_changed && !mightHaveChanged) {
3994 normalizedType = originalNormalizedType;
3999 if (mightHaveChanged) {
4000 Qualifiers qualifiers = normalizedType.getLocalQualifiers();
4001 normalizedType = astCtxt.getTemplateSpecializationType(theTemplateName,
4003 normalizedType.getTypePtr()->getCanonicalTypeInternal());
4004 normalizedType = astCtxt.getQualifiedType(normalizedType, qualifiers);
4010 normalizedType = astCtxt.getElaboratedType(clang::ETK_None,prefix,normalizedType);
4011 normalizedType = astCtxt.getQualifiedType(normalizedType,prefix_qualifiers);
4025 clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4028 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interpreter));
4029 clang::QualType normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt,
type, normCtxt.
GetConfig(),
true );
4037 return normalizedType;
4051 if (
type.isNull()) {
4058 clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4059 clang::PrintingPolicy policy(ctxt.getPrintingPolicy());
4060 policy.SuppressTagKeyword =
true;
4061 policy.SuppressScope =
true;
4062 policy.AnonymousTagLocations =
false;
4067 std::string normalizedNameStep1;
4070 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
4071 normalizedType.getAsStringInternal(normalizedNameStep1,policy);
4081 if (norm_name.length()>2 && norm_name[0]==
':' && norm_name[1]==
':') {
4082 norm_name.erase(0,2);
4090 const clang::TypeDecl* typeDecl,
4091 const cling::Interpreter &interpreter)
4094 const clang::Sema &sema = interpreter.getSema();
4095 clang::ASTContext& astCtxt = sema.getASTContext();
4096 clang::QualType qualType = astCtxt.getTypeDeclType(typeDecl);
4105std::pair<std::string,clang::QualType>
4107 const cling::Interpreter &interpreter,
4111 std::string thisTypeName;
4112 GetNormalizedName(thisTypeName, thisType, interpreter, normCtxt );
4115 if (!hasChanged)
return std::make_pair(thisTypeName,thisType);
4119 "Name changed from %s to %s\n", thisTypeName.c_str(), thisTypeNameForIO.c_str());
4122 auto& lookupHelper = interpreter.getLookupHelper();
4124 const clang::Type* typePtrForIO;
4125 lookupHelper.findScope(thisTypeNameForIO,
4126 cling::LookupHelper::DiagSetting::NoDiagnostics,
4130 if (!typePtrForIO) {
4132 "Type not found: %s.",thisTypeNameForIO.c_str());
4135 clang::QualType typeForIO(typePtrForIO,0);
4138 if (!typeForIO->isRecordType()) {
4139 return std::make_pair(thisTypeNameForIO,typeForIO);
4142 auto thisDeclForIO = typeForIO->getAsCXXRecordDecl();
4143 if (!thisDeclForIO) {
4145 "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());
4146 return std::make_pair(thisTypeName,thisType);
4149 return std::make_pair(thisTypeNameForIO,typeForIO);
4155 const cling::Interpreter &interpreter,
4167 std::string dictFileName(moduleName);
4168 dictFileName +=
"_rdict.pcm";
4169 return dictFileName;
4173 llvm::errs() << llvm::StringRef(commentStart, 80) <<
'\n';
4199 clang::SourceManager& sourceManager = decl.getASTContext().getSourceManager();
4200 clang::SourceLocation sourceLocation = decl.getEndLoc();
4203 sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
4211 if (!decl.hasOwningModule() && sourceManager.isLoadedSourceLocation(sourceLocation)) {
4217 const char *commentStart = sourceManager.getCharacterData(sourceLocation, &invalid);
4221 bool skipToSemi =
true;
4222 if (
const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(&decl)) {
4223 if (FD->isImplicit()) {
4227 if (FD->isExplicitlyDefaulted() || FD->isDeletedAsWritten()) {
4231 }
else if (FD->doesThisDeclarationHaveABody()) {
4234 assert((decl.getEndLoc() != sourceLocation || *commentStart ==
'}'
4236 &&
"Expected macro or end of body at '}'");
4237 if (*commentStart) ++commentStart;
4240 while (*commentStart && isspace(*commentStart)
4241 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4244 if (*commentStart ==
';') ++commentStart;
4248 }
else if (
const clang::EnumConstantDecl* ECD
4249 = clang::dyn_cast<clang::EnumConstantDecl>(&decl)) {
4251 if (ECD->getNextDeclInContext())
4252 while (*commentStart && *commentStart !=
',' && *commentStart !=
'\r' && *commentStart !=
'\n')
4260 while (*commentStart && *commentStart !=
';' && *commentStart !=
'\r' && *commentStart !=
'\n')
4262 if (*commentStart ==
';') ++commentStart;
4266 while ( *commentStart && isspace(*commentStart)
4267 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4271 if (commentStart[0] !=
'/' ||
4272 (commentStart[1] !=
'/' && commentStart[1] !=
'*')) {
4282 unsigned int skipChars = 2;
4283 if (commentStart[0] ==
'/' &&
4284 commentStart[1] ==
'/' &&
4285 (commentStart[2] ==
'/' || commentStart[2] ==
'!') &&
4286 commentStart[3] ==
'<') {
4288 }
else if (commentStart[0] ==
'/' &&
4289 commentStart[1] ==
'*' &&
4290 (commentStart[2] ==
'*' || commentStart[2] ==
'!') &&
4291 commentStart[3] ==
'<') {
4295 commentStart += skipChars;
4298 while ( *commentStart && isspace(*commentStart)
4299 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4302 const char* commentEnd = commentStart;
4304 while (*commentEnd && *commentEnd !=
'\n' && *commentEnd !=
'\r') {
4310 while (commentEnd > commentStart && isspace(commentEnd[-1])) {
4316 unsigned offset = commentStart - sourceManager.getCharacterData(sourceLocation);
4317 *loc = sourceLocation.getLocWithOffset(
offset - 1);
4320 return llvm::StringRef(commentStart, commentEnd - commentStart);
4328 if (!decl)
return false;
4330 auto& sema = interpreter.getCI()->getSema();
4331 auto maybeMacroLoc = decl->getLocation();
4333 if (!maybeMacroLoc.isMacroID())
return false;
4335 static const std::vector<std::string> signatures =
4336 {
"ClassDef",
"ClassDefOverride",
"ClassDefNV",
"ClassDefInline",
"ClassDefInlineOverride",
"ClassDefInlineNV" };
4338 for (
auto &
name : signatures)
4339 if (sema.findMacroSpelling(maybeMacroLoc,
name))
4353 clang::SourceLocation *loc,
4354 const cling::Interpreter &interpreter)
4356 using namespace clang;
4358 const Decl* DeclFileLineDecl
4359 = interpreter.getLookupHelper().findFunctionProto(&decl,
"DeclFileLine",
"",
4360 cling::LookupHelper::NoDiagnostics);
4364 SourceLocation commentSLoc;
4366 if (comment.size()) {
4373 return llvm::StringRef();
4382 const clang::Type *rawtype =
type.getTypePtr();
4385 if (rawtype->isElaboratedTypeSpecifier() ) {
4386 rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4388 if (rawtype->isArrayType()) {
4389 rawtype =
type.getTypePtr()->getBaseElementTypeUnsafe ();
4391 if (rawtype->isPointerType() || rawtype->isReferenceType() ) {
4393 clang::QualType pointee;
4394 while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
4396 rawtype = pointee.getTypePtr();
4398 if (rawtype->isElaboratedTypeSpecifier() ) {
4399 rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4401 if (rawtype->isArrayType()) {
4402 rawtype = rawtype->getBaseElementTypeUnsafe ();
4406 if (rawtype->isArrayType()) {
4407 rawtype = rawtype->getBaseElementTypeUnsafe ();
4418 if (ctxt.isNamespace() || ctxt.isTranslationUnit())
4420 else if(
const auto parentdecl = llvm::dyn_cast<clang::CXXRecordDecl>(&ctxt))
4433 const clang::DeclContext *ctxt = decl.getDeclContext();
4434 switch (decl.getAccess()) {
4435 case clang::AS_public:
4437 case clang::AS_protected:
4439 case clang::AS_private:
4441 case clang::AS_none:
4445 assert(
false &&
"Unexpected value for the access property value in Clang");
4455 return cling::utils::Analyze::IsStdClass(cl);
4465 if (cling::utils::Analyze::IsStdClass(cl)) {
4466 static const char *names[] =
4467 {
"shared_ptr",
"__shared_ptr",
4468 "vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset"};
4469 llvm::StringRef clname(cl.getName());
4470 for(
auto &&
name : names) {
4471 if (clname ==
name)
return true;
4481 const clang::CXXRecordDecl ¤tCl)
4484 if (&cl == ¤tCl)
return true;
4486 const clang::CXXRecordDecl* previous = currentCl.getPreviousDecl();
4489 if (
nullptr == previous){
4508 const clang::CXXRecordDecl *thisDecl =
4509 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(typ, cling::LookupHelper::WithDiagnostics));
4513 Error(
"IsOfType",
"Record decl of type %s not found in the AST.", typ.c_str());
4518 const clang::CXXRecordDecl *mostRecentDecl = thisDecl->getMostRecentDecl();
4543 if (!IsStdClass(cl)) {
4544 auto *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(cl.getDeclContext());
4545 if (cl.getName() !=
"RVec" || nsDecl ==
nullptr || nsDecl->getName() !=
"VecOps")
4548 auto *parentNsDecl = llvm::dyn_cast<clang::NamespaceDecl>(cl.getDeclContext()->getParent());
4549 if (parentNsDecl ==
nullptr || parentNsDecl->getName() !=
"ROOT")
4553 return STLKind(cl.getName());
4557 using namespace clang;
4558 struct SearchTypedef:
public TypeVisitor<SearchTypedef, bool> {
4559 bool VisitTypedefType(
const TypedefType* TD) {
4562 bool VisitArrayType(
const ArrayType* AT) {
4563 return Visit(AT->getElementType().getTypePtr());
4565 bool VisitDecltypeType(
const DecltypeType* DT) {
4566 return Visit(DT->getUnderlyingType().getTypePtr());
4568 bool VisitPointerType(
const PointerType* PT) {
4569 return Visit(PT->getPointeeType().getTypePtr());
4571 bool VisitReferenceType(
const ReferenceType* RT) {
4572 return Visit(RT->getPointeeType().getTypePtr());
4574 bool VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType* STST) {
4575 return Visit(STST->getReplacementType().getTypePtr());
4577 bool VisitTemplateSpecializationType(
const TemplateSpecializationType* TST) {
4578 for (
const TemplateArgument &
TA : TST->template_arguments()) {
4579 if (
TA.getKind() == TemplateArgument::Type && Visit(
TA.getAsType().getTypePtr()))
4584 bool VisitTemplateTypeParmType(
const TemplateTypeParmType* TTPT) {
4587 bool VisitTypeOfType(
const TypeOfType* TOT) {
4588 return TOT->getUnmodifiedType().getTypePtr();
4590 bool VisitElaboratedType(
const ElaboratedType* ET) {
4591 NestedNameSpecifier* NNS = ET->getQualifier();
4593 if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
4594 if (Visit(NNS->getAsType()))
4597 NNS = NNS->getPrefix();
4599 return Visit(ET->getNamedType().getTypePtr());
4620 using namespace llvm;
4621 using namespace clang;
4622 const clang::ASTContext &Ctxt =
instance->getAsCXXRecordDecl()->getASTContext();
4625 const clang::ElaboratedType* etype
4626 = llvm::dyn_cast<clang::ElaboratedType>(
input.getTypePtr());
4630 clang::Qualifiers scope_qualifiers =
input.getLocalQualifiers();
4631 assert(
instance->getAsCXXRecordDecl() !=
nullptr &&
"ReSubstTemplateArg only makes sense with a type representing a class.");
4633 clang::NestedNameSpecifier *scope = ReSubstTemplateArgNNS(Ctxt,etype->getQualifier(),
instance);
4636 if (scope) subTy = Ctxt.getElaboratedType(clang::ETK_None,scope,subTy);
4637 subTy = Ctxt.getQualifiedType(subTy,scope_qualifiers);
4641 QualType QT =
input;
4645 if (isa<clang::PointerType>(QT.getTypePtr())) {
4647 Qualifiers quals = QT.getQualifiers();
4650 if (nQT == QT->getPointeeType())
return QT;
4652 QT = Ctxt.getPointerType(nQT);
4654 QT = Ctxt.getQualifiedType(QT, quals);
4660 if (isa<ReferenceType>(QT.getTypePtr())) {
4662 bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
4663 Qualifiers quals = QT.getQualifiers();
4666 if (nQT == QT->getPointeeType())
return QT;
4670 QT = Ctxt.getLValueReferenceType(nQT);
4672 QT = Ctxt.getRValueReferenceType(nQT);
4674 QT = Ctxt.getQualifiedType(QT, quals);
4680 if (isa<clang::ArrayType>(QT.getTypePtr())) {
4682 Qualifiers quals = QT.getQualifiers();
4684 if (
const auto arr = dyn_cast<ConstantArrayType>(QT.getTypePtr())) {
4687 if (newQT == arr->getElementType())
return QT;
4688 QT = Ctxt.getConstantArrayType(newQT,
4691 arr->getSizeModifier(),
4692 arr->getIndexTypeCVRQualifiers());
4694 }
else if (
const auto arr = dyn_cast<DependentSizedArrayType>(QT.getTypePtr())) {
4697 if (newQT == QT)
return QT;
4698 QT = Ctxt.getDependentSizedArrayType (newQT,
4700 arr->getSizeModifier(),
4701 arr->getIndexTypeCVRQualifiers(),
4702 arr->getBracketsRange());
4704 }
else if (
const auto arr = dyn_cast<IncompleteArrayType>(QT.getTypePtr())) {
4707 if (newQT == arr->getElementType())
return QT;
4708 QT = Ctxt.getIncompleteArrayType (newQT,
4709 arr->getSizeModifier(),
4710 arr->getIndexTypeCVRQualifiers());
4712 }
else if (
const auto arr = dyn_cast<VariableArrayType>(QT.getTypePtr())) {
4715 if (newQT == arr->getElementType())
return QT;
4716 QT = Ctxt.getVariableArrayType (newQT,
4718 arr->getSizeModifier(),
4719 arr->getIndexTypeCVRQualifiers(),
4720 arr->getBracketsRange());
4724 QT = Ctxt.getQualifiedType(QT, quals);
4729 etype = llvm::dyn_cast<clang::ElaboratedType>(
instance);
4731 instance = etype->getNamedType().getTypePtr();
4735 const clang::TemplateSpecializationType* TST
4736 = llvm::dyn_cast<const clang::TemplateSpecializationType>(
instance);
4738 if (!TST)
return input;
4740 const clang::ClassTemplateSpecializationDecl* TSTdecl
4741 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(
instance->getAsCXXRecordDecl());
4743 if (!TSTdecl)
return input;
4745 const clang::SubstTemplateTypeParmType *substType
4746 = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(
input.getTypePtr());
4750 const clang::ClassTemplateDecl *replacedCtxt =
nullptr;
4752 const clang::DeclContext *replacedDeclCtxt = substType->getReplacedParameter()->getDeclContext();
4753 const clang::CXXRecordDecl *decl = llvm::dyn_cast<clang::CXXRecordDecl>(replacedDeclCtxt);
4754 unsigned int index = substType->getReplacedParameter()->getIndex();
4757 if (decl->getKind() == clang::Decl::ClassTemplatePartialSpecialization) {
4758 const clang::ClassTemplatePartialSpecializationDecl *spec = llvm::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(decl);
4760 unsigned int depth = substType->getReplacedParameter()->getDepth();
4762 const TemplateArgument *instanceArgs = spec->getTemplateArgs().data();
4763 unsigned int instanceNArgs = spec->getTemplateArgs().size();
4767 for(
unsigned int A = 0; A < instanceNArgs; ++A) {
4768 if (instanceArgs[A].getKind() == clang::TemplateArgument::Type) {
4769 clang::QualType argQualType = instanceArgs[A].getAsType();
4771 const clang::TemplateTypeParmType *replacementType;
4773 replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(argQualType);
4775 if (!replacementType) {
4776 const clang::SubstTemplateTypeParmType *argType
4777 = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(argQualType);
4779 clang::QualType replacementQT = argType->getReplacementType();
4780 replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(replacementQT);
4783 if (replacementType &&
4784 depth == replacementType->getDepth() &&
4785 index == replacementType->getIndex() )
4792 replacedCtxt = spec->getSpecializedTemplate();
4794 replacedCtxt = decl->getDescribedClassTemplate();
4796 }
else if (
auto const declguide = llvm::dyn_cast<clang::CXXDeductionGuideDecl>(replacedDeclCtxt)) {
4797 replacedCtxt = llvm::dyn_cast<clang::ClassTemplateDecl>(declguide->getDeducedTemplate());
4798 }
else if (
auto const ctdecl = llvm::dyn_cast<clang::ClassTemplateDecl>(replacedDeclCtxt)) {
4799 replacedCtxt = ctdecl;
4801 std::string astDump;
4802 llvm::raw_string_ostream ostream(astDump);
4805 ROOT::TMetaUtils::Warning(
"ReSubstTemplateArg",
"Unexpected type of declaration context for template parameter: %s.\n\tThe responsible class is:\n\t%s\n",
4806 replacedDeclCtxt->getDeclKindName(), astDump.c_str());
4807 replacedCtxt =
nullptr;
4810 if ((replacedCtxt && replacedCtxt->getCanonicalDecl() == TSTdecl->getSpecializedTemplate()->getCanonicalDecl())
4812 substType->getReplacedParameter()
4813 == TSTdecl->getSpecializedTemplate ()->getTemplateParameters()->getParam(
index))
4815 const auto &TAs = TST->template_arguments();
4816 if (
index >= TAs.size()) {
4822 }
else if (TAs[
index].getKind() == clang::TemplateArgument::Type) {
4823 return TAs[
index].getAsType();
4832 const clang::TemplateSpecializationType* inputTST
4833 = llvm::dyn_cast<const clang::TemplateSpecializationType>(
input.getTypePtr());
4834 const clang::ASTContext& astCtxt = TSTdecl->getASTContext();
4837 bool mightHaveChanged =
false;
4838 llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
4839 for (
const clang::TemplateArgument &
TA : inputTST->template_arguments()) {
4840 if (
TA.getKind() != clang::TemplateArgument::Type) {
4841 desArgs.push_back(
TA);
4845 clang::QualType SubTy =
TA.getAsType();
4847 if (llvm::isa<clang::ElaboratedType>(SubTy)
4848 || llvm::isa<clang::SubstTemplateTypeParmType>(SubTy)
4849 || llvm::isa<clang::TemplateSpecializationType>(SubTy)) {
4851 mightHaveChanged = SubTy != newSubTy;
4852 if (!newSubTy.isNull()) {
4853 desArgs.push_back(clang::TemplateArgument(newSubTy));
4856 desArgs.push_back(
TA);
4860 if (mightHaveChanged) {
4861 clang::Qualifiers qualifiers =
input.getLocalQualifiers();
4862 input = astCtxt.getTemplateSpecializationType(inputTST->getTemplateName(),
4864 inputTST->getCanonicalTypeInternal());
4865 input = astCtxt.getQualifiedType(
input, qualifiers);
4877 if ( nArgsToRemove == 0 ||
name ==
"")
4884 unsigned int nArgsRemoved=0;
4885 unsigned int nBraces=0;
4887 while (nArgsRemoved!=nArgsToRemove && cur<
length){
4889 if (
c ==
'<') nBraces++;
4890 if (
c ==
'>') nBraces--;
4891 if (
c ==
',' && nBraces==1 ) nArgsRemoved++;
4905 static const char *stls[] =
4906 {
"any",
"vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset",
4907 "forward_list",
"unordered_set",
"unordered_multiset",
"unordered_map",
"unordered_multimap",
"RVec",
nullptr};
4921 for(
int k=1;stls[k];k++) {
if (
type.equals(stls[k]))
return values[k];}
4932 TND = TND->getMostRecentDecl();
4933 while (TND && !(TND->hasAttrs()))
4934 TND = TND->getPreviousDecl();
4946 TD = TD->getMostRecentDecl();
4947 while (TD && !(TD->hasAttrs() && TD->isThisDeclarationADefinition()))
4948 TD = TD->getPreviousDecl();
4957 std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4959 const clang::DeclContext* enclosingNamespaceDeclCtxt = decl.getDeclContext();
4960 if (!enclosingNamespaceDeclCtxt)
return;
4962 const clang::NamespaceDecl* enclosingNamespace =
4963 clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4964 if (!enclosingNamespace)
return;
4966 enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4967 enclosingNamespace->isInline()));
4977 std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4979 const clang::DeclContext* enclosingNamespaceDeclCtxt = ctxt.getParent ();
4982 if (!enclosingNamespaceDeclCtxt) {
4988 const clang::NamespaceDecl* enclosingNamespace = clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4989 if (!enclosingNamespace)
return;
4992 enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4993 enclosingNamespace->isInline()));
5004 std::list<std::pair<std::string,unsigned int> >& enclosingSc)
5006 const clang::DeclContext* enclosingDeclCtxt = decl.getDeclContext();
5007 if (!enclosingDeclCtxt)
return nullptr;
5009 unsigned int scopeType;
5011 if (
auto enclosingNamespacePtr =
5012 clang::dyn_cast<clang::NamespaceDecl>(enclosingDeclCtxt)){
5013 scopeType= enclosingNamespacePtr->isInline() ? 1 : 0;
5014 enclosingSc.push_back(std::make_pair(enclosingNamespacePtr->getNameAsString(),scopeType));
5018 if (
auto enclosingClassPtr =
5019 clang::dyn_cast<clang::RecordDecl>(enclosingDeclCtxt)){
5020 return enclosingClassPtr;
5032 std::string::size_type beginVar = 0;
5033 std::string::size_type endVar = 0;
5034 while ((beginVar = txt.find(
'$', beginVar)) != std::string::npos
5035 && beginVar + 1 < txt.length()) {
5036 std::string::size_type beginVarName = beginVar + 1;
5037 std::string::size_type endVarName = std::string::npos;
5038 if (txt[beginVarName] ==
'(') {
5040 endVarName = txt.find(
')', beginVarName);
5042 if (endVarName == std::string::npos) {
5044 varname, txt.c_str() + beginVar);
5047 endVar = endVarName + 1;
5050 beginVarName = beginVar + 1;
5051 endVarName = beginVarName;
5052 while (isalnum(txt[endVarName]) || txt[endVarName] ==
'_')
5054 endVar = endVarName;
5057 const char* val = getenv(txt.substr(beginVarName,
5058 endVarName - beginVarName).c_str());
5061 txt.replace(beginVar, endVar - beginVar, val);
5062 int lenval = strlen(val);
5063 int delta = lenval - (endVar - beginVar);
5067 beginVar = endVar + 1;
5079 const char* envInclPath = getenv(
"ROOT_INCLUDE_PATH");
5083 std::istringstream envInclPathsStream(envInclPath);
5084 std::string inclPath;
5085 while (std::getline(envInclPathsStream, inclPath,
':')) {
5088 if (!inclPath.empty()) {
5089 clingArgs.push_back(
"-I");
5090 clingArgs.push_back(inclPath);
5101 size_t start_pos = 0;
5106 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
5107 str.replace(start_pos, from.length(), to);
5108 start_pos += to.length();
5109 if (recurse) changed =
true;
5125 if (theString.size() < theSubstring.size())
return false;
5126 const unsigned int theSubstringSize = theSubstring.size();
5127 return 0 == theString.compare(theString.size() - theSubstringSize,
5136 if (theString.size() < theSubstring.size())
return false;
5137 const unsigned int theSubstringSize = theSubstring.size();
5138 return 0 == theString.compare(0,
5156 size_t linkdeflen = 9;
5158 if (0 == strncasecmp(
filename + (
len - linkdeflen),
"linkdef", linkdeflen - 2)
5174 return llvm::sys::path::extension(
filename) ==
".h" ||
5175 llvm::sys::path::extension(
filename) ==
".hh" ||
5176 llvm::sys::path::extension(
filename) ==
".hpp" ||
5177 llvm::sys::path::extension(
filename) ==
".H" ||
5178 llvm::sys::path::extension(
filename) ==
".h++" ||
5179 llvm::sys::path::extension(
filename) ==
"hxx" ||
5180 llvm::sys::path::extension(
filename) ==
"Hxx" ||
5181 llvm::sys::path::extension(
filename) ==
"HXX";
5187 cling::Interpreter::IgnoreFilesFunc_t ignoreFiles,
5188 const cling::Interpreter &interp,
5191 clang::Sema &sema = interp.getSema();
5192 cling::Transaction theTransaction(sema);
5193 std::set<clang::Decl *> addedDecls;
5194 for (
auto decl : decls) {
5196 clang::Decl *ncDecl =
const_cast<clang::Decl *
>(decl);
5197 theTransaction.append(ncDecl);
5199 std::string newFwdDecl;
5200 llvm::raw_string_ostream llvmOstr(newFwdDecl);
5202 std::string locallogs;
5203 llvm::raw_string_ostream llvmLogStr(locallogs);
5204 interp.forwardDeclare(theTransaction, sema.getPreprocessor(), sema.getASTContext(), llvmOstr,
true,
5205 logs ? &llvmLogStr : nullptr, ignoreFiles);
5209 logs->swap(locallogs);
5221 std::string& defString)
5233 std::string& defString)
5235 std::list<std::pair<std::string,unsigned int> > enclosingNamespaces;
5238 if (rcdPtr)
return rcdPtr;
5241 static const std::string scopeType [] = {
"namespace ",
"inline namespace ",
"class "};
5243 std::string scopeName;
5244 std::string scopeContent;
5245 unsigned int scopeIndex;
5246 for (
auto const & encScope : enclosingNamespaces){
5247 scopeIndex = encScope.second;
5248 scopeName = encScope.first;
5249 scopeContent =
" { " + defString +
" }";
5250 defString = scopeType[scopeIndex] +
5272 const clang::TemplateParameterList& tmplParamList,
5273 const cling::Interpreter& interpreter)
5276 for (
auto prmIt = tmplParamList.begin();
5277 prmIt != tmplParamList.end(); prmIt++){
5279 if (prmIt != tmplParamList.begin())
5280 templateArgs +=
", ";
5282 auto nDecl = *prmIt;
5283 std::string typeName;
5286 if (llvm::isa<clang::TemplateTypeParmDecl>(nDecl)){
5287 typeName =
"typename ";
5288 if (nDecl->isParameterPack())
5290 typeName += (*prmIt)->getNameAsString();
5293 else if (
auto nttpd = llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(nDecl)){
5294 auto theType = nttpd->getType();
5297 if (theType.getAsString().find(
"enum") != std::string::npos){
5298 std::string astDump;
5299 llvm::raw_string_ostream ostream(astDump);
5300 nttpd->dump(ostream);
5302 ROOT::TMetaUtils::Warning(
nullptr,
"Forward declarations of templates with enums as template parameters. The responsible class is: %s\n", astDump.c_str());
5311 else if (
auto ttpd = llvm::dyn_cast<clang::TemplateTemplateParmDecl>(nDecl)){
5314 std::string astDump;
5315 llvm::raw_string_ostream ostream(astDump);
5316 ttpd->dump(ostream);
5318 ROOT::TMetaUtils::Error(
nullptr,
"Cannot reconstruct template template parameter forward declaration for %s\n", astDump.c_str());
5323 templateArgs += typeName;
5334 const cling::Interpreter& interpreter,
5335 std::string& defString)
5337 std::string templatePrefixString;
5338 auto tmplParamList= templDecl.getTemplateParameters();
5339 if (!tmplParamList){
5341 "Cannot extract template parameter list for %s",
5342 templDecl.getNameAsString().c_str());
5349 "Problems with arguments for forward declaration of class %s\n",
5350 templDecl.getNameAsString().c_str());
5353 templatePrefixString =
"template " + templatePrefixString +
" ";
5355 defString = templatePrefixString +
"class ";
5356 if (templDecl.isParameterPack())
5357 defString +=
"... ";
5358 defString += templDecl.getNameAsString();
5359 if (llvm::isa<clang::TemplateTemplateParmDecl>(&templDecl)) {
5373 std::string& argFwdDecl,
5374 const cling::Interpreter& interpreter,
5375 bool acceptStl=
false)
5381 if (clang::TemplateArgument::Type != arg.getKind())
return 0;
5383 auto argQualType = arg.getAsType();
5386 while (llvm::isa<clang::PointerType>(argQualType.getTypePtr())) argQualType = argQualType->getPointeeType();
5388 auto argTypePtr = argQualType.getTypePtr();
5391 if (llvm::isa<clang::EnumType>(argTypePtr)){
5396 if (llvm::isa<clang::BuiltinType>(argTypePtr)){
5401 if (
auto tdTypePtr = llvm::dyn_cast<clang::TypedefType>(argTypePtr)) {
5402 FwdDeclFromTypeDefNameDecl(*tdTypePtr->getDecl(), interpreter, argFwdDecl);
5406 if (
auto argRecTypePtr = llvm::dyn_cast<clang::RecordType>(argTypePtr)){
5408 if (
auto argRecDeclPtr = argRecTypePtr->getDecl()){
5409 FwdDeclFromRcdDecl(*argRecDeclPtr,interpreter,argFwdDecl,acceptStl);
5421 const cling::Interpreter& interpreter,
5422 std::string& defString,
5423 const std::string &normalizedName)
5427 if (
auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)) {
5428 if (
const auto *specDef = tmplSpecDeclPtr->getDefinition()) {
5429 if (specDef->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization)
5433 std::cout <<
" Forward declaring template spec " << normalizedName <<
":\n";
5434 for (
auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()) {
5435 std::string argFwdDecl;
5438 std::cout <<
" o Template argument ";
5440 std::cout <<
"successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5442 std::cout <<
"could not be treated. Abort fwd declaration generation.\n";
5449 defString += argFwdDecl +
'\n';
5451 defString +=
"template <> class " + normalizedName +
';';
5465 const cling::Interpreter& interpreter,
5466 std::string& defString,
5474 if (!recordDecl.getIdentifier())
5478 std::string argsFwdDecl;
5480 if (
auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)){
5481 std::string argFwdDecl;
5483 std::cout <<
"Class " << recordDecl.getNameAsString()
5484 <<
" is a template specialisation. Treating its arguments.\n";
5485 for(
auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()){
5488 std::cout <<
" o Template argument ";
5490 std::cout <<
"successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5492 std::cout <<
"could not be treated. Abort fwd declaration generation.\n";
5499 argsFwdDecl+=argFwdDecl;
5503 defString=argsFwdDecl;
5508 if (
auto tmplDeclPtr = tmplSpecDeclPtr->getSpecializedTemplate()){
5511 defString = argsFwdDecl +
"\n" + defString;
5516 defString =
"class " + recordDecl.getNameAsString() +
";";
5517 const clang::RecordDecl* rcd =
EncloseInScopes(recordDecl, defString);
5525 defString = argsFwdDecl +
"\n" + defString;
5536 const cling::Interpreter& interpreter,
5537 std::string& fwdDeclString,
5538 std::unordered_set<std::string>* fwdDeclSetPtr)
5540 std::string buffer = tdnDecl.getNameAsString();
5541 std::string underlyingName;
5542 auto underlyingType = tdnDecl.getUnderlyingType().getCanonicalType();
5543 if (
const clang::TagType* TT
5544 = llvm::dyn_cast<clang::TagType>(underlyingType.getTypePtr())) {
5545 if (clang::NamedDecl* ND = TT->getDecl()) {
5546 if (!ND->getIdentifier()) {
5560 if (underlyingName.find(
">::") != std::string::npos)
5563 buffer=
"typedef "+underlyingName+
" "+buffer+
";";
5575 auto& ctxt = tdnDecl.getASTContext();
5576 auto immediatelyUnderlyingType = underlyingType.getSingleStepDesugaredType(ctxt);
5578 if (
auto underlyingTdnTypePtr = llvm::dyn_cast<clang::TypedefType>(immediatelyUnderlyingType.getTypePtr())){
5579 std::string tdnFwdDecl;
5580 auto underlyingTdnDeclPtr = underlyingTdnTypePtr->getDecl();
5585 if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(tdnFwdDecl).second)
5586 fwdDeclString+=tdnFwdDecl;
5587 }
else if (
auto CXXRcdDeclPtr = immediatelyUnderlyingType->getAsCXXRecordDecl()){
5588 std::string classFwdDecl;
5590 std::cout <<
"Typedef " << tdnDecl.getNameAsString() <<
" hides a class: "
5591 << CXXRcdDeclPtr->getNameAsString() << std::endl;
5600 if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(classFwdDecl).second)
5601 fwdDeclString+=classFwdDecl;
5604 fwdDeclString+=buffer;
5616 std::string& valAsString,
5617 const clang::PrintingPolicy& ppolicy)