24#include <unordered_set>
26#include "RConfigure.h"
33#include "clang/AST/ASTContext.h"
34#include "clang/AST/Attr.h"
35#include "clang/AST/CXXInheritance.h"
36#include "clang/AST/Decl.h"
37#include "clang/AST/DeclTemplate.h"
38#include "clang/AST/Mangle.h"
39#include "clang/AST/Type.h"
40#include "clang/AST/TypeVisitor.h"
41#include "clang/Frontend/CompilerInstance.h"
42#include "clang/Lex/HeaderSearch.h"
43#include "clang/Lex/ModuleMap.h"
44#include "clang/Lex/Preprocessor.h"
45#include "clang/Lex/PreprocessorOptions.h"
47#include "clang/Sema/Sema.h"
48#include "clang/Sema/SemaDiagnostic.h"
50#include "cling/Interpreter/LookupHelper.h"
51#include "cling/Interpreter/Transaction.h"
52#include "cling/Interpreter/Interpreter.h"
53#include "cling/Utils/AST.h"
55#include "llvm/Support/Path.h"
56#include "llvm/Support/FileSystem.h"
59#include "../../../interpreter/llvm/src/tools/clang/lib/Sema/HackForDefaultTemplateArg.h"
64#define strncasecmp _strnicmp
75 llvm::SmallString<256> result_path;
76 llvm::sys::fs::real_path(path, result_path,
true);
77 return result_path.str().str();
83class TNormalizedCtxtImpl {
84 using DeclsCont_t = TNormalizedCtxt::Config_t::SkipCollection;
90 TypesCont_t fTypeWithAlternative;
91 static TemplPtrIntMap_t fTemplatePtrArgsToKeepMap;
93 TNormalizedCtxtImpl(
const cling::LookupHelper &lh);
95 const Config_t &GetConfig()
const {
return fConfig; }
96 const TypesCont_t &GetTypeWithAlternative()
const {
return fTypeWithAlternative; }
97 void AddTemplAndNargsToKeep(
const clang::ClassTemplateDecl* templ,
unsigned int i);
98 int GetNargsToKeep(
const clang::ClassTemplateDecl* templ)
const;
99 const TemplPtrIntMap_t GetTemplNargsToKeepMap()
const {
return fTemplatePtrArgsToKeepMap; }
100 void keepTypedef(
const cling::LookupHelper &lh,
const char*
name,
101 bool replace =
false);
111static clang::NestedNameSpecifier* AddDefaultParametersNNS(
const clang::ASTContext& Ctx,
112 clang::NestedNameSpecifier* scope,
113 const cling::Interpreter &interpreter,
115 if (!scope)
return 0;
117 const clang::Type* scope_type = scope->getAsType();
120 clang::NestedNameSpecifier* outer_scope = scope->getPrefix();
122 outer_scope = AddDefaultParametersNNS(Ctx, outer_scope, interpreter, normCtxt);
125 clang::QualType addDefault =
128 if (addDefault.getTypePtr() != scope_type)
129 return clang::NestedNameSpecifier::Create(Ctx,outer_scope,
131 addDefault.getTypePtr());
138static bool CheckDefinition(
const clang::CXXRecordDecl *cl,
const clang::CXXRecordDecl *context)
140 if (!cl->hasDefinition()) {
143 "Missing definition for class %s, please #include its header in the header of %s\n",
144 cl->getName().str().c_str(), context->getName().str().c_str());
147 "Missing definition for class %s\n",
148 cl->getName().str().c_str());
160static clang::NestedNameSpecifier* ReSubstTemplateArgNNS(
const clang::ASTContext &Ctxt,
161 clang::NestedNameSpecifier *scope,
162 const clang::Type *instance)
164 if (!scope)
return 0;
166 const clang::Type* scope_type = scope->getAsType();
168 clang::NestedNameSpecifier* outer_scope = scope->getPrefix();
170 outer_scope = ReSubstTemplateArgNNS(Ctxt, outer_scope, instance);
172 clang::QualType substScope =
175 scope = clang::NestedNameSpecifier::Create(Ctxt,outer_scope,
177 substScope.getTypePtr());
184static bool IsTypeInt(
const clang::Type *
type)
186 const clang::BuiltinType * builtin = llvm::dyn_cast<clang::BuiltinType>(
type->getCanonicalTypeInternal().getTypePtr());
188 return builtin->isInteger();
196static bool IsFieldDeclInt(
const clang::FieldDecl *field)
198 return IsTypeInt(field->getType().getTypePtr());
204static const clang::FieldDecl *GetDataMemberFromAll(
const clang::CXXRecordDecl &cl, llvm::StringRef
what)
206 for(clang::RecordDecl::field_iterator field_iter = cl.field_begin(), end = cl.field_end();
209 if (field_iter->getName() ==
what) {
219static bool CXXRecordDecl__FindOrdinaryMember(
const clang::CXXBaseSpecifier *Specifier,
220 clang::CXXBasePath &Path,
223 clang::RecordDecl *BaseRecord = Specifier->getType()->getAs<clang::RecordType>()->getDecl();
225 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(BaseRecord);
226 if (clxx == 0)
return false;
228 const clang::FieldDecl *found = GetDataMemberFromAll(*clxx,(
const char*)Name);
232 clang::NamedDecl* NonConstFD =
const_cast<clang::FieldDecl*
>(found);
233 clang::NamedDecl** BaseSpecFirstHack
234 =
reinterpret_cast<clang::NamedDecl**
>(NonConstFD);
235 Path.Decls = clang::DeclContextLookupResult(llvm::ArrayRef<clang::NamedDecl*>(BaseSpecFirstHack, 1));
260static const clang::FieldDecl *GetDataMemberFromAllParents(
const clang::CXXRecordDecl &cl,
const char *
what)
262 clang::CXXBasePaths Paths;
263 Paths.setOrigin(
const_cast<clang::CXXRecordDecl*
>(&cl));
264 if (cl.lookupInBases([=](
const clang::CXXBaseSpecifier *Specifier, clang::CXXBasePath &Path) {
265 return CXXRecordDecl__FindOrdinaryMember(Specifier, Path, what);}, Paths))
267 clang::CXXBasePaths::paths_iterator iter = Paths.begin();
268 if (iter != Paths.end()) {
270 const clang::FieldDecl *found = (clang::FieldDecl *)iter->Decls.data();
278cling::LookupHelper::DiagSetting ToLHDS(
bool wantDiags) {
280 ? cling::LookupHelper::WithDiagnostics
281 : cling::LookupHelper::NoDiagnostics;
288namespace TMetaUtils {
294void TNormalizedCtxtImpl::AddTemplAndNargsToKeep(
const clang::ClassTemplateDecl* templ,
297 Error(
"TNormalizedCtxt::AddTemplAndNargsToKeep",
298 "Tring to specify a number of template arguments to keep for a null pointer. Exiting without assigning any value.\n");
302 const clang::ClassTemplateDecl* canTempl = templ->getCanonicalDecl();
304 if(fTemplatePtrArgsToKeepMap.count(canTempl)==1 &&
305 fTemplatePtrArgsToKeepMap[canTempl]!=(
int)i){
306 const std::string templateName (canTempl->getNameAsString());
307 const std::string i_str (std::to_string(i));
308 const std::string previousArgsToKeep(std::to_string(fTemplatePtrArgsToKeepMap[canTempl]));
309 Error(
"TNormalizedCtxt::AddTemplAndNargsToKeep",
310 "Tring to specify for template %s %s arguments to keep, while before this number was %s\n",
311 canTempl->getNameAsString().c_str(),
313 previousArgsToKeep.c_str());
316 fTemplatePtrArgsToKeepMap[canTempl]=i;
323int TNormalizedCtxtImpl::GetNargsToKeep(
const clang::ClassTemplateDecl* templ)
const{
324 const clang::ClassTemplateDecl* constTempl = templ->getCanonicalDecl();
325 auto thePairPtr = fTemplatePtrArgsToKeepMap.find(constTempl);
326 int nArgsToKeep = (thePairPtr != fTemplatePtrArgsToKeepMap.end() ) ? thePairPtr->second : -1;
334 fImpl(new TNormalizedCtxtImpl(lh))
338 fImpl(new TNormalizedCtxtImpl(*other.fImpl))
345 return fImpl->GetConfig();
348 return fImpl->GetTypeWithAlternative();
352 return fImpl->AddTemplAndNargsToKeep(templ, i);
356 return fImpl->GetNargsToKeep(templ);
359 return fImpl->GetTemplNargsToKeepMap();
364 return fImpl->keepTypedef(lh,
name, replace);
368 const std::string &normalizedName)
372 if (normalizedName.find(
"Double32_t") != std::string::npos
373 || normalizedName.find(
"Float16_t") != std::string::npos)
375 std::unique_ptr<clang::MangleContext> mangleCtx(rDecl->getASTContext().createMangleContext());
376 std::string mangledName;
378 llvm::raw_string_ostream sstr(mangledName);
379 if (
const clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(rDecl)) {
380 mangleCtx->mangleCXXRTTI(clang::QualType(TD->getTypeForDecl(), 0), sstr);
383 if (!mangledName.empty()) {
386 if (mangledName[0] ==
'\01')
387 mangledName.erase(0, 1);
389 if (!errDemangle && demangledTIName) {
390 static const char typeinfoNameFor[] =
" `RTTI Type Descriptor'";
391 if (strstr(demangledTIName, typeinfoNameFor)) {
392 std::string demangledName = demangledTIName;
393 demangledName.erase(demangledName.end() - strlen(typeinfoNameFor), demangledName.end());
396 if (!errDemangle && demangledTIName) {
397 static const char typeinfoNameFor[] =
"typeinfo for ";
398 if (!strncmp(demangledTIName, typeinfoNameFor, strlen(typeinfoNameFor))) {
399 std::string demangledName = demangledTIName + strlen(typeinfoNameFor);
401 free(demangledTIName);
402 return demangledName;
406 "Demangled typeinfo name '%s' does not contain `RTTI Type Descriptor'\n",
410 "Demangled typeinfo name '%s' does not start with 'typeinfo for'\n",
415 free(demangledTIName);
426 const clang::RecordDecl *decl,
429 bool rRequestNoInputOperator,
430 bool rRequestOnlyTClass,
431 int rRequestedVersionNumber,
432 const cling::Interpreter &interpreter,
445 const clang::Type *requestedType,
446 const clang::RecordDecl *decl,
447 const char *requestName,
448 unsigned int nTemplateArgsToSkip,
451 bool rRequestNoInputOperator,
452 bool rRequestOnlyTClass,
453 int rRequestVersionNumber,
454 const cling::Interpreter &interpreter,
456 fRuleIndex(index), fDecl(decl), fRequestedName(
""), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer),
457 fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber)
466 "Could not remove the requested template arguments.\n");
475 const clang::Type *requestedType,
476 const clang::RecordDecl *decl,
477 const char *requestName,
480 bool rRequestNoInputOperator,
481 bool rRequestOnlyTClass,
482 int rRequestVersionNumber,
483 const cling::Interpreter &interpreter,
485 fRuleIndex(index), fDecl(decl), fRequestedName(
""), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer),
486 fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber)
500 const clang::RecordDecl *decl,
501 const char *requestName,
504 bool rRequestNoInputOperator,
505 bool rRequestOnlyTClass,
506 int rRequestVersionNumber,
507 const cling::Interpreter &interpreter,
509 fRuleIndex(index), fDecl(decl), fRequestedName(
""), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer), fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber)
518 if (requestName && requestName[0]) {
533 ExistingTypeCheck_t existingTypeCheck,
534 AutoParse_t autoParse,
535 bool *shuttingDownPtr,
536 const int* pgDebug ):
537 fInterpreter(&interpreter),fNormalizedCtxt(&normCtxt),
538 fExistingTypeCheck(existingTypeCheck),
539 fAutoParse(autoParse),
540 fInterpreterIsShuttingDownPtr(shuttingDownPtr),
552 if (tname.empty())
return false;
562 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
563 clang::QualType t = lh.findType(nameLong, ToLHDS(
WantDiags()));
566 if (!
dest.isNull() && (
dest != t)) {
569 dest.getAsStringInternal(nameLong,
fInterpreter->getCI()->getASTContext().getPrintingPolicy());
577 const std::string &nameLong)
579 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
580 clang::QualType t = lh.findType(nondef.c_str(), ToLHDS(
WantDiags()));
583 if (!
dest.isNull() && (
dest != t) &&
584 nameLong == t.getAsString(
fInterpreter->getCI()->getASTContext().getPrintingPolicy()))
594 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
595 const clang::Decl *scope = lh.findScope(base.c_str(), ToLHDS(
WantDiags()), 0);
602 const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(scope);
603 isInlined = nsdecl && nsdecl->isInline();
615 if (tname.empty())
return false;
623 return ! result.empty();
632 const cling::LookupHelper& lh =
fInterpreter->getLookupHelper();
633 clang::QualType t = lh.findType(tname.c_str(), ToLHDS(
WantDiags()));
644 clang::PrintingPolicy policy(
fInterpreter->getCI()->getASTContext().getPrintingPolicy());
645 policy.SuppressTagKeyword =
true;
646 policy.SuppressScope =
true;
652 dest.getAsStringInternal(result, policy);
654 unsigned long offset = 0;
655 if (strncmp(result.c_str(),
"const ", 6) == 0) {
658 if (dropstd && strncmp(result.c_str()+offset,
"std::", 5) == 0) {
659 result.erase(offset,5);
661 for(
unsigned int i = 1; i<result.length(); ++i) {
662 if (result[i]==
's') {
663 if (result[i-1]==
'<' || result[i-1]==
',' || result[i-1]==
' ') {
664 if (dropstd && result.compare(i,5,
"std::",5) == 0) {
669 if (result[i]==
' ') {
670 if (result[i-1] ==
',') {
673 }
else if ( (i+1) < result.length() &&
674 (result[i+1]==
'*' || result[i+1]==
'&' || result[i+1]==
'[') ) {
708void ROOT::TMetaUtils::TNormalizedCtxtImpl::keepTypedef(
const cling::LookupHelper &lh,
711 clang::QualType toSkip = lh.findType(
name, cling::LookupHelper::WithDiagnostics);
712 if (
const clang::Type* T = toSkip.getTypePtr()) {
713 const clang::TypedefType *
tt = llvm::dyn_cast<clang::TypedefType>(T);
715 clang::Decl* D =
tt->getDecl();
716 fConfig.m_toSkip.insert(D);
718 clang::QualType canon = toSkip->getCanonicalTypeInternal();
719 fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),T));
721 fTypeWithAlternative.insert(T);
732ROOT::TMetaUtils::TNormalizedCtxtImpl::TNormalizedCtxtImpl(
const cling::LookupHelper &lh)
734 keepTypedef(lh,
"Double32_t");
735 keepTypedef(lh,
"Float16_t");
736 keepTypedef(lh,
"Long64_t",
true);
737 keepTypedef(lh,
"ULong64_t",
true);
739 clang::QualType toSkip = lh.findType(
"string", cling::LookupHelper::WithDiagnostics);
740 if (!toSkip.isNull()) {
741 if (
const clang::TypedefType* TT
742 = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
743 fConfig.m_toSkip.insert(TT->getDecl());
745 toSkip = lh.findType(
"std::string", cling::LookupHelper::WithDiagnostics);
746 if (!toSkip.isNull()) {
747 if (
const clang::TypedefType* TT
748 = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
749 fConfig.m_toSkip.insert(TT->getDecl());
751 clang::QualType canon = toSkip->getCanonicalTypeInternal();
752 fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),toSkip.getTypePtr()));
757TNCtxtFullQual::TemplPtrIntMap_t TNCtxtFullQual::fTemplatePtrArgsToKeepMap=TNCtxtFullQual::TemplPtrIntMap_t{};
763 return (cl.getKind() == clang::Decl::ClassTemplatePartialSpecialization
764 || cl.getKind() == clang::Decl::ClassTemplateSpecialization);
771 const cling::Interpreter& interp)
773 clang::Sema* S = &interp.getSema();
774 const clang::NamedDecl* ND = cling::utils::Lookup::Named(S,
name, cl);
775 if (ND == (clang::NamedDecl*)-1)
776 return (clang::FunctionDecl*)-1;
777 return llvm::dyn_cast_or_null<clang::FunctionDecl>(ND);
783const clang::CXXRecordDecl *
785 bool ,
const clang::Type** resultType)
787 const cling::LookupHelper& lh = interp.getLookupHelper();
790 const clang::CXXRecordDecl *result
791 = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
792 (lh.findScope(
name, cling::LookupHelper::NoDiagnostics, resultType));
794 std::string std_name(
"std::");
798 result = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
799 (lh.findScope(std_name, cling::LookupHelper::NoDiagnostics, resultType));
809 clang::QualType qType(cl->getTypeForDecl(),0);
817 clang::Sema& S = interp.getCI()->getSema();
820 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interp));
821 return S.RequireCompleteType(Loc, Type, clang::diag::err_incomplete_type);
827 const clang::CXXRecordDecl *context,
const cling::Interpreter &interp)
833 if (!cl->getDefinition() || !cl->isCompleteDefinition()) {
837 if (!CheckDefinition(cl, context) || !CheckDefinition(base, context)) {
841 if (!base->hasDefinition()) {
845 return cl->isDerivedFrom(base);
857 const clang::NamedDecl *base
861 return IsBase(CRD, llvm::dyn_cast<clang::CXXRecordDecl>( base ),
862 llvm::dyn_cast<clang::CXXRecordDecl>(
m.getDeclContext()),interp);
870 const clang::NamedDecl &forcontext,
871 const clang::QualType &qti,
872 const char *R__t,
int rwmode,
873 const cling::Interpreter &interp,
876 static const clang::CXXRecordDecl *TObject_decl
879 kBIT_ISTOBJECT = 0x10000000,
880 kBIT_HASSTREAMER = 0x20000000,
881 kBIT_ISSTRING = 0x40000000,
883 kBIT_ISPOINTER = 0x00001000,
884 kBIT_ISFUNDAMENTAL = 0x00000020,
885 kBIT_ISENUM = 0x00000008
888 const clang::Type &ti( * qti.getTypePtr() );
898 clang::CXXRecordDecl *cxxtype = rawtype->getAsCXXRecordDecl() ;
900 int isTObj = cxxtype && (
IsBase(cxxtype,TObject_decl,
nullptr,interp) || rawname ==
"TObject");
904 if (ti.isPointerType()) kase |= kBIT_ISPOINTER;
905 if (rawtype->isFundamentalType()) kase |= kBIT_ISFUNDAMENTAL;
906 if (rawtype->isEnumeralType()) kase |= kBIT_ISENUM;
909 if (isTObj) kase |= kBIT_ISTOBJECT;
910 if (isStre) kase |= kBIT_HASSTREAMER;
911 if (tiName ==
"string") kase |= kBIT_ISSTRING;
912 if (tiName ==
"string*") kase |= kBIT_ISSTRING;
916 tcl =
" internal error in rootcling ";
922 if (R__t) finalString <<
" " << tiName <<
" " << R__t <<
";" << std::endl;
925 case kBIT_ISFUNDAMENTAL:
927 finalString <<
" R__b >> " << R__t <<
";" << std::endl;
930 case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
932 finalString <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl;
941 finalString <<
" Int_t readtemp;" << std::endl
942 <<
" R__b >> readtemp;" << std::endl
943 <<
" " << R__t <<
" = static_cast<" << tiName <<
">(readtemp);" << std::endl;
946 case kBIT_HASSTREAMER:
947 case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
949 finalString <<
" " << R__t <<
".Streamer(R__b);" << std::endl;
952 case kBIT_HASSTREAMER|kBIT_ISPOINTER:
955 finalString <<
" if (R__b.GetInfo() && R__b.GetInfo()->GetOldVersion()<=3) {" << std::endl;
956 if (cxxtype && cxxtype->isAbstract()) {
957 finalString <<
" R__ASSERT(0);// " << objType <<
" is abstract. We assume that older file could not be produced using this streaming method." << std::endl;
959 finalString <<
" " << R__t <<
" = new " << objType <<
";" << std::endl
960 <<
" " << R__t <<
"->Streamer(R__b);" << std::endl;
962 finalString <<
" } else {" << std::endl
963 <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl
964 <<
" }" << std::endl;
969 finalString <<
" {TString R__str;" << std::endl
970 <<
" R__str.Streamer(R__b);" << std::endl
971 <<
" " << R__t <<
" = R__str.Data();}" << std::endl;
974 case kBIT_ISSTRING|kBIT_ISPOINTER:
976 finalString <<
" {TString R__str;" << std::endl
977 <<
" R__str.Streamer(R__b);" << std::endl
978 <<
" " << R__t <<
" = new string(R__str.Data());}" << std::endl;
983 finalString <<
" " << R__t <<
" = (" << tiName <<
")R__b.ReadObjectAny(" << tcl <<
");" << std::endl;
988 finalString <<
" R__b.StreamObject(&" << R__t <<
"," << tcl <<
");" << std::endl;
996 case kBIT_ISFUNDAMENTAL:
997 case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
999 finalString <<
" R__b << " << R__t <<
";" << std::endl;
1003 if (!R__t)
return 0;
1004 finalString <<
" { void *ptr_enum = (void*)&" << R__t <<
";\n";
1005 finalString <<
" R__b >> *reinterpret_cast<Int_t*>(ptr_enum); }" << std::endl;
1008 case kBIT_HASSTREAMER:
1009 case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
1010 if (!R__t)
return 0;
1011 finalString <<
" ((" << objType <<
"&)" << R__t <<
").Streamer(R__b);" << std::endl;
1014 case kBIT_HASSTREAMER|kBIT_ISPOINTER:
1015 if (!R__t)
return 1;
1016 finalString <<
" R__b.WriteObjectAny(" << R__t <<
"," << tcl <<
");" << std::endl;
1020 if (!R__t)
return 0;
1021 finalString <<
" {TString R__str(" << R__t <<
".c_str());" << std::endl
1022 <<
" R__str.Streamer(R__b);};" << std::endl;
1025 case kBIT_ISSTRING|kBIT_ISPOINTER:
1026 if (!R__t)
return 0;
1027 finalString <<
" {TString R__str(" << R__t <<
"->c_str());" << std::endl
1028 <<
" R__str.Streamer(R__b);}" << std::endl;
1031 case kBIT_ISPOINTER:
1032 if (!R__t)
return 1;
1033 finalString <<
" R__b.WriteObjectAny(" << R__t <<
"," << tcl <<
");" << std::endl;
1037 if (!R__t)
return 1;
1038 finalString <<
" R__b.StreamObject((" << objType <<
"*)&" << R__t <<
"," << tcl <<
");" << std::endl;
1050 clang::CXXRecordDecl* ncCl =
const_cast<clang::CXXRecordDecl*
>(cl);
1053 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
1055 if (
auto* Ctor = interpreter.getCI()->getSema().LookupDefaultConstructor(ncCl)) {
1056 if (Ctor->getAccess() == clang::AS_public && !Ctor->isDeleted()) {
1069 const char *typeOfArg,
1070 const clang::CXXRecordDecl *expectedArgType,
1071 const cling::Interpreter& interpreter)
1073 if (typeOfArg && !expectedArgType) {
1074 const cling::LookupHelper& lh = interpreter.getLookupHelper();
1077 clang::QualType instanceType = lh.findType(typeOfArg, cling::LookupHelper::WithDiagnostics);
1078 if (!instanceType.isNull())
1079 expectedArgType = instanceType->getAsCXXRecordDecl();
1082 if (!expectedArgType)
1083 return EIOCtorCategory::kAbsent;
1086 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
1087 for (
auto iter = cl->ctor_begin(), end = cl->ctor_end(); iter != end; ++iter)
1089 if ((iter->getAccess() != clang::AS_public) || (iter->getNumParams() != 1))
1093 clang::QualType argType((*iter->param_begin())->getType());
1094 argType = argType.getDesugaredType(cl->getASTContext());
1096 auto ioCtorCategory = EIOCtorCategory::kAbsent;
1097 if (argType->isPointerType()) {
1098 ioCtorCategory = EIOCtorCategory::kIOPtrType;
1099 argType = argType->getPointeeType();
1100 }
else if (argType->isReferenceType()) {
1101 ioCtorCategory = EIOCtorCategory::kIORefType;
1102 argType = argType.getNonReferenceType();
1106 argType = argType.getDesugaredType(cl->getASTContext());
1107 const clang::CXXRecordDecl *argDecl = argType->getAsCXXRecordDecl();
1109 if (argDecl->getCanonicalDecl() == expectedArgType->getCanonicalDecl()) {
1110 return ioCtorCategory;
1113 std::string realArg = argType.getAsString();
1114 std::string clarg(
"class ");
1116 if (realArg == clarg)
1117 return ioCtorCategory;
1121 return EIOCtorCategory::kAbsent;
1130 const cling::Interpreter& interpreter)
1132 const char *arg = ioctortype.
GetName();
1134 if (!ioctortype.
GetType() && (!arg || !arg[0])) {
1147 const char *method,
const char *
proto,
1148 const cling::Interpreter &interp,
1151 const clang::FunctionDecl* funcD
1152 = interp.getLookupHelper().findFunctionProto(cinfo, method,
proto,
1153 diagnose ? cling::LookupHelper::WithDiagnostics
1154 : cling::LookupHelper::NoDiagnostics);
1156 return llvm::dyn_cast<const clang::CXXMethodDecl>(funcD);
1165 namespace TMetaUtils {
1168 const cling::LookupHelper& lh = interp.getLookupHelper();
1171 clang::QualType instanceType = lh.findType(type_of_arg, cling::LookupHelper::WithDiagnostics);
1172 if (!instanceType.isNull())
1173 fArgType = instanceType->getAsCXXRecordDecl();
1187 const cling::Interpreter &interp)
1189 if (cl->isAbstract())
return false;
1191 for (
auto & ctorType : ctorTypes) {
1195 if (EIOCtorCategory::kAbsent == ioCtorCat)
1198 std::string
proto( ctorType.GetName() );
1199 bool defaultCtor =
proto.empty();
1205 if (EIOCtorCategory::kIOPtrType == ioCtorCat) {
1207 }
else if (EIOCtorCategory::kIORefType == ioCtorCat) {
1211 arg +=
")nullptr )";
1214 const clang::CXXMethodDecl *method
1216 cling::LookupHelper::NoDiagnostics);
1217 if (method && method->getAccess() != clang::AS_public) {
1231 const cling::Interpreter& interp)
1233 if (!cl)
return false;
1235 if (cl->hasUserDeclaredDestructor()) {
1237 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interp));
1238 clang::CXXDestructorDecl *
dest = cl->getDestructor();
1240 return (
dest->getAccess() == clang::AS_public);
1252 const char *methodname,
1254 const cling::Interpreter &interp,
1257 const clang::CXXMethodDecl *method
1259 diagnose ? cling::LookupHelper::WithDiagnostics
1260 : cling::LookupHelper::NoDiagnostics);
1261 return (method && method->getAccess() == clang::AS_public);
1272 const char *
proto =
"TDirectory*";
1273 const char *
name =
"DirectoryAutoAdd";
1287 const char *
proto =
"TCollection*,TFileMergeInfo*";
1288 const char *
name =
"Merge";
1301 const char *
proto =
"TCollection*";
1302 const char *
name =
"Merge";
1317 const char *
proto =
"TFileMergeInfo*";
1318 const char *
name =
"ResetAfterMerge";
1328 const clang::CXXRecordDecl* clxx,
1329 const cling::Interpreter &interp,
1332 static const char *
proto =
"TBuffer&";
1334 const clang::CXXMethodDecl *method
1336 cling::LookupHelper::NoDiagnostics);
1337 const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1339 return (method && method->getDeclContext() == clxx_as_context
1347 const clang::CXXRecordDecl* clxx,
1348 const cling::Interpreter &interp,
1351 static const char *
proto =
"TBuffer&,TClass*";
1353 const clang::CXXMethodDecl *method
1355 cling::LookupHelper::NoDiagnostics);
1356 const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1358 return (method && method->getDeclContext() == clxx_as_context
1388 clang::QualType qualType(&
type,0);
1420 llvm::raw_string_ostream stream(qual_name);
1421 clang::PrintingPolicy policy( cl.getASTContext().getPrintingPolicy() );
1422 policy.SuppressTagKeyword =
true;
1423 policy.SuppressUnwrittenScope =
true;
1425 cl.getNameForDiagnostic(stream,policy,
true);
1428 if ( qual_name ==
"(anonymous " ) {
1429 size_t pos = qual_name.find(
':');
1430 qual_name.erase(0,pos+2);
1446 const clang::Type* declType ( recordDecl.getTypeForDecl() );
1447 clang::QualType qualType(declType,0);
1481 std::stringstream dims;
1482 std::string typenameStr;
1484 const clang::ASTContext& astContext = cl.getASTContext();
1487 for(clang::RecordDecl::field_iterator field_iter = cl.field_begin(), end = cl.field_end();
1495 typenameStr.clear();
1499 clang::QualType fieldType(field_iter->getType());
1500 if (fieldType->isConstantArrayType()) {
1501 const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(fieldType.getTypePtr());
1503 dims <<
"[" << arrayType->getSize().getLimitedValue() <<
"]";
1504 fieldType = arrayType->getElementType();
1505 arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1515 for(clang::CXXRecordDecl::base_class_const_iterator iter = cl.bases_begin(), end = cl.bases_end();
1518 std::string basename( iter->getType()->getAsCXXRecordDecl()->getNameAsString() );
1528 const cling::Interpreter &interp,
1531 return interp.getLookupHelper().findFunctionProto(cinfo, method,
proto,
1532 diagnose ? cling::LookupHelper::WithDiagnostics
1533 : cling::LookupHelper::NoDiagnostics);
1567 clang::SourceLocation sourceLocation = decl->getLocation();
1568 clang::SourceManager& sourceManager = decl->getASTContext().getSourceManager();
1570 if (!sourceLocation.isValid() ) {
1574 if (!sourceLocation.isFileID()) {
1575 sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
1578 if (sourceLocation.isValid() && sourceLocation.isFileID()) {
1579 return sourceManager.getLineNumber(sourceManager.getFileID(sourceLocation),sourceManager.getFileOffset(sourceLocation));
1592 while (llvm::isa<clang::PointerType>(instanceType.getTypePtr())
1593 || llvm::isa<clang::ReferenceType>(instanceType.getTypePtr()))
1595 instanceType = instanceType->getPointeeType();
1598 const clang::ElaboratedType* etype
1599 = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
1601 instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
1613 bool result =
false;
1614 const clang::CXXRecordDecl* clxx = instanceType->getAsCXXRecordDecl();
1615 if (clxx && clxx->getTemplateSpecializationKind() != clang::TSK_Undeclared) {
1617 const clang::TemplateSpecializationType* TST
1618 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
1625 for(clang::TemplateSpecializationType::iterator
1626 I = TST->begin(), E = TST->end();
1629 if (
I->getKind() == clang::TemplateArgument::Type) {
1644 const cling::Interpreter &interp,
1647 const clang::CXXRecordDecl* clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
1648 if (clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared)
return 0;
1650 clang::QualType instanceType = interp.getLookupHelper().findType(cl.
GetNormalizedName(),
1651 cling::LookupHelper::WithDiagnostics);
1652 if (instanceType.isNull()) {
1665 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(attribute);
1670 attrString = annAttr->getAnnotation();
1679 size_t substrFound (attributeStr.find(propNames::separator));
1680 if (substrFound==std::string::npos) {
1684 size_t EndPart1 = attributeStr.find_first_of(propNames::separator) ;
1685 attrName = attributeStr.substr(0, EndPart1);
1686 const int separatorLength(propNames::separator.size());
1687 attrValue = attributeStr.substr(EndPart1 + separatorLength);
1695 std::string attrString;
1697 if (0!=ret)
return ret;
1705 const std::string& propName,
1706 std::string& propValue)
1708 for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1709 attrIt!=decl.attr_end();++attrIt){
1710 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1711 if (!annAttr)
continue;
1713 llvm::StringRef attribute = annAttr->getAnnotation();
1714 std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1715 if (split.first != propName.c_str())
continue;
1717 propValue = split.second;
1728 const std::string& propName,
1731 for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1732 attrIt!=decl.attr_end();++attrIt){
1733 clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1734 if (!annAttr)
continue;
1736 llvm::StringRef attribute = annAttr->getAnnotation();
1737 std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1738 if (split.first != propName.c_str())
continue;
1740 return split.second.getAsInteger(10,propValue);
1751 const clang::CXXRecordDecl *decl,
1752 const cling::Interpreter &interp,
1755 bool& needCollectionProxy)
1759 std::string mappedname;
1761 std::string csymbol = classname;
1769 csymbol.insert(0,
"::");
1775 bool isStd = TMetaUtils::IsStdClass(*decl);
1776 const cling::LookupHelper& lh = interp.getLookupHelper();
1777 bool isString = TMetaUtils::IsOfType(*decl,
"std::string",lh);
1779 bool isStdNotString = isStd && !isString;
1781 finalString <<
"namespace ROOT {" <<
"\n";
1785 finalString <<
" static TClass *" << mappedname.c_str() <<
"_Dictionary();\n"
1786 <<
" static void " << mappedname.c_str() <<
"_TClassManip(TClass*);\n";
1792 finalString <<
" static void *new_" << mappedname.c_str() <<
"(void *p = 0);" <<
"\n";
1796 finalString <<
" static void *newArray_";
1797 finalString << mappedname.c_str();
1798 finalString <<
"(Long_t size, void *p);";
1799 finalString <<
"\n";
1804 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";
1807 finalString <<
" static void directoryAutoAdd_" << mappedname.c_str() <<
"(void *obj, TDirectory *dir);" <<
"\n";
1810 finalString <<
" static void streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj);" <<
"\n";
1813 finalString <<
" static void conv_streamer_" << mappedname.c_str() <<
"(TBuffer &buf, void *obj, const TClass*);" <<
"\n";
1816 finalString <<
" static Long64_t merge_" << mappedname.c_str() <<
"(void *obj, TCollection *coll,TFileMergeInfo *info);" <<
"\n";
1819 finalString <<
" static void reset_" << mappedname.c_str() <<
"(void *obj, TFileMergeInfo *info);" <<
"\n";
1826 ROOT::SchemaRuleClassMap_t::iterator rulesIt1 =
ROOT::gReadRules.find( classname.c_str() );
1827 ROOT::SchemaRuleClassMap_t::iterator rulesIt2 =
ROOT::gReadRawRules.find( classname.c_str() );
1838 finalString <<
"\n // Schema evolution read functions\n";
1839 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt1->second.begin();
1840 while( rIt != rulesIt1->second.end() ) {
1846 std::string error_string;
1848 Warning(0,
"%s", error_string.c_str());
1849 rIt = rulesIt1->second.erase(rIt);
1857 if( rIt->find(
"code" ) != rIt->end() ) {
1873 finalString <<
"\n // Schema evolution read raw functions\n";
1874 std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt2->second.begin();
1875 while( rIt != rulesIt2->second.end() ) {
1881 std::string error_string;
1883 Warning(0,
"%s", error_string.c_str());
1884 rIt = rulesIt2->second.erase(rIt);
1892 if( rIt->find(
"code" ) == rIt->end() )
1900 finalString <<
"\n" <<
" // Function generating the singleton type initializer" <<
"\n";
1902 finalString <<
" static TGenericClassInfo *GenerateInitInstanceLocal(const " << csymbol <<
"*)" <<
"\n" <<
" {" <<
"\n";
1904 finalString <<
" " << csymbol <<
" *ptr = 0;" <<
"\n";
1908 finalString <<
" static ::TVirtualIsAProxy* isa_proxy = new ::TInstrumentedIsAProxy< " << csymbol <<
" >(0);" <<
"\n";
1911 finalString <<
" static ::TVirtualIsAProxy* isa_proxy = new ::TIsAProxy(typeid(" << csymbol <<
"));" <<
"\n";
1913 finalString <<
" static ::ROOT::TGenericClassInfo " <<
"\n" <<
" instance(\"" << classname.c_str() <<
"\", ";
1916 finalString << csymbol <<
"::Class_Version(), ";
1918 finalString <<
"2, ";
1920 finalString <<
"-2, ";
1926 static const char *versionFunc =
"GetClassVersion";
1930 std::string
proto = classname +
"*";
1931 const clang::Decl* ctxt = llvm::dyn_cast<clang::Decl>((*cl).getDeclContext());
1932 const clang::FunctionDecl *methodinfo
1934 interp, cling::LookupHelper::NoDiagnostics);
1942 finalString <<
"GetClassVersion< ";
1943 finalString << classname.c_str();
1944 finalString <<
" >(), ";
1952 if (filename.length() > 0) {
1953 for (
unsigned int i=0; i<filename.length(); i++) {
1954 if (filename[i]==
'\\') filename[i]=
'/';
1958 <<
"," <<
"\n" <<
" typeid(" << csymbol
1959 <<
"), ::ROOT::Internal::DefineBehavior(ptr, ptr)," <<
"\n" <<
" ";
1962 finalString <<
"&" << csymbol <<
"::Dictionary, ";
1964 finalString <<
"&" << mappedname <<
"_Dictionary, ";
1968 TClassTable__kHasCustomStreamerMember = 0x10
1973 rootflag = rootflag | TClassTable__kHasCustomStreamerMember;
1975 finalString <<
"isa_proxy, " << rootflag <<
"," <<
"\n" <<
" sizeof(" << csymbol <<
") );" <<
"\n";
1977 finalString <<
" instance.SetNew(&new_" << mappedname.c_str() <<
");" <<
"\n";
1979 finalString <<
" instance.SetNewArray(&newArray_" << mappedname.c_str() <<
");" <<
"\n";
1982 finalString <<
" instance.SetDelete(&delete_" << mappedname.c_str() <<
");" <<
"\n" <<
" instance.SetDeleteArray(&deleteArray_" << mappedname.c_str() <<
");" <<
"\n" <<
" instance.SetDestructor(&destruct_" << mappedname.c_str() <<
");" <<
"\n";
1985 finalString <<
" instance.SetDirectoryAutoAdd(&directoryAutoAdd_" << mappedname.c_str() <<
");" <<
"\n";
1989 finalString <<
" instance.SetStreamerFunc(&streamer_" << mappedname.c_str() <<
");" <<
"\n";
1993 finalString <<
" instance.SetConvStreamerFunc(&conv_streamer_" << mappedname.c_str() <<
");" <<
"\n";
1996 finalString <<
" instance.SetMerge(&merge_" << mappedname.c_str() <<
");" <<
"\n";
1999 finalString <<
" instance.SetResetAfterMerge(&reset_" << mappedname.c_str() <<
");" <<
"\n";
2002 finalString <<
" instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" <<
"Pushback" <<
"<Internal::TStdBitsetHelper< " << classname.c_str() <<
" > >()));" <<
"\n";
2004 needCollectionProxy =
true;
2005 }
else if (stl != 0 &&
2008 int idx = classname.find(
"<");
2010 const char* methodTCP=0;
2015 methodTCP=
"Pushback";
2018 methodTCP=
"Pushfront";
2024 methodTCP=
"MapInsert";
2036 finalString <<
" instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP <<
"< " << classNameForIO.c_str() <<
" >()));" <<
"\n";
2038 needCollectionProxy =
true;
2046 finalString <<
"\n" <<
" ::ROOT::AddClassAlternate(\""
2053 finalString <<
"\n" <<
" ::ROOT::AddClassAlternate(\""
2063 finalString <<
"\n" <<
" ::ROOT::Internal::TSchemaHelper* rule;" <<
"\n";
2067 finalString <<
"\n" <<
" // the io read rules" <<
"\n" <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrules(" << rulesIt1->second.size() <<
");" <<
"\n";
2069 finalString <<
" instance.SetReadRules( readrules );" <<
"\n";
2073 finalString <<
"\n" <<
" // the io read raw rules" <<
"\n" <<
" std::vector<::ROOT::Internal::TSchemaHelper> readrawrules(" << rulesIt2->second.size() <<
");" <<
"\n";
2075 finalString <<
" instance.SetReadRawRules( readrawrules );" <<
"\n";
2078 finalString <<
" return &instance;" <<
"\n" <<
" }" <<
"\n";
2082 finalString <<
" TGenericClassInfo *GenerateInitInstance(const " << csymbol <<
"*)" <<
"\n" <<
" {\n return GenerateInitInstanceLocal((" << csymbol <<
"*)0);\n }" <<
"\n";
2085 finalString <<
" // Static variable to force the class initialization" <<
"\n";
2089 finalString <<
" static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstanceLocal((const " << csymbol <<
"*)0x0); R__UseDummy(_R__UNIQUE_DICT_(Init));" <<
"\n";
2092 finalString <<
"\n" <<
" // Dictionary for non-ClassDef classes" <<
"\n"
2093 <<
" static TClass *" << mappedname <<
"_Dictionary() {\n"
2094 <<
" TClass* theClass ="
2095 <<
"::ROOT::GenerateInitInstanceLocal((const " << csymbol <<
"*)0x0)->GetClass();\n"
2096 <<
" " << mappedname <<
"_TClassManip(theClass);\n";
2097 finalString <<
" return theClass;\n";
2098 finalString <<
" }\n\n";
2102 std::string manipString;
2103 std::string attribute_s;
2104 std::string attrName, attrValue;
2106 bool attrMapExtracted =
false;
2107 if (decl->hasAttrs()){
2109 for (clang::Decl::attr_iterator attrIt = decl->attr_begin();
2110 attrIt!=decl->attr_end();++attrIt){
2117 if (attrName ==
"name" ||
2118 attrName ==
"pattern" ||
2119 attrName ==
"rootmap")
continue;
2125 if (!attrMapExtracted){
2126 manipString+=
" theClass->CreateAttributeMap();\n";
2127 manipString+=
" TDictAttributeMap* attrMap( theClass->GetAttributeMap() );\n";
2128 attrMapExtracted=
true;
2130 manipString+=
" attrMap->AddProperty(\""+attrName +
"\",\""+attrValue+
"\");\n";
2136 for(clang::CXXRecordDecl::decl_iterator internalDeclIt = decl->decls_begin();
2137 internalDeclIt != decl->decls_end(); ++internalDeclIt){
2138 if (!(!(*internalDeclIt)->isImplicit()
2139 && (clang::isa<clang::FieldDecl>(*internalDeclIt) ||
2140 clang::isa<clang::VarDecl>(*internalDeclIt))))
continue;
2143 if (!internalDeclIt->hasAttrs())
continue;
2145 attrMapExtracted =
false;
2146 bool memberPtrCreated =
false;
2148 for (clang::Decl::attr_iterator attrIt = internalDeclIt->attr_begin();
2149 attrIt!=internalDeclIt->attr_end();++attrIt){
2157 clang::NamedDecl* namedInternalDecl = clang::dyn_cast<clang::NamedDecl> (*internalDeclIt);
2158 if (!namedInternalDecl) {
2159 TMetaUtils::Error(0,
"Cannot convert field declaration to clang::NamedDecl");
2162 const std::string memberName(namedInternalDecl->getName());
2163 const std::string cppMemberName=
"theMember_"+memberName;
2166 const std::string dataMemberCreation=
" TDataMember* "+cppMemberName+
" = theClass->GetDataMember(\""+memberName+
"\");\n";
2175 if (attrName == propNames::comment ||
2176 attrName == propNames::iotype ||
2177 attrName == propNames::ioname )
continue;
2179 if (!memberPtrCreated){
2180 manipString+=dataMemberCreation;
2181 memberPtrCreated=
true;
2184 if (!attrMapExtracted){
2185 manipString+=
" "+cppMemberName+
"->CreateAttributeMap();\n";
2186 manipString+=
" TDictAttributeMap* memberAttrMap_"+memberName+
"( theMember_"+memberName+
"->GetAttributeMap() );\n";
2187 attrMapExtracted=
true;
2190 manipString+=
" memberAttrMap_"+memberName+
"->AddProperty(\""+attrName +
"\",\""+attrValue+
"\");\n";
2197 finalString <<
" static void " << mappedname <<
"_TClassManip(TClass* " << (manipString.empty() ?
"":
"theClass") <<
"){\n"
2202 finalString <<
"} // end of namespace ROOT" <<
"\n" <<
"\n";
2212 std::string &clsname,
2213 std::string &nsname,
2214 const clang::CXXRecordDecl *cl)
2224 auto ctxt = cl->getEnclosingNamespaceContext();
2225 while(ctxt && ctxt!=cl && ctxt->isInlineNamespace()) {
2226 ctxt = ctxt->getParent();
2229 const clang::NamedDecl *namedCtxt = llvm::dyn_cast<clang::NamedDecl>(ctxt);
2230 if (namedCtxt && namedCtxt!=cl) {
2231 const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(namedCtxt);
2232 if (nsdecl != 0 && !nsdecl->isAnonymousNamespace()) {
2234 clsname.erase (0, nsname.size() + 2);
2246 const clang::DeclContext *ctxt = cl.getDeclContext();
2247 while(ctxt && !ctxt->isNamespace()) {
2248 ctxt = ctxt->getParent();
2262 int closing_brackets = 0;
2266 if (ctxt && ctxt->isNamespace()) {
2271 const clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(ctxt);
2274 out <<
"namespace " << ns->getNameAsString() <<
" {" << std::endl;
2278 return closing_brackets;
2292 clang::TemplateSpecializationKind kind = cl->getTemplateSpecializationKind();
2293 if (kind == clang::TSK_Undeclared ) {
2296 }
else if (kind == clang::TSK_ExplicitSpecialization) {
2310 const char *
name = which;
2311 const char *
proto =
"size_t";
2312 const char *protoPlacement =
"size_t,void*";
2315 const clang::FunctionDecl *operatornew
2318 cling::LookupHelper::NoDiagnostics);
2319 const clang::FunctionDecl *operatornewPlacement
2321 name, protoPlacement, interp,
2322 cling::LookupHelper::NoDiagnostics);
2324 const clang::DeclContext *ctxtnew = 0;
2325 const clang::DeclContext *ctxtnewPlacement = 0;
2328 ctxtnew = operatornew->getParent();
2330 if (operatornewPlacement) {
2331 ctxtnewPlacement = operatornewPlacement->getParent();
2337 operatornewPlacement
2342 ctxtnew = operatornew->getParent();
2344 if (operatornewPlacement) {
2345 ctxtnewPlacement = operatornewPlacement->getParent();
2348 if (ctxtnewPlacement == 0) {
2356 if (ctxtnew == ctxtnewPlacement) {
2360 const clang::CXXRecordDecl* clnew = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnew);
2361 const clang::CXXRecordDecl* clnewPlacement = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnewPlacement);
2362 if (clnew == 0 && clnewPlacement == 0) {
2368 if (clnew != 0 && clnewPlacement == 0) {
2372 if (clnew == 0 && clnewPlacement != 0) {
2377 if (clnew->isDerivedFrom(clnewPlacement)) {
2407 const clang::CXXRecordDecl *decl,
2408 const cling::Interpreter &interp,
2414 std::string mappedname;
2432 classname.insert(0,
"::");
2435 finalString <<
"namespace ROOT {" <<
"\n";
2440 finalString <<
" // Wrappers around operator new" <<
"\n";
2441 finalString <<
" static void *new_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" return p ? ";
2443 finalString <<
"new(p) ";
2444 finalString << classname.c_str();
2445 finalString << args;
2446 finalString <<
" : ";
2448 finalString <<
"::new((::ROOT::Internal::TOperatorNewHelper*)p) ";
2449 finalString << classname.c_str();
2450 finalString << args;
2451 finalString <<
" : ";
2453 finalString <<
"new " << classname.c_str() << args <<
";" <<
"\n";
2454 finalString <<
" }" <<
"\n";
2458 finalString <<
" static void *newArray_";
2459 finalString << mappedname.c_str();
2460 finalString <<
"(Long_t nElements, void *p) {";
2461 finalString <<
"\n";
2462 finalString <<
" return p ? ";
2464 finalString <<
"new(p) ";
2465 finalString << classname.c_str();
2466 finalString <<
"[nElements] : ";
2468 finalString <<
"::new((::ROOT::Internal::TOperatorNewHelper*)p) ";
2469 finalString << classname.c_str();
2470 finalString <<
"[nElements] : ";
2472 finalString <<
"new ";
2473 finalString << classname.c_str();
2474 finalString <<
"[nElements];";
2475 finalString <<
"\n";
2476 finalString <<
" }";
2477 finalString <<
"\n";
2482 finalString <<
" // Wrapper around operator delete" <<
"\n" <<
" static void delete_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" delete ((" << classname.c_str() <<
"*)p);" <<
"\n" <<
" }" <<
"\n" <<
" static void deleteArray_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" delete [] ((" << classname.c_str() <<
"*)p);" <<
"\n" <<
" }" <<
"\n" <<
" static void destruct_" << mappedname.c_str() <<
"(void *p) {" <<
"\n" <<
" typedef " << classname.c_str() <<
" current_t;" <<
"\n" <<
" ((current_t*)p)->~current_t();" <<
"\n" <<
" }" <<
"\n";
2486 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";
2490 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";
2494 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";
2498 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";
2500 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";
2504 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";
2506 finalString <<
"} // end of namespace ROOT for class " << classname.c_str() <<
"\n" <<
"\n";
2513 const cling::Interpreter &interp,
2520 if (version == 0)
return;
2524 const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
2525 if (clxx == 0)
return;
2528 for(clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
2534 Internal::RStl::Instance().GenerateTClassFor( iter->getType(), interp, normCtxt);
2539 for(clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
2543 std::string mTypename;
2549 if (!strcmp(shortTypeName,
"string")) {
2561 Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
2571 const clang::Type *rawtype =
m.getType()->getCanonicalTypeInternal().getTypePtr();
2572 if (rawtype->isArrayType()) {
2573 rawtype = rawtype->getBaseElementTypeUnsafe ();
2587 const clang::CXXRecordDecl* CRD = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
2596 if (!funcCV)
return -1;
2599 if (funcCV == (clang::FunctionDecl*)-1)
return 1;
2614 using res_t = std::pair<bool, int>;
2616 const clang::CompoundStmt* FuncBody
2617 = llvm::dyn_cast_or_null<clang::CompoundStmt>(funcCV->getBody());
2619 return res_t{
false, -1};
2620 if (FuncBody->size() != 1) {
2624 return res_t{
false, -1};
2626 const clang::ReturnStmt* RetStmt
2627 = llvm::dyn_cast<clang::ReturnStmt>(FuncBody->body_back());
2629 return res_t{
false, -1};
2630 const clang::Expr* RetExpr = RetStmt->getRetValue();
2636 llvm::APSInt RetRes;
2637 if (!RetExpr->isIntegerConstantExpr(RetRes, funcCV->getASTContext()))
2638 return res_t{
false, -1};
2639 if (RetRes.isSigned()) {
2640 return res_t{
true, (
Version_t)RetRes.getSExtValue()};
2643 return res_t{
true, (
Version_t)RetRes.getZExtValue()};
2659 clang::QualType
type =
m.getType();
2662 if (decl)
return TMetaUtils::IsSTLCont(*decl);
2671 clang::QualType
type = base.getType();
2674 if (decl)
return TMetaUtils::IsSTLCont(*decl);
2684 const std::function<
void(
const clang::Module::Header &)> &closure,
2685 bool includeDirectlyUsedModules)
2694 const std::size_t publicHeaderIndex = 4;
2697 const std::size_t maxArrayLength = ((
sizeof module.Headers) / (
sizeof *module.Headers));
2698 static_assert(publicHeaderIndex + 1 == maxArrayLength,
2699 "'Headers' has changed it's size, we need to update publicHeaderIndex");
2704 llvm::SetVector<const clang::Module *> modules;
2705 modules.insert(&module);
2706 for (
size_t i = 0; i < modules.size(); ++i) {
2707 const clang::Module *M = modules[i];
2708 for (
const clang::Module *subModule : M->submodules())
2709 modules.insert(subModule);
2712 for (
const clang::Module *
m : modules) {
2713 if (includeDirectlyUsedModules) {
2714 for (clang::Module *used :
m->DirectUses) {
2719 for (std::size_t i = 0; i < publicHeaderIndex; i++) {
2720 auto &headerList =
m->Headers[i];
2721 for (
const clang::Module::Header &moduleHeader : headerList) {
2722 closure(moduleHeader);
2736 static char t[4096];
2737 static const char* constwd =
"const ";
2738 static const char* constwdend =
"const";
2743 for (s=typeDesc;*s;s++) {
2746 if (lev==0 && *s==
'*')
continue;
2747 if (lev==0 && (strncmp(constwd,s,strlen(constwd))==0
2748 ||strcmp(constwdend,s)==0 ) ) {
2749 s+=strlen(constwd)-1;
2752 if (lev==0 && *s==
' ' && *(s+1)!=
'*') { p = t;
continue;}
2753 if (p - t > (
long)
sizeof(t)) {
2754 printf(
"ERROR (rootcling): type name too long for StortTypeName: %s\n",
2767 const cling::Interpreter& interp)
2772 if (comment[0] ==
'!')
return false;
2774 clang::QualType
type =
m.getType();
2776 if (
type->isReferenceType()) {
2781 std::string mTypeName =
type.getAsString(
m.getASTContext().getPrintingPolicy());
2782 if (!strcmp(mTypeName.c_str(),
"string") || !strcmp(mTypeName.c_str(),
"string*")) {
2785 if (!strcmp(mTypeName.c_str(),
"std::string") || !strcmp(mTypeName.c_str(),
"std::string*")) {
2793 const clang::Type *rawtype =
type.getTypePtr()->getBaseElementTypeUnsafe ();
2795 if (rawtype->isPointerType()) {
2797 clang::QualType pointee;
2798 while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
2800 rawtype = pointee.getTypePtr();
2804 if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2809 const clang::CXXRecordDecl *cxxdecl = rawtype->getAsCXXRecordDecl();
2813 if (version > 0)
return true;
2826 const clang::Type *rawtype =
m.getType().getTypePtr();
2829 clang::QualType pointee;
2830 while ( rawtype->isPointerType() && ((pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull()) && pointee.getTypePtr() != rawtype)
2832 rawtype = pointee.getTypePtr();
2846 if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2850 return rawtype->getAsCXXRecordDecl();
2859 const cling::Interpreter &interp,
2861 std::ostream& dictStream,
2863 bool isGenreflex=
false)
2865 const clang::CXXRecordDecl* decl = llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl());
2867 if (!decl || !decl->isCompleteDefinition()) {
2871 std::string fullname;
2874 Internal::RStl::Instance().GenerateTClassFor(cl.
GetNormalizedName(), llvm::dyn_cast<clang::CXXRecordDecl>(cl.
GetRecordDecl()), interp, normCtxt);
2883 (*WriteStreamerFunc)(cl, interp, normCtxt, dictStream, isGenreflex || cl.RequestStreamerInfo());
2885 ROOT::TMetaUtils::Info(0,
"Class %s: Do not generate Streamer() [*** custom streamer ***]\n",fullname.c_str());
2907 const cling::Interpreter &interpreter,
2910 const clang::ASTContext& Ctx = interpreter.getCI()->getASTContext();
2912 clang::QualType originalType = instanceType;
2916 if (llvm::isa<clang::PointerType>(instanceType.getTypePtr())) {
2918 clang::Qualifiers quals = instanceType.getQualifiers();
2919 clang::QualType newPointee =
AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2920 if (newPointee != instanceType->getPointeeType()) {
2921 instanceType = Ctx.getPointerType(newPointee);
2923 instanceType = Ctx.getQualifiedType(instanceType, quals);
2925 return instanceType;
2930 if (llvm::isa<clang::ReferenceType>(instanceType.getTypePtr())) {
2932 bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(instanceType.getTypePtr());
2933 clang::Qualifiers quals = instanceType.getQualifiers();
2934 clang::QualType newPointee =
AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2936 if (newPointee != instanceType->getPointeeType()) {
2939 instanceType = Ctx.getLValueReferenceType(newPointee);
2941 instanceType = Ctx.getRValueReferenceType(newPointee);
2943 instanceType = Ctx.getQualifiedType(instanceType, quals);
2945 return instanceType;
2949 bool prefix_changed =
false;
2950 clang::NestedNameSpecifier* prefix = 0;
2951 clang::Qualifiers prefix_qualifiers = instanceType.getLocalQualifiers();
2952 const clang::ElaboratedType* etype
2953 = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
2956 prefix = AddDefaultParametersNNS(Ctx, etype->getQualifier(), interpreter, normCtxt);
2957 prefix_changed = prefix != etype->getQualifier();
2958 instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
2964 const clang::TemplateSpecializationType* TST
2965 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
2967 const clang::ClassTemplateSpecializationDecl* TSTdecl
2968 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instanceType.getTypePtr()->getAsCXXRecordDecl());
2980 bool mightHaveChanged =
false;
2981 if (TST && TSTdecl) {
2983 clang::Sema& S = interpreter.getCI()->getSema();
2984 clang::TemplateDecl *Template = TSTdecl->getSpecializedTemplate()->getMostRecentDecl();
2985 clang::TemplateParameterList *Params = Template->getTemplateParameters();
2986 clang::TemplateParameterList::iterator Param = Params->
begin();
2990 unsigned int dropDefault = normCtxt.
GetConfig().DropDefaultArg(*Template);
2992 llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
2993 unsigned int Idecl = 0, Edecl = TSTdecl->getTemplateArgs().size();
2994 unsigned int maxAddArg = TSTdecl->getTemplateArgs().size() - dropDefault;
2995 for(clang::TemplateSpecializationType::iterator
2996 I = TST->begin(), E = TST->end();
2998 I!=E ? ++
I : 0, ++Idecl, ++Param) {
3002 if (
I->getKind() == clang::TemplateArgument::Template) {
3003 clang::TemplateName templateName =
I->getAsTemplate();
3004 clang::TemplateDecl* templateDecl = templateName.getAsTemplateDecl();
3006 clang::DeclContext* declCtxt = templateDecl->getDeclContext();
3008 if (declCtxt && !templateName.getAsQualifiedTemplateName()){
3009 clang::NamespaceDecl* ns = clang::dyn_cast<clang::NamespaceDecl>(declCtxt);
3010 clang::NestedNameSpecifier* nns;
3012 nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx, ns);
3013 }
else if (clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(declCtxt)) {
3014 nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx,TD,
false );
3017 desArgs.push_back(*
I);
3020 clang::TemplateName templateNameWithNSS ( Ctx.getQualifiedTemplateName(nns,
false, templateDecl) );
3021 desArgs.push_back(clang::TemplateArgument(templateNameWithNSS));
3022 mightHaveChanged =
true;
3028 if (
I->getKind() != clang::TemplateArgument::Type) {
3029 desArgs.push_back(*
I);
3033 clang::QualType SubTy =
I->getAsType();
3042 if (SubTy != newSubTy) {
3043 mightHaveChanged =
true;
3044 desArgs.push_back(clang::TemplateArgument(newSubTy));
3046 desArgs.push_back(*
I);
3049 }
else if (!isStdDropDefault && Idecl < maxAddArg) {
3051 mightHaveChanged =
true;
3053 const clang::TemplateArgument& templateArg
3054 = TSTdecl->getTemplateArgs().get(Idecl);
3055 if (templateArg.getKind() != clang::TemplateArgument::Type) {
3056 desArgs.push_back(templateArg);
3059 clang::QualType SubTy = templateArg.getAsType();
3061 clang::SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3062 clang::SourceLocation RAngleLoc = TSTdecl->getSourceRange().getBegin();
3064 clang::TemplateTypeParmDecl *TTP = llvm::dyn_cast<clang::TemplateTypeParmDecl>(*Param);
3067 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
3068 clang::sema::HackForDefaultTemplateArg raii;
3069 bool HasDefaultArgs;
3070 clang::TemplateArgumentLoc ArgType = S.SubstDefaultTemplateArgumentIfAvailable(
3079 if (ArgType.getArgument().isNull()
3080 || ArgType.getArgument().getKind() != clang::TemplateArgument::Type) {
3082 "Template parameter substitution failed for %s around %s\n",
3083 instanceType.getAsString().c_str(), SubTy.getAsString().c_str());
3086 clang::QualType BetterSubTy = ArgType.getArgument().getAsType();
3087 SubTy = cling::utils::Transform::GetPartiallyDesugaredType(Ctx,BetterSubTy,normCtxt.
GetConfig(),
true);
3090 desArgs.push_back(clang::TemplateArgument(SubTy));
3099 if (mightHaveChanged) {
3100 instanceType = Ctx.getTemplateSpecializationType(TST->getTemplateName(),
3102 TST->getCanonicalTypeInternal());
3106 if (!prefix_changed && !mightHaveChanged)
return originalType;
3108 instanceType = Ctx.getElaboratedType(clang::ETK_None,prefix,instanceType);
3109 instanceType = Ctx.getQualifiedType(instanceType,prefix_qualifiers);
3111 return instanceType;
3131 llvm::StringRef title;
3134 if (clang::AnnotateAttr *A =
m.getAttr<clang::AnnotateAttr>())
3135 title = A->getAnnotation();
3147 if (errnum) *errnum =
VALID;
3149 if (title.size() == 0 || (title[0] !=
'['))
return llvm::StringRef();
3150 size_t rightbracket = title.find(
']');
3151 if (rightbracket == llvm::StringRef::npos)
return llvm::StringRef();
3153 std::string working;
3154 llvm::StringRef indexvar(title.data()+1,rightbracket-1);
3161 size_t indexvarlen = indexvar.size();
3162 for ( i=0; i<indexvarlen; i++) {
3163 if (!isspace(indexvar[i])) {
3164 working += indexvar[i];
3169 const char *tokenlist =
"*+-";
3170 char *current =
const_cast<char*
>(working.c_str());
3171 current = strtok(current,tokenlist);
3173 while (current!=0) {
3175 if (isdigit(current[0])) {
3176 for(i=0;i<strlen(current);i++) {
3177 if (!isdigit(current[i])) {
3182 if (errstr) *errstr = current;
3183 if (errnum) *errnum =
NOT_INT;
3184 return llvm::StringRef();
3190 const clang::CXXRecordDecl *parent_clxx = llvm::dyn_cast<clang::CXXRecordDecl>(
m.getDeclContext());
3191 const clang::FieldDecl *index1 = 0;
3193 index1 = GetDataMemberFromAll(*parent_clxx, current );
3195 if ( IsFieldDeclInt(index1) ) {
3201 for(clang::RecordDecl::field_iterator field_iter = parent_clxx->field_begin(), end = parent_clxx->field_end();
3205 if ( field_iter->getNameAsString() ==
m.getNameAsString() ) {
3211 if (errstr) *errstr = current;
3212 if (errnum) *errnum =
NOT_DEF;
3213 return llvm::StringRef();
3215 if ( field_iter->getNameAsString() == index1->getNameAsString() ) {
3223 if (errstr) *errstr = current;
3224 if (errnum) *errnum =
NOT_INT;
3225 return llvm::StringRef();
3230 index1 = GetDataMemberFromAllParents( *parent_clxx, current );
3232 if ( IsFieldDeclInt(index1) ) {
3239 if (errnum) *errnum =
NOT_INT;
3240 if (errstr) *errstr = current;
3244 if (errnum) *errnum =
NOT_INT;
3245 if (errstr) *errstr = current;
3246 return llvm::StringRef();
3248 if ( found && (index1->getAccess() == clang::AS_private) ) {
3251 if (errstr) *errstr = current;
3253 return llvm::StringRef();
3260 if (errstr) *errstr = indexvar;
3261 if (errnum) *errnum =
UNKNOWN;
3262 return llvm::StringRef();
3267 current = strtok(0,tokenlist);
3280 out.resize(strlen(in)*2);
3281 unsigned int i=0,j=0,
c;
3283 if (out.capacity() < (j+3)) {
3287 case '+': strcpy(
const_cast<char*
>(out.data())+j,
"pL"); j+=2;
break;
3288 case '-': strcpy(
const_cast<char*
>(out.data())+j,
"mI"); j+=2;
break;
3289 case '*': strcpy(
const_cast<char*
>(out.data())+j,
"mU"); j+=2;
break;
3290 case '/': strcpy(
const_cast<char*
>(out.data())+j,
"dI"); j+=2;
break;
3291 case '&': strcpy(
const_cast<char*
>(out.data())+j,
"aN"); j+=2;
break;
3292 case '%': strcpy(
const_cast<char*
>(out.data())+j,
"pE"); j+=2;
break;
3293 case '|': strcpy(
const_cast<char*
>(out.data())+j,
"oR"); j+=2;
break;
3294 case '^': strcpy(
const_cast<char*
>(out.data())+j,
"hA"); j+=2;
break;
3295 case '>': strcpy(
const_cast<char*
>(out.data())+j,
"gR"); j+=2;
break;
3296 case '<': strcpy(
const_cast<char*
>(out.data())+j,
"lE"); j+=2;
break;
3297 case '=': strcpy(
const_cast<char*
>(out.data())+j,
"eQ"); j+=2;
break;
3298 case '~': strcpy(
const_cast<char*
>(out.data())+j,
"wA"); j+=2;
break;
3299 case '.': strcpy(
const_cast<char*
>(out.data())+j,
"dO"); j+=2;
break;
3300 case '(': strcpy(
const_cast<char*
>(out.data())+j,
"oP"); j+=2;
break;
3301 case ')': strcpy(
const_cast<char*
>(out.data())+j,
"cP"); j+=2;
break;
3302 case '[': strcpy(
const_cast<char*
>(out.data())+j,
"oB"); j+=2;
break;
3303 case ']': strcpy(
const_cast<char*
>(out.data())+j,
"cB"); j+=2;
break;
3304 case '!': strcpy(
const_cast<char*
>(out.data())+j,
"nO"); j+=2;
break;
3305 case ',': strcpy(
const_cast<char*
>(out.data())+j,
"cO"); j+=2;
break;
3306 case '$': strcpy(
const_cast<char*
>(out.data())+j,
"dA"); j+=2;
break;
3307 case ' ': strcpy(
const_cast<char*
>(out.data())+j,
"sP"); j+=2;
break;
3308 case ':': strcpy(
const_cast<char*
>(out.data())+j,
"cL"); j+=2;
break;
3309 case '"': strcpy(
const_cast<char*
>(out.data())+j,
"dQ"); j+=2;
break;
3310 case '@': strcpy(
const_cast<char*
>(out.data())+j,
"aT"); j+=2;
break;
3311 case '\'': strcpy(
const_cast<char*
>(out.data())+j,
"sQ"); j+=2;
break;
3312 case '\\': strcpy(
const_cast<char*
>(out.data())+j,
"fI"); j+=2;
break;
3313 default: out[j++]=
c;
break;
3320 std::size_t firstNonNumber = out.find_first_not_of(
"0123456789");
3321 out.replace(0,firstNonNumber,
"");
3326static clang::SourceLocation
3328 clang::SourceLocation sourceLoc) {
3330 if (!sourceLoc.isFileID()) {
3331 return sourceManager.getExpansionRange(sourceLoc).getEnd();
3340 const cling::Interpreter& interp)
3370 using namespace clang;
3371 SourceLocation headerLoc = decl.getLocation();
3373 static const char invalidFilename[] =
"";
3374 if (!headerLoc.isValid())
return invalidFilename;
3376 HeaderSearch& HdrSearch = interp.getCI()->getPreprocessor().getHeaderSearchInfo();
3378 SourceManager& sourceManager = decl.getASTContext().getSourceManager();
3380 FileID headerFID = sourceManager.getFileID(headerLoc);
3381 SourceLocation includeLoc
3383 sourceManager.getIncludeLoc(headerFID));
3385 const FileEntry *headerFE = sourceManager.getFileEntryForID(headerFID);
3386 while (includeLoc.isValid() && sourceManager.isInSystemHeader(includeLoc)) {
3387 const DirectoryLookup *foundDir = 0;
3390 assert(headerFE &&
"Couldn't find FileEntry from FID!");
3391 const FileEntry *FEhdr
3392 = HdrSearch.LookupFile(llvm::sys::path::filename(headerFE->getName()),
3395 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3403 headerFID = sourceManager.getFileID(includeLoc);
3404 headerFE = sourceManager.getFileEntryForID(headerFID);
3409 if (interp.getCI()->getLangOpts().Modules && !headerFE) {
3410 assert(decl.isFirstDecl() &&
"Couldn't trace back include from a decl"
3411 " that is not from an AST file");
3412 assert(StringRef(includeLoc.printToString(sourceManager)).startswith(
"<module-includes>"));
3416 sourceManager.getIncludeLoc(headerFID));
3419 if (!headerFE)
return invalidFilename;
3420 llvm::StringRef headerFileName = headerFE->getName();
3431 bool isAbsolute = llvm::sys::path::is_absolute(headerFileName);
3432 const FileEntry* FELong = 0;
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 const DirectoryLookup* FoundDir = 0;
3449 FELong = HdrSearch.LookupFile(trailingPart, SourceLocation(),
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 const DirectoryLookup* FoundDir = 0;
3475 if (HdrSearch.LookupFile(trailingPart, SourceLocation(),
3477 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3480 0,
nullptr ) == FELong) {
3481 return trailingPart;
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 clang::sema::HackForDefaultTemplateArg raii;
3668 bool HasDefaultArgs;
3669 TemplateArgumentLoc defTArgLoc = S.SubstDefaultTemplateArgumentIfAvailable(Template,
3677 newArg = defTArgLoc.getArgument();
3678 if (newArg.isNull() ||
3679 newArg.getKind() != clang::TemplateArgument::Type) {
3681 "Template parameter substitution failed!");
3684 ClassTemplateSpecializationDecl* nTSTdecl
3685 = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(newArg.getAsType()->getAsCXXRecordDecl());
3688 isEqual = nTSTdecl->getMostRecentDecl() == TSTdecl->getMostRecentDecl() ||
3689 tParQualType.getTypePtr() == newArg.getAsType().getTypePtr();
3701 const clang::NamedDecl& tPar)
3703 using namespace clang;
3704 const NonTypeTemplateParmDecl* nttpdPtr = llvm::dyn_cast<NonTypeTemplateParmDecl>(&tPar);
3705 if (!nttpdPtr)
return false;
3706 const NonTypeTemplateParmDecl& nttpd = *nttpdPtr;
3708 if (!nttpd.hasDefaultArgument())
3712 llvm::APSInt defaultValueAPSInt(64,
false);
3713 if (Expr* defArgExpr = nttpd.getDefaultArgument()) {
3714 const ASTContext& astCtxt = nttpdPtr->getASTContext();
3715 defArgExpr->isIntegerConstantExpr(defaultValueAPSInt, astCtxt);
3718 const int value = tArg.getAsIntegral().getLimitedValue();
3721 return value == defaultValueAPSInt;
3731 using namespace clang;
3732 if (!nDecl)
return false;
3733 if (
const TemplateTypeParmDecl* ttpd = llvm::dyn_cast<TemplateTypeParmDecl>(nDecl))
3734 return ttpd->hasDefaultArgument();
3735 if (
const NonTypeTemplateParmDecl* nttpd = llvm::dyn_cast<NonTypeTemplateParmDecl>(nDecl))
3736 return nttpd->hasDefaultArgument();
3741static void KeepNParams(clang::QualType& normalizedType,
3742 const clang::QualType& vanillaType,
3743 const cling::Interpreter& interp,
3748 const clang::TemplateArgument &tArg,
3749 const cling::Interpreter& interp,
3751 const clang::ASTContext& astCtxt)
3754 using namespace clang;
3761 if (tArg.getKind() == clang::TemplateArgument::Type) {
3762 QualType thisNormQualType = normTArg.getAsType();
3763 QualType thisArgQualType = tArg.getAsType();
3768 normTArg = TemplateArgument(thisNormQualType);
3769 return (thisNormQualType != thisArgQualType);
3770 }
else if (normTArg.getKind() == clang::TemplateArgument::Pack) {
3771 assert( tArg.getKind() == clang::TemplateArgument::Pack );
3773 SmallVector<TemplateArgument, 2> desArgs;
3774 bool mightHaveChanged =
true;
3775 for (
auto I = normTArg.pack_begin(), E = normTArg.pack_end(),
3776 FI = tArg.pack_begin(), FE = tArg.pack_end();
3777 I != E && FI != FE; ++
I, ++FI)
3779 TemplateArgument pack_arg(*
I);
3781 desArgs.push_back(pack_arg);
3783 if (mightHaveChanged) {
3784 ASTContext &mutableCtx(
const_cast<ASTContext&
>(astCtxt) );
3785 normTArg = TemplateArgument::CreatePackCopy(mutableCtx, desArgs);
3787 return mightHaveChanged;
3798 const clang::QualType& vanillaType,
3799 const cling::Interpreter& interp,
3803 using namespace clang;
3807 ClassTemplateSpecializationDecl* ctsd;
3808 ClassTemplateDecl* ctd;
3809 if (! QualType2Template(vanillaType, ctd, ctsd)) return ;
3815 QualType originalNormalizedType = normalizedType;
3817 const ASTContext& astCtxt = ctsd->getASTContext();
3822 if (llvm::isa<clang::PointerType>(normalizedType.getTypePtr())) {
3824 clang::Qualifiers quals = normalizedType.getQualifiers();
3825 auto valNormalizedType = normalizedType->getPointeeType();
3826 KeepNParams(valNormalizedType,vanillaType, interp, normCtxt);
3827 normalizedType = astCtxt.getPointerType(valNormalizedType);
3829 normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3835 if (llvm::isa<clang::ReferenceType>(normalizedType.getTypePtr())) {
3837 bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(normalizedType.getTypePtr());
3838 clang::Qualifiers quals = normalizedType.getQualifiers();
3839 auto valNormType = normalizedType->getPointeeType();
3840 KeepNParams(valNormType, vanillaType, interp, normCtxt);
3844 normalizedType = astCtxt.getLValueReferenceType(valNormType);
3846 normalizedType = astCtxt.getRValueReferenceType(valNormType);
3848 normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3853 bool prefix_changed =
false;
3854 clang::NestedNameSpecifier* prefix =
nullptr;
3855 clang::Qualifiers prefix_qualifiers = normalizedType.getLocalQualifiers();
3856 const clang::ElaboratedType* etype
3857 = llvm::dyn_cast<clang::ElaboratedType>(normalizedType.getTypePtr());
3861 prefix = AddDefaultParametersNNS(astCtxt, etype->getQualifier(), interp, normCtxt);
3862 prefix_changed = prefix != etype->getQualifier();
3863 normalizedType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3869 const clang::ClassTemplateDecl* ctdWithDefaultArgs = ctd;
3870 for (
const RedeclarableTemplateDecl* rd: ctdWithDefaultArgs->redecls()) {
3871 clang::TemplateParameterList* tpl = rd->getTemplateParameters();
3872 if (tpl->getMinRequiredArguments () < tpl->size()) {
3873 ctdWithDefaultArgs = llvm::dyn_cast<clang::ClassTemplateDecl>(rd);
3877 TemplateParameterList* tParsPtr = ctdWithDefaultArgs->getTemplateParameters();
3878 const TemplateParameterList& tPars = *tParsPtr;
3879 const TemplateArgumentList& tArgs = ctsd->getTemplateArgs();
3882 TemplateName theTemplateName = ExtractTemplateNameFromQualType(normalizedType);
3883 if (theTemplateName.isNull()) {
3884 normalizedType=originalNormalizedType;
3888 const TemplateSpecializationType* normalizedTst =
3889 llvm::dyn_cast<TemplateSpecializationType>(normalizedType.getTypePtr());
3890 if (!normalizedTst) {
3891 normalizedType=originalNormalizedType;
3895 const clang::ClassTemplateSpecializationDecl* TSTdecl
3896 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(normalizedType.getTypePtr()->getAsCXXRecordDecl());
3897 bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
3904 llvm::SmallVector<TemplateArgument, 4> argsToKeep;
3906 const int nArgs = tArgs.size();
3907 const int nNormArgs = normalizedTst->getNumArgs();
3909 bool mightHaveChanged =
false;
3912 for (
int formal = 0, inst = 0; formal != nArgs; ++formal, ++inst) {
3913 const NamedDecl* tParPtr = tPars.getParam(formal);
3915 Error(
"KeepNParams",
"The parameter number %s is null.\n", formal);
3922 if (formal == nNormArgs || inst == nNormArgs)
break;
3924 const TemplateArgument& tArg = tArgs.get(formal);
3925 TemplateArgument normTArg(normalizedTst->getArgs()[inst]);
3927 bool shouldKeepArg = nArgsToKeep < 0 || inst < nArgsToKeep;
3928 if (isStdDropDefault) shouldKeepArg =
false;
3937 if ( tParPtr->isTemplateParameterPack() ) {
3942 for( ; inst != nNormArgs; ++inst) {
3943 normTArg = normalizedTst->getArgs()[inst];
3945 argsToKeep.push_back(normTArg);
3951 argsToKeep.push_back(normTArg);
3954 if (!isStdDropDefault) {
3956 mightHaveChanged =
true;
3966 auto argKind = tArg.getKind();
3967 if (argKind == clang::TemplateArgument::Type){
3969 equal =
areEqualTypes(tArg, argsToKeep, *tParPtr, interp, normCtxt);
3970 }
else if (argKind == clang::TemplateArgument::Integral){
3975 argsToKeep.push_back(normTArg);
3977 mightHaveChanged =
true;
3983 if (!prefix_changed && !mightHaveChanged) {
3984 normalizedType = originalNormalizedType;
3989 if (mightHaveChanged) {
3990 Qualifiers qualifiers = normalizedType.getLocalQualifiers();
3991 normalizedType = astCtxt.getTemplateSpecializationType(theTemplateName,
3993 normalizedType.getTypePtr()->getCanonicalTypeInternal());
3994 normalizedType = astCtxt.getQualifiedType(normalizedType, qualifiers);
4000 normalizedType = astCtxt.getElaboratedType(clang::ETK_None,prefix,normalizedType);
4001 normalizedType = astCtxt.getQualifiedType(normalizedType,prefix_qualifiers);
4015 clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4018 cling::Interpreter::PushTransactionRAII RAII(
const_cast<cling::Interpreter*
>(&interpreter));
4019 clang::QualType normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt,
type, normCtxt.
GetConfig(),
true );
4027 return normalizedType;
4041 if (
type.isNull()) {
4048 clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4049 clang::PrintingPolicy policy(ctxt.getPrintingPolicy());
4050 policy.SuppressTagKeyword =
true;
4051 policy.SuppressScope =
true;
4052 policy.AnonymousTagLocations =
false;
4057 std::string normalizedNameStep1;
4060 cling::Interpreter::PushTransactionRAII clingRAII(
const_cast<cling::Interpreter*
>(&interpreter));
4061 normalizedType.getAsStringInternal(normalizedNameStep1,policy);
4071 if (norm_name.length()>2 && norm_name[0]==
':' && norm_name[1]==
':') {
4072 norm_name.erase(0,2);
4080 const clang::TypeDecl* typeDecl,
4081 const cling::Interpreter &interpreter)
4084 const clang::Sema &sema = interpreter.getSema();
4085 clang::ASTContext& astCtxt = sema.getASTContext();
4086 clang::QualType qualType = astCtxt.getTypeDeclType(typeDecl);
4095std::pair<std::string,clang::QualType>
4097 const cling::Interpreter &interpreter,
4101 std::string thisTypeName;
4102 GetNormalizedName(thisTypeName, thisType, interpreter, normCtxt );
4105 if (!hasChanged)
return std::make_pair(thisTypeName,thisType);
4109 "Name changed from %s to %s\n", thisTypeName.c_str(), thisTypeNameForIO.c_str());
4112 auto& lookupHelper = interpreter.getLookupHelper();
4114 const clang::Type* typePtrForIO;
4115 lookupHelper.findScope(thisTypeNameForIO,
4116 cling::LookupHelper::DiagSetting::NoDiagnostics,
4120 if (!typePtrForIO) {
4122 "Type not found: %s.",thisTypeNameForIO.c_str());
4125 clang::QualType typeForIO(typePtrForIO,0);
4128 if (!typeForIO->isRecordType()) {
4129 return std::make_pair(thisTypeNameForIO,typeForIO);
4132 auto thisDeclForIO = typeForIO->getAsCXXRecordDecl();
4133 if (!thisDeclForIO) {
4135 "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());
4136 return std::make_pair(thisTypeName,thisType);
4139 return std::make_pair(thisTypeNameForIO,typeForIO);
4145 const cling::Interpreter &interpreter,
4157 std::string dictFileName(moduleName);
4158 dictFileName +=
"_rdict.pcm";
4159 return dictFileName;
4163 llvm::errs() << llvm::StringRef(commentStart, 80) <<
'\n';
4189 clang::SourceManager& sourceManager = decl.getASTContext().getSourceManager();
4190 clang::SourceLocation sourceLocation = decl.getEndLoc();
4193 sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
4201 if (!decl.hasOwningModule() && sourceManager.isLoadedSourceLocation(sourceLocation)) {
4207 const char *commentStart = sourceManager.getCharacterData(sourceLocation, &invalid);
4211 bool skipToSemi =
true;
4212 if (
const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(&decl)) {
4213 if (FD->isImplicit()) {
4217 if (FD->isExplicitlyDefaulted() || FD->isDeletedAsWritten()) {
4221 }
else if (FD->doesThisDeclarationHaveABody()) {
4224 assert((decl.getEndLoc() != sourceLocation || *commentStart ==
'}'
4226 &&
"Expected macro or end of body at '}'");
4227 if (*commentStart) ++commentStart;
4230 while (*commentStart && isspace(*commentStart)
4231 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4234 if (*commentStart ==
';') ++commentStart;
4238 }
else if (
const clang::EnumConstantDecl* ECD
4239 = clang::dyn_cast<clang::EnumConstantDecl>(&decl)) {
4241 if (ECD->getNextDeclInContext())
4242 while (*commentStart && *commentStart !=
',' && *commentStart !=
'\r' && *commentStart !=
'\n')
4250 while (*commentStart && *commentStart !=
';' && *commentStart !=
'\r' && *commentStart !=
'\n')
4252 if (*commentStart ==
';') ++commentStart;
4256 while ( *commentStart && isspace(*commentStart)
4257 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4261 if (commentStart[0] !=
'/' ||
4262 (commentStart[1] !=
'/' && commentStart[1] !=
'*')) {
4272 unsigned int skipChars = 2;
4273 if (commentStart[0] ==
'/' &&
4274 commentStart[1] ==
'/' &&
4275 (commentStart[2] ==
'/' || commentStart[2] ==
'!') &&
4276 commentStart[3] ==
'<') {
4278 }
else if (commentStart[0] ==
'/' &&
4279 commentStart[1] ==
'*' &&
4280 (commentStart[2] ==
'*' || commentStart[2] ==
'!') &&
4281 commentStart[3] ==
'<') {
4285 commentStart += skipChars;
4288 while ( *commentStart && isspace(*commentStart)
4289 && *commentStart !=
'\n' && *commentStart !=
'\r') {
4292 const char* commentEnd = commentStart;
4294 while (*commentEnd && *commentEnd !=
'\n' && *commentEnd !=
'\r') {
4300 while (commentEnd > commentStart && isspace(commentEnd[-1])) {
4306 unsigned offset = commentStart - sourceManager.getCharacterData(sourceLocation);
4307 *loc = sourceLocation.getLocWithOffset(offset - 1);
4310 return llvm::StringRef(commentStart, commentEnd - commentStart);
4321 clang::SourceLocation *loc,
4322 const cling::Interpreter &interpreter)
4324 using namespace clang;
4325 SourceLocation commentSLoc;
4326 llvm::StringRef comment;
4328 Sema& sema = interpreter.getCI()->getSema();
4330 const Decl* DeclFileLineDecl
4331 = interpreter.getLookupHelper().findFunctionProto(&decl,
"DeclFileLine",
"",
4332 cling::LookupHelper::NoDiagnostics);
4333 if (!DeclFileLineDecl)
return llvm::StringRef();
4336 SourceLocation maybeMacroLoc = DeclFileLineDecl->getLocation();
4337 bool isClassDefMacro = maybeMacroLoc.isMacroID() && sema.findMacroSpelling(maybeMacroLoc,
"ClassDef");
4338 if (isClassDefMacro) {
4340 if (comment.size()) {
4347 return llvm::StringRef();
4356 const clang::Type *rawtype =
type.getTypePtr();
4359 if (rawtype->isElaboratedTypeSpecifier() ) {
4360 rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4362 if (rawtype->isArrayType()) {
4363 rawtype =
type.getTypePtr()->getBaseElementTypeUnsafe ();
4365 if (rawtype->isPointerType() || rawtype->isReferenceType() ) {
4367 clang::QualType pointee;
4368 while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
4370 rawtype = pointee.getTypePtr();
4372 if (rawtype->isElaboratedTypeSpecifier() ) {
4373 rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4375 if (rawtype->isArrayType()) {
4376 rawtype = rawtype->getBaseElementTypeUnsafe ();
4380 if (rawtype->isArrayType()) {
4381 rawtype = rawtype->getBaseElementTypeUnsafe ();
4391 return cling::utils::Analyze::IsStdClass(cl);
4401 if (cling::utils::Analyze::IsStdClass(cl)) {
4402 static const char *names[] =
4403 {
"shared_ptr",
"__shared_ptr",
4404 "vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset"};
4405 llvm::StringRef clname(cl.getName());
4406 for(
auto &&
name : names) {
4407 if (clname ==
name)
return true;
4417 const clang::CXXRecordDecl ¤tCl)
4420 if (&cl == ¤tCl)
return true;
4422 const clang::CXXRecordDecl* previous = currentCl.getPreviousDecl();
4425 if (NULL == previous){
4444 const clang::CXXRecordDecl *thisDecl =
4445 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(typ, cling::LookupHelper::WithDiagnostics));
4449 Error(
"IsOfType",
"Record decl of type %s not found in the AST.", typ.c_str());
4454 const clang::CXXRecordDecl *mostRecentDecl = thisDecl->getMostRecentDecl();
4479 if (!IsStdClass(cl)) {
4483 return STLKind(cl.getName());
4487 using namespace clang;
4488 struct SearchTypedef:
public TypeVisitor<SearchTypedef, bool> {
4489 bool VisitTypedefType(
const TypedefType* TD) {
4492 bool VisitArrayType(
const ArrayType* AT) {
4493 return Visit(AT->getElementType().getTypePtr());
4495 bool VisitDecltypeType(
const DecltypeType* DT) {
4496 return Visit(DT->getUnderlyingType().getTypePtr());
4498 bool VisitPointerType(
const PointerType* PT) {
4499 return Visit(PT->getPointeeType().getTypePtr());
4501 bool VisitReferenceType(
const ReferenceType* RT) {
4502 return Visit(RT->getPointeeType().getTypePtr());
4504 bool VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType* STST) {
4505 return Visit(STST->getReplacementType().getTypePtr());
4507 bool VisitTemplateSpecializationType(
const TemplateSpecializationType* TST) {
4508 for (
int I = 0,
N = TST->getNumArgs();
I <
N; ++
I) {
4509 const TemplateArgument& TA = TST->getArg(
I);
4510 if (TA.getKind() == TemplateArgument::Type
4511 && Visit(TA.getAsType().getTypePtr()))
4516 bool VisitTemplateTypeParmType(
const TemplateTypeParmType* TTPT) {
4519 bool VisitTypeOfType(
const TypeOfType* TOT) {
4520 return TOT->getUnderlyingType().getTypePtr();
4522 bool VisitElaboratedType(
const ElaboratedType* ET) {
4523 NestedNameSpecifier* NNS = ET->getQualifier();
4525 if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
4526 if (Visit(NNS->getAsType()))
4529 NNS = NNS->getPrefix();
4531 return Visit(ET->getNamedType().getTypePtr());
4546 if (!instance)
return input;
4552 using namespace llvm;
4553 using namespace clang;
4554 const clang::ASTContext &Ctxt = instance->getAsCXXRecordDecl()->getASTContext();
4557 const clang::ElaboratedType* etype
4558 = llvm::dyn_cast<clang::ElaboratedType>(input.getTypePtr());
4562 clang::Qualifiers scope_qualifiers = input.getLocalQualifiers();
4563 assert(instance->getAsCXXRecordDecl()!=0 &&
"ReSubstTemplateArg only makes sense with a type representing a class.");
4565 clang::NestedNameSpecifier *scope = ReSubstTemplateArgNNS(Ctxt,etype->getQualifier(),instance);
4566 clang::QualType subTy =
ReSubstTemplateArg(clang::QualType(etype->getNamedType().getTypePtr(),0),instance);
4568 if (scope) subTy = Ctxt.getElaboratedType(clang::ETK_None,scope,subTy);
4569 subTy = Ctxt.getQualifiedType(subTy,scope_qualifiers);
4573 QualType QT = input;
4577 if (isa<clang::PointerType>(QT.getTypePtr())) {
4579 Qualifiers quals = QT.getQualifiers();
4582 if (nQT == QT->getPointeeType())
return QT;
4584 QT = Ctxt.getPointerType(nQT);
4586 QT = Ctxt.getQualifiedType(QT, quals);
4592 if (isa<ReferenceType>(QT.getTypePtr())) {
4594 bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
4595 Qualifiers quals = QT.getQualifiers();
4598 if (nQT == QT->getPointeeType())
return QT;
4602 QT = Ctxt.getLValueReferenceType(nQT);
4604 QT = Ctxt.getRValueReferenceType(nQT);
4606 QT = Ctxt.getQualifiedType(QT, quals);
4612 if (isa<clang::ArrayType>(QT.getTypePtr())) {
4614 Qualifiers quals = QT.getQualifiers();
4616 if (
const auto arr = dyn_cast<ConstantArrayType>(QT.getTypePtr())) {
4619 if (newQT == arr->getElementType())
return QT;
4620 QT = Ctxt.getConstantArrayType (newQT,
4622 arr->getSizeModifier(),
4623 arr->getIndexTypeCVRQualifiers());
4625 }
else if (
const auto arr = dyn_cast<DependentSizedArrayType>(QT.getTypePtr())) {
4628 if (newQT == QT)
return QT;
4629 QT = Ctxt.getDependentSizedArrayType (newQT,
4631 arr->getSizeModifier(),
4632 arr->getIndexTypeCVRQualifiers(),
4633 arr->getBracketsRange());
4635 }
else if (
const auto arr = dyn_cast<IncompleteArrayType>(QT.getTypePtr())) {
4638 if (newQT == arr->getElementType())
return QT;
4639 QT = Ctxt.getIncompleteArrayType (newQT,
4640 arr->getSizeModifier(),
4641 arr->getIndexTypeCVRQualifiers());
4643 }
else if (
const auto arr = dyn_cast<VariableArrayType>(QT.getTypePtr())) {
4646 if (newQT == arr->getElementType())
return QT;
4647 QT = Ctxt.getVariableArrayType (newQT,
4649 arr->getSizeModifier(),
4650 arr->getIndexTypeCVRQualifiers(),
4651 arr->getBracketsRange());
4655 QT = Ctxt.getQualifiedType(QT, quals);
4660 etype = llvm::dyn_cast<clang::ElaboratedType>(instance);
4662 instance = etype->getNamedType().getTypePtr();
4663 if (!instance)
return input;
4666 const clang::TemplateSpecializationType* TST
4667 = llvm::dyn_cast<const clang::TemplateSpecializationType>(instance);
4669 if (!TST)
return input;
4671 const clang::ClassTemplateSpecializationDecl* TSTdecl
4672 = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instance->getAsCXXRecordDecl());
4674 const clang::SubstTemplateTypeParmType *substType
4675 = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(input.getTypePtr());
4679 const clang::ClassTemplateDecl *replacedCtxt = 0;
4681 const clang::DeclContext *replacedDeclCtxt = substType->getReplacedParameter()->getDecl()->getDeclContext();
4682 const clang::CXXRecordDecl *decl = llvm::dyn_cast<clang::CXXRecordDecl>(replacedDeclCtxt);
4683 unsigned int index = substType->getReplacedParameter()->getIndex();
4686 if (decl->getKind() == clang::Decl::ClassTemplatePartialSpecialization) {
4687 const clang::ClassTemplatePartialSpecializationDecl *spec = llvm::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(decl);
4689 unsigned int depth = substType->getReplacedParameter()->getDepth();
4691 const TemplateArgument *instanceArgs = spec->getTemplateArgs().data();
4692 unsigned int instanceNArgs = spec->getTemplateArgs().size();
4696 for(
unsigned int A = 0; A < instanceNArgs; ++A) {
4697 if (instanceArgs[A].getKind() == clang::TemplateArgument::Type) {
4698 clang::QualType argQualType = instanceArgs[A].getAsType();
4700 const clang::TemplateTypeParmType *replacementType;
4702 replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(argQualType);
4704 if (!replacementType) {
4705 const clang::SubstTemplateTypeParmType *argType
4706 = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(argQualType);
4708 clang::QualType replacementQT = argType->getReplacementType();
4709 replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(replacementQT);
4712 if (replacementType &&
4713 depth == replacementType->getDepth() &&
4714 index == replacementType->getIndex() )
4721 replacedCtxt = spec->getSpecializedTemplate();
4723 replacedCtxt = decl->getDescribedClassTemplate();
4725 }
else if (
auto const declguide = llvm::dyn_cast<clang::CXXDeductionGuideDecl>(replacedDeclCtxt)) {
4726 replacedCtxt = llvm::dyn_cast<clang::ClassTemplateDecl>(declguide->getDeducedTemplate());
4727 }
else if (
auto const ctdecl = llvm::dyn_cast<clang::ClassTemplateDecl>(replacedDeclCtxt)) {
4728 replacedCtxt = ctdecl;
4730 std::string astDump;
4731 llvm::raw_string_ostream ostream(astDump);
4732 instance->dump(ostream);
4734 ROOT::TMetaUtils::Warning(
"ReSubstTemplateArg",
"Unexpected type of declaration context for template parameter: %s.\n\tThe responsible class is:\n\t%s\n",
4735 replacedDeclCtxt->getDeclKindName(), astDump.c_str());
4736 replacedCtxt =
nullptr;
4739 if ((replacedCtxt && replacedCtxt->getCanonicalDecl() == TSTdecl->getSpecializedTemplate()->getCanonicalDecl())
4741 substType->getReplacedParameter()->getDecl()
4742 == TSTdecl->getSpecializedTemplate ()->getTemplateParameters()->getParam(index))
4744 if ( index >= TST->getNumArgs() ) {
4750 }
else if (TST->getArg(index).getKind() == clang::TemplateArgument::Type) {
4751 return TST->getArg(index).getAsType();
4760 const clang::TemplateSpecializationType* inputTST
4761 = llvm::dyn_cast<const clang::TemplateSpecializationType>(input.getTypePtr());
4762 const clang::ASTContext& astCtxt = TSTdecl->getASTContext();
4765 bool mightHaveChanged =
false;
4766 llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
4767 for(clang::TemplateSpecializationType::iterator
I = inputTST->begin(), E = inputTST->end();
4769 if (
I->getKind() != clang::TemplateArgument::Type) {
4770 desArgs.push_back(*
I);
4774 clang::QualType SubTy =
I->getAsType();
4776 if (llvm::isa<clang::SubstTemplateTypeParmType>(SubTy)
4777 || llvm::isa<clang::TemplateSpecializationType>(SubTy)) {
4779 mightHaveChanged = SubTy != newSubTy;
4780 if (!newSubTy.isNull()) {
4781 desArgs.push_back(clang::TemplateArgument(newSubTy));
4784 desArgs.push_back(*
I);
4788 if (mightHaveChanged) {
4789 clang::Qualifiers qualifiers = input.getLocalQualifiers();
4790 input = astCtxt.getTemplateSpecializationType(inputTST->getTemplateName(),
4792 inputTST->getCanonicalTypeInternal());
4793 input = astCtxt.getQualifiedType(input, qualifiers);
4805 if ( nArgsToRemove == 0 ||
name ==
"")
4810 const unsigned int length =
name.length();
4812 unsigned int nArgsRemoved=0;
4813 unsigned int nBraces=0;
4815 while (nArgsRemoved!=nArgsToRemove && cur<length){
4817 if (
c ==
'<') nBraces++;
4818 if (
c ==
'>') nBraces--;
4819 if (
c ==
',' && nBraces==1 ) nArgsRemoved++;
4833 static const char *stls[] =
4834 {
"any",
"vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset",
4835 "forward_list",
"unordered_set",
"unordered_multiset",
"unordered_map",
"unordered_multimap",0};
4848 for(
int k=1;stls[k];k++) {
if (
type.equals(stls[k]))
return values[k];}
4859 TND = TND->getMostRecentDecl();
4860 while (TND && !(TND->hasAttrs()))
4861 TND = TND->getPreviousDecl();
4873 TD = TD->getMostRecentDecl();
4874 while (TD && !(TD->hasAttrs() && TD->isThisDeclarationADefinition()))
4875 TD = TD->getPreviousDecl();
4884 std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4886 const clang::DeclContext* enclosingNamespaceDeclCtxt = decl.getDeclContext();
4887 if (!enclosingNamespaceDeclCtxt)
return;
4889 const clang::NamespaceDecl* enclosingNamespace =
4890 clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4891 if (!enclosingNamespace)
return;
4893 enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4894 enclosingNamespace->isInline()));
4904 std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4906 const clang::DeclContext* enclosingNamespaceDeclCtxt = ctxt.getParent ();
4909 if (!enclosingNamespaceDeclCtxt) {
4915 const clang::NamespaceDecl* enclosingNamespace = clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4916 if (!enclosingNamespace)
return;
4919 enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4920 enclosingNamespace->isInline()));
4931 std::list<std::pair<std::string,unsigned int> >& enclosingSc)
4933 const clang::DeclContext* enclosingDeclCtxt = decl.getDeclContext();
4934 if (!enclosingDeclCtxt)
return 0;
4936 unsigned int scopeType;
4938 if (
auto enclosingNamespacePtr =
4939 clang::dyn_cast<clang::NamespaceDecl>(enclosingDeclCtxt)){
4940 scopeType= enclosingNamespacePtr->isInline() ? 1 : 0;
4941 enclosingSc.push_back(std::make_pair(enclosingNamespacePtr->getNameAsString(),scopeType));
4945 if (
auto enclosingClassPtr =
4946 clang::dyn_cast<clang::RecordDecl>(enclosingDeclCtxt)){
4947 return enclosingClassPtr;
4960 std::string::size_type beginVar = 0;
4961 std::string::size_type endVar = 0;
4962 while ((beginVar = txt.find(
'$', beginVar)) != std::string::npos
4963 && beginVar + 1 < txt.length()) {
4964 std::string::size_type beginVarName = beginVar + 1;
4965 std::string::size_type endVarName = std::string::npos;
4966 if (txt[beginVarName] ==
'(') {
4968 endVarName = txt.find(
')', beginVarName);
4970 if (endVarName == std::string::npos) {
4972 varname, txt.c_str() + beginVar);
4975 endVar = endVarName + 1;
4978 beginVarName = beginVar + 1;
4979 endVarName = beginVarName;
4980 while (isalnum(txt[endVarName]) || txt[endVarName] ==
'_')
4982 endVar = endVarName;
4985 const char* val = getenv(txt.substr(beginVarName,
4986 endVarName - beginVarName).c_str());
4989 txt.replace(beginVar, endVar - beginVar, val);
4990 int lenval = strlen(val);
4991 int delta = lenval - (endVar - beginVar);
4995 beginVar = endVar + 1;
5007 const char* envInclPath = getenv(
"ROOT_INCLUDE_PATH");
5011 std::istringstream envInclPathsStream(envInclPath);
5012 std::string inclPath;
5013 while (std::getline(envInclPathsStream, inclPath,
':')) {
5016 if (!inclPath.empty()) {
5017 clingArgs.push_back(
"-I");
5018 clingArgs.push_back(inclPath);
5029 size_t start_pos = 0;
5034 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
5035 str.replace(start_pos, from.length(), to);
5036 start_pos += to.length();
5037 if (recurse) changed =
true;
5053 if (theString.size() < theSubstring.size())
return false;
5054 const unsigned int theSubstringSize = theSubstring.size();
5055 return 0 == theString.compare(theString.size() - theSubstringSize,
5064 if (theString.size() < theSubstring.size())
return false;
5065 const unsigned int theSubstringSize = theSubstring.size();
5066 return 0 == theString.compare(0,
5079 if ((strstr(filename,
"LinkDef") || strstr(filename,
"Linkdef") ||
5080 strstr(filename,
"linkdef")) && strstr(filename,
".h")) {
5083 size_t len = strlen(filename);
5084 size_t linkdeflen = 9;
5086 if (0 == strncasecmp(filename + (len - linkdeflen),
"linkdef", linkdeflen - 2)
5087 && 0 == strcmp(filename + (len - 2),
".h")
5102 return llvm::sys::path::extension(filename) ==
".h" ||
5103 llvm::sys::path::extension(filename) ==
".hh" ||
5104 llvm::sys::path::extension(filename) ==
".hpp" ||
5105 llvm::sys::path::extension(filename) ==
".H" ||
5106 llvm::sys::path::extension(filename) ==
".h++" ||
5107 llvm::sys::path::extension(filename) ==
"hxx" ||
5108 llvm::sys::path::extension(filename) ==
"Hxx" ||
5109 llvm::sys::path::extension(filename) ==
"HXX";
5115 cling::Interpreter::IgnoreFilesFunc_t ignoreFiles,
5116 const cling::Interpreter &interp,
5119 clang::Sema &sema = interp.getSema();
5120 cling::Transaction theTransaction(sema);
5121 std::set<clang::Decl *> addedDecls;
5122 for (
auto decl : decls) {
5124 clang::Decl *ncDecl =
const_cast<clang::Decl *
>(decl);
5125 theTransaction.append(ncDecl);
5127 std::string newFwdDecl;
5128 llvm::raw_string_ostream llvmOstr(newFwdDecl);
5130 std::string locallogs;
5131 llvm::raw_string_ostream llvmLogStr(locallogs);
5132 interp.forwardDeclare(theTransaction, sema.getPreprocessor(), sema.getASTContext(), llvmOstr,
true,
5133 logs ? &llvmLogStr : nullptr, ignoreFiles);
5137 logs->swap(locallogs);
5149 std::string& defString)
5161 std::string& defString)
5163 std::list<std::pair<std::string,unsigned int> > enclosingNamespaces;
5166 if (rcdPtr)
return rcdPtr;
5169 static const std::string scopeType [] = {
"namespace ",
"inline namespace ",
"class "};
5171 std::string scopeName;
5172 std::string scopeContent;
5173 unsigned int scopeIndex;
5174 for (
auto const & encScope : enclosingNamespaces){
5175 scopeIndex = encScope.second;
5176 scopeName = encScope.first;
5177 scopeContent =
" { " + defString +
" }";
5178 defString = scopeType[scopeIndex] +
5200 const clang::TemplateParameterList& tmplParamList,
5201 const cling::Interpreter& interpreter)
5204 for (
auto prmIt = tmplParamList.begin();
5205 prmIt != tmplParamList.end(); prmIt++){
5207 if (prmIt != tmplParamList.begin())
5208 templateArgs +=
", ";
5210 auto nDecl = *prmIt;
5211 std::string typeName;
5214 if (llvm::isa<clang::TemplateTypeParmDecl>(nDecl)){
5215 typeName =
"typename ";
5216 if (nDecl->isParameterPack())
5218 typeName += (*prmIt)->getNameAsString();
5221 else if (
auto nttpd = llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(nDecl)){
5222 auto theType = nttpd->getType();
5225 if (theType.getAsString().find(
"enum") != std::string::npos){
5226 std::string astDump;
5227 llvm::raw_string_ostream ostream(astDump);
5228 nttpd->dump(ostream);
5230 ROOT::TMetaUtils::Warning(0,
"Forward declarations of templates with enums as template parameters. The responsible class is: %s\n", astDump.c_str());
5239 else if (
auto ttpd = llvm::dyn_cast<clang::TemplateTemplateParmDecl>(nDecl)){
5242 std::string astDump;
5243 llvm::raw_string_ostream ostream(astDump);
5244 ttpd->dump(ostream);
5246 ROOT::TMetaUtils::Error(0,
"Cannot reconstruct template template parameter forward declaration for %s\n", astDump.c_str());
5251 templateArgs += typeName;
5262 const cling::Interpreter& interpreter,
5263 std::string& defString)
5265 std::string templatePrefixString;
5266 auto tmplParamList= templDecl.getTemplateParameters();
5267 if (!tmplParamList){
5269 "Cannot extract template parameter list for %s",
5270 templDecl.getNameAsString().c_str());
5277 "Problems with arguments for forward declaration of class %s\n",
5278 templDecl.getNameAsString().c_str());
5281 templatePrefixString =
"template " + templatePrefixString +
" ";
5283 defString = templatePrefixString +
"class ";
5284 if (templDecl.isParameterPack())
5285 defString +=
"... ";
5286 defString += templDecl.getNameAsString();
5287 if (llvm::isa<clang::TemplateTemplateParmDecl>(&templDecl)) {
5301 std::string& argFwdDecl,
5302 const cling::Interpreter& interpreter,
5303 bool acceptStl=
false)
5309 if (clang::TemplateArgument::Type != arg.getKind())
return 0;
5311 auto argQualType = arg.getAsType();
5314 while (llvm::isa<clang::PointerType>(argQualType.getTypePtr())) argQualType = argQualType->getPointeeType();
5316 auto argTypePtr = argQualType.getTypePtr();
5319 if (llvm::isa<clang::EnumType>(argTypePtr)){
5324 if (llvm::isa<clang::BuiltinType>(argTypePtr)){
5329 if (
auto tdTypePtr = llvm::dyn_cast<clang::TypedefType>(argTypePtr)) {
5330 FwdDeclFromTypeDefNameDecl(*tdTypePtr->getDecl(), interpreter, argFwdDecl);
5334 if (
auto argRecTypePtr = llvm::dyn_cast<clang::RecordType>(argTypePtr)){
5336 if (
auto argRecDeclPtr = argRecTypePtr->getDecl()){
5337 FwdDeclFromRcdDecl(*argRecDeclPtr,interpreter,argFwdDecl,acceptStl);
5349 const cling::Interpreter& interpreter,
5350 std::string& defString,
5351 const std::string &normalizedName)
5355 if (
auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)) {
5356 if (
const auto *specDef = tmplSpecDeclPtr->getDefinition()) {
5357 if (specDef->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization)
5361 std::cout <<
" Forward declaring template spec " << normalizedName <<
":\n";
5362 for (
auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()) {
5363 std::string argFwdDecl;
5366 std::cout <<
" o Template argument ";
5368 std::cout <<
"successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5370 std::cout <<
"could not be treated. Abort fwd declaration generation.\n";
5377 defString += argFwdDecl +
'\n';
5379 defString +=
"template <> class " + normalizedName +
';';
5393 const cling::Interpreter& interpreter,
5394 std::string& defString,
5402 if (!recordDecl.getIdentifier())
5406 std::string argsFwdDecl;
5408 if (
auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)){
5409 std::string argFwdDecl;
5411 std::cout <<
"Class " << recordDecl.getNameAsString()
5412 <<
" is a template specialisation. Treating its arguments.\n";
5413 for(
auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()){
5416 std::cout <<
" o Template argument ";
5418 std::cout <<
"successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5420 std::cout <<
"could not be treated. Abort fwd declaration generation.\n";
5427 argsFwdDecl+=argFwdDecl;
5431 defString=argsFwdDecl;
5436 if (
auto tmplDeclPtr = tmplSpecDeclPtr->getSpecializedTemplate()){
5439 defString = argsFwdDecl +
"\n" + defString;
5444 defString =
"class " + recordDecl.getNameAsString() +
";";
5445 const clang::RecordDecl* rcd =
EncloseInScopes(recordDecl, defString);
5453 defString = argsFwdDecl +
"\n" + defString;
5464 const cling::Interpreter& interpreter,
5465 std::string& fwdDeclString,
5466 std::unordered_set<std::string>* fwdDeclSetPtr)
5468 std::string buffer = tdnDecl.getNameAsString();
5469 std::string underlyingName;
5470 auto underlyingType = tdnDecl.getUnderlyingType().getCanonicalType();
5471 if (
const clang::TagType* TT
5472 = llvm::dyn_cast<clang::TagType>(underlyingType.getTypePtr())) {
5473 if (clang::NamedDecl* ND = TT->getDecl()) {
5474 if (!ND->getIdentifier()) {
5488 if (underlyingName.find(
">::") != std::string::npos)
5491 buffer=
"typedef "+underlyingName+
" "+buffer+
";";
5503 auto& ctxt = tdnDecl.getASTContext();
5504 auto immediatelyUnderlyingType = underlyingType.getSingleStepDesugaredType(ctxt);
5506 if (
auto underlyingTdnTypePtr = llvm::dyn_cast<clang::TypedefType>(immediatelyUnderlyingType.getTypePtr())){
5507 std::string tdnFwdDecl;
5508 auto underlyingTdnDeclPtr = underlyingTdnTypePtr->getDecl();
5513 if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(tdnFwdDecl).second)
5514 fwdDeclString+=tdnFwdDecl;
5515 }
else if (
auto CXXRcdDeclPtr = immediatelyUnderlyingType->getAsCXXRecordDecl()){
5516 std::string classFwdDecl;
5518 std::cout <<
"Typedef " << tdnDecl.getNameAsString() <<
" hides a class: "
5519 << CXXRcdDeclPtr->getNameAsString() << std::endl;
5528 if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(classFwdDecl).second)
5529 fwdDeclString+=classFwdDecl;
5532 fwdDeclString+=buffer;
5544 std::string& valAsString,
5545 const clang::PrintingPolicy& ppolicy)
5547 auto defArgExprPtr = par.getDefaultArg();
5548 auto& ctxt = par.getASTContext();
5549 if(!defArgExprPtr->isEvaluatable(ctxt)){
5553 auto defArgType = par.getType();
5556 if (defArgType->isBooleanType()){
5558 defArgExprPtr->EvaluateAsBooleanCondition (result,ctxt);
5559 valAsString=std::to_string(result);
5564 if (defArgType->isIntegerType()){
5565 clang::Expr::EvalResult evalResult;
5566 defArgExprPtr->EvaluateAsInt(evalResult, ctxt);
5567 llvm::APSInt result = evalResult.Val.getInt();
5568 auto uintVal = *result.getRawData();
5569 if (result.isNegative()){
5570 long long int intVal=uintVal*-1;
5571 valAsString=std::to_string(intVal);
5573 valAsString=std::to_string(uintVal);
5580 llvm::raw_string_ostream rso(valAsString);
5581 defArgExprPtr->printPretty(rso,
nullptr,ppolicy);
5582 valAsString = rso.str();
The file contains utilities which are foundational and could be used across the core component of ROO...
static void indent(ostringstream &buf, int indent_level)
static bool RecurseKeepNParams(clang::TemplateArgument &normTArg, const clang::TemplateArgument &tArg, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const clang::ASTContext &astCtxt)
static clang::SourceLocation getFinalSpellingLoc(clang::SourceManager &sourceManager, clang::SourceLocation sourceLoc)
const clang::DeclContext * GetEnclosingSpace(const clang::RecordDecl &cl)
bool IsTemplate(const clang::Decl &cl)
static void KeepNParams(clang::QualType &normalizedType, const clang::QualType &vanillaType, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
This function allows to manipulate the number of arguments in the type of a template specialisation.
const clang::CXXMethodDecl * GetMethodWithProto(const clang::Decl *cinfo, const char *method, const char *proto, const cling::Interpreter &interp, bool diagnose)
int dumpDeclForAssert(const clang::Decl &D, const char *commentStart)
static void replaceEnvVars(const char *varname, std::string &txt)
Reimplementation of TSystem::ExpandPathName() that cannot be used from TMetaUtils.
static bool areEqualValues(const clang::TemplateArgument &tArg, const clang::NamedDecl &tPar)
std::cout << "Are equal values?\n";
ROOT::TMetaUtils::TNormalizedCtxtImpl TNCtxtFullQual
static bool isTypeWithDefault(const clang::NamedDecl *nDecl)
Check if this NamedDecl is a template parameter with a default argument.
static int TreatSingleTemplateArg(const clang::TemplateArgument &arg, std::string &argFwdDecl, const cling::Interpreter &interpreter, bool acceptStl=false)
static bool areEqualTypes(const clang::TemplateArgument &tArg, llvm::SmallVectorImpl< clang::TemplateArgument > &preceedingTArgs, const clang::NamedDecl &tPar, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
static bool hasSomeTypedefSomewhere(const clang::Type *T)
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
const_iterator begin() const
const std::string & GetPathSeparator()
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
void WriteSchemaList(std::list< SchemaRuleMap_t > &rules, const std::string &listName, std::ostream &output)
Write schema rules.
std::map< std::string, ROOT::Internal::TSchemaType > MembersTypeMap_t
void WriteReadRuleFunc(SchemaRuleMap_t &rule, int index, std::string &mappedName, MembersTypeMap_t &members, std::ostream &output)
Write the conversion function for Read rule, the function name is being written to rule["funcname"].
R__EXTERN SchemaRuleClassMap_t gReadRules
bool HasValidDataMembers(SchemaRuleMap_t &rule, MembersTypeMap_t &members, std::string &error_string)
Check if given rule contains references to valid data members.
void WriteReadRawRuleFunc(SchemaRuleMap_t &rule, int index, std::string &mappedName, MembersTypeMap_t &members, std::ostream &output)
Write the conversion function for ReadRaw rule, the function name is being written to rule["funcname"...
R__EXTERN SchemaRuleClassMap_t gReadRawRules
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
char * DemangleName(const char *mangled_name, int &errorCode)
std::string GetNameForIO(const std::string &templateInstanceName, TClassEdit::EModType mode=TClassEdit::kNone, bool *hasChanged=nullptr)
bool IsSTLBitset(const char *type)
Return true is the name is std::bitset<number> or bitset<number>
void ShortType(std::string &answer, int mode)
Return the absolute type of typeDesc into the string answ.
#define dest(otri, vertexptr)