Logo ROOT  
Reference Guide
TClingUtils.cxx
Go to the documentation of this file.
1 // @(#)root/metautils:$Id$
2 // Author: Paul Russo, 2009-10-06
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //______________________________________________________________________________
13 // //
14 // ROOT::TMetaUtils provides utility wrappers around //
15 // cling, the LLVM-based interpreter. It's an internal set of tools //
16 // used by TCling and rootcling. //
17 // //
18 //______________________________________________________________________________
19 #include <algorithm>
20 #include <iostream>
21 #include <sstream>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <unordered_set>
25 
26 #include "RConfigure.h"
27 #include <ROOT/RConfig.hxx>
28 #include <ROOT/FoundationUtils.hxx>
29 #include "Rtypes.h"
30 #include "strlcpy.h"
31 
32 #include "RStl.h"
33 
34 #include "clang/AST/ASTContext.h"
35 #include "clang/AST/Attr.h"
36 #include "clang/AST/CXXInheritance.h"
37 #include "clang/AST/Decl.h"
38 #include "clang/AST/DeclTemplate.h"
39 #include "clang/AST/Mangle.h"
40 #include "clang/AST/Type.h"
41 #include "clang/AST/TypeVisitor.h"
42 #include "clang/Frontend/CompilerInstance.h"
43 #include "clang/Lex/HeaderSearch.h"
44 #include "clang/Lex/ModuleMap.h"
45 #include "clang/Lex/Preprocessor.h"
46 #include "clang/Lex/PreprocessorOptions.h"
47 
48 #include "clang/Sema/Sema.h"
49 #include "clang/Sema/SemaDiagnostic.h"
50 
51 #include "cling/Interpreter/LookupHelper.h"
52 #include "cling/Interpreter/Transaction.h"
53 #include "cling/Interpreter/Interpreter.h"
54 #include "cling/Utils/AST.h"
55 
56 #include "llvm/Support/Path.h"
57 #include "llvm/Support/FileSystem.h"
58 
59 // Intentionally access non-public header ...
60 #include "../../../interpreter/llvm/src/tools/clang/lib/Sema/HackForDefaultTemplateArg.h"
61 
62 #include "TClingUtils.h"
63 
64 #ifdef _WIN32
65 #define strncasecmp _strnicmp
66 #include <io.h>
67 #else
68 #include <unistd.h>
69 #endif // _WIN32
70 
71 namespace ROOT {
72 namespace TMetaUtils {
73 
74 std::string GetRealPath(const std::string &path)
75 {
76  llvm::SmallString<256> result_path;
77  llvm::sys::fs::real_path(path, result_path, /*expandTilde*/true);
78  return result_path.str().str();
79 }
80 
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 
85  using DeclsCont_t = TNormalizedCtxt::Config_t::SkipCollection;
89 private:
93 public:
94  TNormalizedCtxtImpl(const cling::LookupHelper &lh);
95 
96  const Config_t &GetConfig() const { return fConfig; }
98  void AddTemplAndNargsToKeep(const clang::ClassTemplateDecl* templ, unsigned int i);
99  int GetNargsToKeep(const clang::ClassTemplateDecl* templ) const;
101  void keepTypedef(const cling::LookupHelper &lh, const char* name,
102  bool replace = false);
103 };
104 }
105 }
106 
107 namespace {
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Add default parameter to the scope if needed.
111 
112 static clang::NestedNameSpecifier *AddDefaultParametersNNS(const clang::ASTContext& Ctx,
113  clang::NestedNameSpecifier* scope,
114  const cling::Interpreter &interpreter,
115  const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) {
116  if (!scope) return nullptr;
117 
118  const clang::Type* scope_type = scope->getAsType();
119  if (scope_type) {
120  // this is not a namespace, so we might need to desugar
121  clang::NestedNameSpecifier* outer_scope = scope->getPrefix();
122  if (outer_scope) {
123  outer_scope = AddDefaultParametersNNS(Ctx, outer_scope, interpreter, normCtxt);
124  }
125 
126  clang::QualType addDefault =
127  ROOT::TMetaUtils::AddDefaultParameters(clang::QualType(scope_type,0), interpreter, normCtxt );
128  // NOTE: Should check whether the type has changed or not.
129  if (addDefault.getTypePtr() != scope_type)
130  return clang::NestedNameSpecifier::Create(Ctx,outer_scope,
131  false /* template keyword wanted */,
132  addDefault.getTypePtr());
133  }
134  return scope;
135 }
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 
139 static bool CheckDefinition(const clang::CXXRecordDecl *cl, const clang::CXXRecordDecl *context)
140 {
141  if (!cl->hasDefinition()) {
142  if (context) {
143  ROOT::TMetaUtils::Error("CheckDefinition",
144  "Missing definition for class %s, please #include its header in the header of %s\n",
145  cl->getName().str().c_str(), context->getName().str().c_str());
146  } else {
147  ROOT::TMetaUtils::Error("CheckDefinition",
148  "Missing definition for class %s\n",
149  cl->getName().str().c_str());
150  }
151  return false;
152  }
153  return true;
154 }
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Check if 'scope' or any of its template parameter was substituted when
158 /// instantiating the class template instance and replace it with the
159 /// partially sugared types we have from 'instance'.
160 
161 static clang::NestedNameSpecifier *ReSubstTemplateArgNNS(const clang::ASTContext &Ctxt,
162  clang::NestedNameSpecifier *scope,
163  const clang::Type *instance)
164 {
165  if (!scope) return nullptr;
166 
167  const clang::Type* scope_type = scope->getAsType();
168  if (scope_type) {
169  clang::NestedNameSpecifier* outer_scope = scope->getPrefix();
170  if (outer_scope) {
171  outer_scope = ReSubstTemplateArgNNS(Ctxt, outer_scope, instance);
172  }
173  clang::QualType substScope =
174  ROOT::TMetaUtils::ReSubstTemplateArg(clang::QualType(scope_type,0), instance);
175  // NOTE: Should check whether the type has changed or not.
176  scope = clang::NestedNameSpecifier::Create(Ctxt,outer_scope,
177  false /* template keyword wanted */,
178  substScope.getTypePtr());
179  }
180  return scope;
181 }
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 
185 static bool IsTypeInt(const clang::Type *type)
186 {
187  const clang::BuiltinType * builtin = llvm::dyn_cast<clang::BuiltinType>(type->getCanonicalTypeInternal().getTypePtr());
188  if (builtin) {
189  return builtin->isInteger(); // builtin->getKind() == clang::BuiltinType::Int;
190  } else {
191  return false;
192  }
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 
197 static bool IsFieldDeclInt(const clang::FieldDecl *field)
198 {
199  return IsTypeInt(field->getType().getTypePtr());
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Return a data member name 'what' in the class described by 'cl' if any.
204 
205 static const clang::FieldDecl *GetDataMemberFromAll(const clang::CXXRecordDecl &cl, llvm::StringRef what)
206 {
207  for(clang::RecordDecl::field_iterator field_iter = cl.field_begin(), end = cl.field_end();
208  field_iter != end;
209  ++field_iter){
210  if (field_iter->getName() == what) {
211  return *field_iter;
212  }
213  }
214  return nullptr;
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 
219 static bool CXXRecordDecl__FindOrdinaryMember(const clang::CXXBaseSpecifier *Specifier,
220  clang::CXXBasePath &Path,
221  const char *Name)
222 {
223  if (!Specifier) return false;
224  clang::RecordDecl *BaseRecord = Specifier->getType()->getAs<clang::RecordType>()->getDecl();
225 
226  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(BaseRecord);
227  if (!clxx) return false;
228 
229  const clang::FieldDecl *found = GetDataMemberFromAll(*clxx,(const char*)Name);
230  if (found) {
231  // Humm, this is somewhat bad (well really bad), oh well.
232  // Let's hope Paths never thinks it owns those (it should not as far as I can tell).
233  clang::NamedDecl* NonConstFD = const_cast<clang::FieldDecl*>(found);
234  clang::NamedDecl** BaseSpecFirstHack
235  = reinterpret_cast<clang::NamedDecl**>(NonConstFD);
236  Path.Decls = clang::DeclContextLookupResult(llvm::ArrayRef<clang::NamedDecl*>(BaseSpecFirstHack, 1));
237  return true;
238  }
239  //
240  // This is inspired from CXXInheritance.cpp:
241  /*
242  * RecordDecl *BaseRecord =
243  * Specifier->getType()->castAs<RecordType>()->getDecl();
244  *
245  * const unsigned IDNS = clang::Decl::IDNS_Ordinary | clang::Decl::IDNS_Tag | clang::Decl::IDNS_Member;
246  * clang::DeclarationName N = clang::DeclarationName::getFromOpaquePtr(Name);
247  * for (Path.Decls = BaseRecord->lookup(N);
248  * Path.Decls.first != Path.Decls.second;
249  * ++Path.Decls.first) {
250  * if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS))
251  * return true;
252  }
253  */
254  return false;
255 
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Return a data member name 'what' in any of the base classes of the class described by 'cl' if any.
260 
261 static const clang::FieldDecl *GetDataMemberFromAllParents(const clang::CXXRecordDecl &cl, const char *what)
262 {
263  clang::CXXBasePaths Paths;
264  Paths.setOrigin(const_cast<clang::CXXRecordDecl*>(&cl));
265  if (cl.lookupInBases([=](const clang::CXXBaseSpecifier *Specifier, clang::CXXBasePath &Path) {
266  return CXXRecordDecl__FindOrdinaryMember(Specifier, Path, what);}, Paths))
267  {
268  clang::CXXBasePaths::paths_iterator iter = Paths.begin();
269  if (iter != Paths.end()) {
270  // See CXXRecordDecl__FindOrdinaryMember, this is, well, awkward.
271  const clang::FieldDecl *found = (clang::FieldDecl *)iter->Decls.data();
272  return found;
273  }
274  }
275  return nullptr;
276 }
277 
278 static
279 cling::LookupHelper::DiagSetting ToLHDS(bool wantDiags) {
280  return wantDiags
281  ? cling::LookupHelper::WithDiagnostics
282  : cling::LookupHelper::NoDiagnostics;
283 }
284 
285 } // end of anonymous namespace
286 
287 
288 namespace ROOT {
289 namespace TMetaUtils {
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 /// Add to the internal map the pointer of a template as key and the number of
293 /// template arguments to keep as value.
294 
295 void TNormalizedCtxtImpl::AddTemplAndNargsToKeep(const clang::ClassTemplateDecl* templ,
296  unsigned int i){
297  if (!templ){
298  Error("TNormalizedCtxt::AddTemplAndNargsToKeep",
299  "Tring to specify a number of template arguments to keep for a null pointer. Exiting without assigning any value.\n");
300  return;
301  }
302 
303  const clang::ClassTemplateDecl* canTempl = templ->getCanonicalDecl();
304 
305  if(fTemplatePtrArgsToKeepMap.count(canTempl)==1 &&
306  fTemplatePtrArgsToKeepMap[canTempl]!=(int)i){
307  const std::string templateName (canTempl->getNameAsString());
308  const std::string i_str (std::to_string(i));
309  const std::string previousArgsToKeep(std::to_string(fTemplatePtrArgsToKeepMap[canTempl]));
310  Error("TNormalizedCtxt::AddTemplAndNargsToKeep",
311  "Tring to specify for template %s %s arguments to keep, while before this number was %s\n",
312  canTempl->getNameAsString().c_str(),
313  i_str.c_str(),
314  previousArgsToKeep.c_str());
315  }
316 
317  fTemplatePtrArgsToKeepMap[canTempl]=i;
318 }
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Get from the map the number of arguments to keep.
321 /// It uses the canonical decl of the template as key.
322 /// If not present, returns -1.
323 
324 int TNormalizedCtxtImpl::GetNargsToKeep(const clang::ClassTemplateDecl* templ) const{
325  const clang::ClassTemplateDecl* constTempl = templ->getCanonicalDecl();
326  auto thePairPtr = fTemplatePtrArgsToKeepMap.find(constTempl);
327  int nArgsToKeep = (thePairPtr != fTemplatePtrArgsToKeepMap.end() ) ? thePairPtr->second : -1;
328  return nArgsToKeep;
329 }
330 
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 
334 TNormalizedCtxt::TNormalizedCtxt(const cling::LookupHelper &lh):
335  fImpl(new TNormalizedCtxtImpl(lh))
336 {}
337 
339  fImpl(new TNormalizedCtxtImpl(*other.fImpl))
340 {}
341 
343  delete fImpl;
344 }
346  return fImpl->GetConfig();
347 }
349  return fImpl->GetTypeWithAlternative();
350 }
351 void TNormalizedCtxt::AddTemplAndNargsToKeep(const clang::ClassTemplateDecl* templ, unsigned int i)
352 {
353  return fImpl->AddTemplAndNargsToKeep(templ, i);
354 }
355 int TNormalizedCtxt::GetNargsToKeep(const clang::ClassTemplateDecl* templ) const
356 {
357  return fImpl->GetNargsToKeep(templ);
358 }
360  return fImpl->GetTemplNargsToKeepMap();
361 }
362 void TNormalizedCtxt::keepTypedef(const cling::LookupHelper &lh, const char* name,
363  bool replace /*= false*/)
364 {
365  return fImpl->keepTypedef(lh, name, replace);
366 }
367 
368 std::string AnnotatedRecordDecl::BuildDemangledTypeInfo(const clang::RecordDecl *rDecl,
369  const std::string &normalizedName)
370 {
371  // Types with strong typedefs must not be findable through demangled type names, or else
372  // the demangled name will resolve to both sinblings double / Double32_t.
373  if (normalizedName.find("Double32_t") != std::string::npos
374  || normalizedName.find("Float16_t") != std::string::npos)
375  return {};
376  std::unique_ptr<clang::MangleContext> mangleCtx(rDecl->getASTContext().createMangleContext());
377  std::string mangledName;
378  {
379  llvm::raw_string_ostream sstr(mangledName);
380  if (const clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(rDecl)) {
381  mangleCtx->mangleCXXRTTI(clang::QualType(TD->getTypeForDecl(), 0), sstr);
382  }
383  }
384  if (!mangledName.empty()) {
385  int errDemangle = 0;
386 #ifdef WIN32
387  if (mangledName[0] == '\01')
388  mangledName.erase(0, 1);
389  char *demangledTIName = TClassEdit::DemangleName(mangledName.c_str(), errDemangle);
390  if (!errDemangle && demangledTIName) {
391  static const char typeinfoNameFor[] = " `RTTI Type Descriptor'";
392  if (strstr(demangledTIName, typeinfoNameFor)) {
393  std::string demangledName = demangledTIName;
394  demangledName.erase(demangledName.end() - strlen(typeinfoNameFor), demangledName.end());
395 #else
396  char* demangledTIName = TClassEdit::DemangleName(mangledName.c_str(), errDemangle);
397  if (!errDemangle && demangledTIName) {
398  static const char typeinfoNameFor[] = "typeinfo for ";
399  if (!strncmp(demangledTIName, typeinfoNameFor, strlen(typeinfoNameFor))) {
400  std::string demangledName = demangledTIName + strlen(typeinfoNameFor);
401 #endif
402  free(demangledTIName);
403  return demangledName;
404  } else {
405 #ifdef WIN32
406  ROOT::TMetaUtils::Error("AnnotatedRecordDecl::BuildDemangledTypeInfo",
407  "Demangled typeinfo name '%s' does not contain `RTTI Type Descriptor'\n",
408  demangledTIName);
409 #else
410  ROOT::TMetaUtils::Error("AnnotatedRecordDecl::BuildDemangledTypeInfo",
411  "Demangled typeinfo name '%s' does not start with 'typeinfo for'\n",
412  demangledTIName);
413 #endif
414  } // if demangled type_info starts with "typeinfo for "
415  } // if demangling worked
416  free(demangledTIName);
417  } // if mangling worked
418  return {};
419 }
420 
421 
422 ////////////////////////////////////////////////////////////////////////////////
423 /// There is no requested type name.
424 /// Still let's normalized the actual name.
425 
427  const clang::RecordDecl *decl,
428  bool rStreamerInfo,
429  bool rNoStreamer,
430  bool rRequestNoInputOperator,
431  bool rRequestOnlyTClass,
432  int rRequestedVersionNumber,
433  const cling::Interpreter &interpreter,
434  const TNormalizedCtxt &normCtxt) :
435  fRuleIndex(index), fDecl(decl), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer),
436  fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestedVersionNumber)
437 {
438  TMetaUtils::GetNormalizedName(fNormalizedName, decl->getASTContext().getTypeDeclType(decl), interpreter,normCtxt);
440 }
441 
442 ////////////////////////////////////////////////////////////////////////////////
443 /// Normalize the requested type name.
444 
446  const clang::Type *requestedType,
447  const clang::RecordDecl *decl,
448  const char *requestName,
449  unsigned int nTemplateArgsToSkip,
450  bool rStreamerInfo,
451  bool rNoStreamer,
452  bool rRequestNoInputOperator,
453  bool rRequestOnlyTClass,
454  int rRequestVersionNumber,
455  const cling::Interpreter &interpreter,
456  const TNormalizedCtxt &normCtxt) :
457  fRuleIndex(index), fDecl(decl), fRequestedName(""), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer),
458  fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber)
459 {
460  // For comparison purposes.
462  splitname1.ShortType(fRequestedName, 0);
463 
464  TMetaUtils::GetNormalizedName( fNormalizedName, clang::QualType(requestedType,0), interpreter, normCtxt);
465  if ( 0!=TMetaUtils::RemoveTemplateArgsFromName( fNormalizedName, nTemplateArgsToSkip) ){
466  ROOT::TMetaUtils::Warning("AnnotatedRecordDecl",
467  "Could not remove the requested template arguments.\n");
468  }
470 }
471 
472 ////////////////////////////////////////////////////////////////////////////////
473 /// Normalize the requested type name.
474 
476  const clang::Type *requestedType,
477  const clang::RecordDecl *decl,
478  const char *requestName,
479  bool rStreamerInfo,
480  bool rNoStreamer,
481  bool rRequestNoInputOperator,
482  bool rRequestOnlyTClass,
483  int rRequestVersionNumber,
484  const cling::Interpreter &interpreter,
485  const TNormalizedCtxt &normCtxt) :
486  fRuleIndex(index), fDecl(decl), fRequestedName(""), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer),
487  fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber)
488 {
489  // For comparison purposes.
491  splitname1.ShortType(fRequestedName, 0);
492 
493  TMetaUtils::GetNormalizedName( fNormalizedName, clang::QualType(requestedType,0), interpreter, normCtxt);
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 /// Normalize the requested name.
499 
501  const clang::RecordDecl *decl,
502  const char *requestName,
503  bool rStreamerInfo,
504  bool rNoStreamer,
505  bool rRequestNoInputOperator,
506  bool rRequestOnlyTClass,
507  int rRequestVersionNumber,
508  const cling::Interpreter &interpreter,
509  const TNormalizedCtxt &normCtxt) :
510  fRuleIndex(index), fDecl(decl), fRequestedName(""), fRequestStreamerInfo(rStreamerInfo), fRequestNoStreamer(rNoStreamer), fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber)
511 {
512  // const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (decl);
513  // if (tmplt_specialization) {
514  // tmplt_specialization->getTemplateArgs ().data()->print(decl->getASTContext().getPrintingPolicy(),llvm::outs());
515  // llvm::outs() << "\n";
516  // }
517  // const char *current = requestName;
518  // Strips spaces and std::
519  if (requestName && requestName[0]) {
522 
524  } else {
525  TMetaUtils::GetNormalizedName( fNormalizedName, decl->getASTContext().getTypeDeclType(decl),interpreter,normCtxt);
526  }
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 
532 TClingLookupHelper::TClingLookupHelper(cling::Interpreter &interpreter,
533  TNormalizedCtxt &normCtxt,
534  ExistingTypeCheck_t existingTypeCheck,
535  AutoParse_t autoParse,
536  bool *shuttingDownPtr,
537  const int* pgDebug /*= 0*/):
538  fInterpreter(&interpreter),fNormalizedCtxt(&normCtxt),
539  fExistingTypeCheck(existingTypeCheck),
540  fAutoParse(autoParse),
541  fInterpreterIsShuttingDownPtr(shuttingDownPtr),
542  fPDebug(pgDebug)
543 {
544 }
545 
546 ////////////////////////////////////////////////////////////////////////////////
547 /// Helper routine to ry hard to avoid looking up in the Cling database as
548 /// this could enduce an unwanted autoparsing.
549 
550 bool TClingLookupHelper::ExistingTypeCheck(const std::string &tname,
551  std::string &result)
552 {
553  if (tname.empty()) return false;
554 
555  if (fExistingTypeCheck) return fExistingTypeCheck(tname,result);
556  else return false;
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 
562 {
563  const cling::LookupHelper& lh = fInterpreter->getLookupHelper();
564  clang::QualType t = lh.findType(nameLong, ToLHDS(WantDiags()));
565  if (!t.isNull()) {
566  clang::QualType dest = cling::utils::Transform::GetPartiallyDesugaredType(fInterpreter->getCI()->getASTContext(), t, fNormalizedCtxt->GetConfig(), true /* fully qualify */);
567  if (!dest.isNull() && (dest != t)) {
568  // getAsStringInternal() appends.
569  nameLong.clear();
570  dest.getAsStringInternal(nameLong, fInterpreter->getCI()->getASTContext().getPrintingPolicy());
571  }
572  }
573 }
574 
575 ////////////////////////////////////////////////////////////////////////////////
576 
578  const std::string &nameLong)
579 {
580  const cling::LookupHelper& lh = fInterpreter->getLookupHelper();
581  clang::QualType t = lh.findType(nondef.c_str(), ToLHDS(WantDiags()));
582  if (!t.isNull()) {
583  clang::QualType dest = cling::utils::Transform::GetPartiallyDesugaredType(fInterpreter->getCI()->getASTContext(), t, fNormalizedCtxt->GetConfig(), true /* fully qualify */);
584  if (!dest.isNull() && (dest != t) &&
585  nameLong == t.getAsString(fInterpreter->getCI()->getASTContext().getPrintingPolicy()))
586  return true;
587  }
588  return false;
589 }
590 
591 ////////////////////////////////////////////////////////////////////////////////
592 
593 bool TClingLookupHelper::IsDeclaredScope(const std::string &base, bool &isInlined)
594 {
595  const cling::LookupHelper& lh = fInterpreter->getLookupHelper();
596  const clang::Decl *scope = lh.findScope(base.c_str(), ToLHDS(WantDiags()), 0);
597 
598  if (!scope) {
599  // the nesting namespace is not declared
600  isInlined = false;
601  return false;
602  }
603  const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(scope);
604  isInlined = nsdecl && nsdecl->isInline();
605  return true;
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////////
609 /// We assume that we have a simple type:
610 /// [const] typename[*&][const]
611 
613  std::string &result,
614  bool dropstd /* = true */)
615 {
616  if (tname.empty()) return false;
617 
618  // Try hard to avoid looking up in the Cling database as this could enduce
619  // an unwanted autoparsing.
620  // Note: this is always done by the callers and thus is redundant.
621  // Maybe replace with
622  assert(! (fExistingTypeCheck && fExistingTypeCheck(tname,result)) );
623  if (fExistingTypeCheck && fExistingTypeCheck(tname,result)) {
624  return ! result.empty();
625  }
626 
627  if (fAutoParse) fAutoParse(tname.c_str());
628 
629  // Since we already check via other means (TClassTable which is populated by
630  // the dictonary loading, and the gROOT list of classes and enums, which are
631  // populated via TProtoClass/Enum), we should be able to disable the autoloading
632  // ... which requires access to libCore or libCling ...
633  const cling::LookupHelper& lh = fInterpreter->getLookupHelper();
634  clang::QualType t = lh.findType(tname.c_str(), ToLHDS(WantDiags()));
635  // Technically we ought to try:
636  // if (t.isNull()) t = lh.findType(TClassEdit::InsertStd(tname), ToLHDS(WantDiags()));
637  // at least until the 'normalized name' contains the std:: prefix.
638 
639  if (!t.isNull()) {
641  if (!dest.isNull() && dest != t) {
642  // Since our input is not a template instance name, rather than going through the full
643  // TMetaUtils::GetNormalizedName, we just do the 'strip leading std' and fix
644  // white space.
645  clang::PrintingPolicy policy(fInterpreter->getCI()->getASTContext().getPrintingPolicy());
646  policy.SuppressTagKeyword = true; // Never get the class or struct keyword
647  policy.SuppressScope = true; // Force the scope to be coming from a clang::ElaboratedType.
648  // The scope suppression is required for getting rid of the anonymous part of the name of a class defined in an anonymous namespace.
649  // This gives us more control vs not using the clang::ElaboratedType and relying on the Policy.SuppressUnwrittenScope which would
650  // strip both the anonymous and the inline namespace names (and we probably do not want the later to be suppressed).
651  // getAsStringInternal() appends.
652  result.clear();
653  dest.getAsStringInternal(result, policy);
654  // Strip the std::
655  unsigned long offset = 0;
656  if (strncmp(result.c_str(), "const ", 6) == 0) {
657  offset = 6;
658  }
659  if (dropstd && strncmp(result.c_str()+offset, "std::", 5) == 0) {
660  result.erase(offset,5);
661  }
662  for(unsigned int i = 1; i<result.length(); ++i) {
663  if (result[i]=='s') {
664  if (result[i-1]=='<' || result[i-1]==',' || result[i-1]==' ') {
665  if (dropstd && result.compare(i,5,"std::",5) == 0) {
666  result.erase(i,5);
667  }
668  }
669  }
670  if (result[i]==' ') {
671  if (result[i-1] == ',') {
672  result.erase(i,1);
673  --i;
674  } else if ( (i+1) < result.length() &&
675  (result[i+1]=='*' || result[i+1]=='&' || result[i+1]=='[') ) {
676  result.erase(i,1);
677  --i;
678  }
679  }
680  }
681 
682 // std::string alt;
683 // TMetaUtils::GetNormalizedName(alt, dest, *fInterpreter, *fNormalizedCtxt);
684 // if (alt != result) fprintf(stderr,"norm: %s vs result=%s\n",alt.c_str(),result.c_str());
685 
686  return true;
687  }
688  }
689  return false;
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 // TClassEdit will call this routine as soon as any of its static variable (used
694 // for caching) is destroyed.
696 {
699 }
700 
701  } // end namespace ROOT
702 } // end namespace TMetaUtils
703 
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Insert the type with name into the collection of typedefs to keep.
707 /// if replace, replace occurrences of the canonical type by name.
708 
709 void ROOT::TMetaUtils::TNormalizedCtxtImpl::keepTypedef(const cling::LookupHelper &lh,
710  const char* name,
711  bool replace /*=false*/) {
712  clang::QualType toSkip = lh.findType(name, cling::LookupHelper::WithDiagnostics);
713  if (const clang::Type* T = toSkip.getTypePtr()) {
714  const clang::TypedefType *tt = llvm::dyn_cast<clang::TypedefType>(T);
715  if (!tt) return;
716  clang::Decl* D = tt->getDecl();
717  fConfig.m_toSkip.insert(D);
718  if (replace) {
719  clang::QualType canon = toSkip->getCanonicalTypeInternal();
720  fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),T));
721  } else {
722  fTypeWithAlternative.insert(T);
723  }
724  }
725 }
726 
727 ////////////////////////////////////////////////////////////////////////////////
728 /// Initialize the list of typedef to keep (i.e. make them opaque for normalization)
729 /// and the list of typedef whose semantic is different from their underlying type
730 /// (Double32_t and Float16_t).
731 /// This might be specific to an interpreter.
732 
734 {
735  keepTypedef(lh, "Double32_t");
736  keepTypedef(lh, "Float16_t");
737  keepTypedef(lh, "Long64_t", true);
738  keepTypedef(lh, "ULong64_t", true);
739 
740  clang::QualType toSkip = lh.findType("string", cling::LookupHelper::WithDiagnostics);
741  if (!toSkip.isNull()) {
742  if (const clang::TypedefType* TT
743  = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
744  fConfig.m_toSkip.insert(TT->getDecl());
745  }
746  toSkip = lh.findType("std::string", cling::LookupHelper::WithDiagnostics);
747  if (!toSkip.isNull()) {
748  if (const clang::TypedefType* TT
749  = llvm::dyn_cast_or_null<clang::TypedefType>(toSkip.getTypePtr()))
750  fConfig.m_toSkip.insert(TT->getDecl());
751 
752  clang::QualType canon = toSkip->getCanonicalTypeInternal();
753  fConfig.m_toReplace.insert(std::make_pair(canon.getTypePtr(),toSkip.getTypePtr()));
754  }
755 }
756 
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 
762 inline bool IsTemplate(const clang::Decl &cl)
763 {
764  return (cl.getKind() == clang::Decl::ClassTemplatePartialSpecialization
765  || cl.getKind() == clang::Decl::ClassTemplateSpecialization);
766 }
767 
768 
769 ////////////////////////////////////////////////////////////////////////////////
770 
771 const clang::FunctionDecl* ROOT::TMetaUtils::ClassInfo__HasMethod(const clang::DeclContext *cl, const char* name,
772  const cling::Interpreter& interp)
773 {
774  clang::Sema* S = &interp.getSema();
775  const clang::NamedDecl* ND = cling::utils::Lookup::Named(S, name, cl);
776  if (ND == (clang::NamedDecl*)-1)
777  return (clang::FunctionDecl*)-1;
778  return llvm::dyn_cast_or_null<clang::FunctionDecl>(ND);
779 }
780 
781 ////////////////////////////////////////////////////////////////////////////////
782 /// Return the scope corresponding to 'name' or std::'name'
783 
784 const clang::CXXRecordDecl *
785 ROOT::TMetaUtils::ScopeSearch(const char *name, const cling::Interpreter &interp,
786  bool /*diagnose*/, const clang::Type** resultType)
787 {
788  const cling::LookupHelper& lh = interp.getLookupHelper();
789  // We have many bogus diagnostics if we allow diagnostics here. Suppress.
790  // FIXME: silence them in the callers.
791  const clang::CXXRecordDecl *result
792  = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
793  (lh.findScope(name, cling::LookupHelper::NoDiagnostics, resultType));
794  if (!result) {
795  std::string std_name("std::");
796  std_name += name;
797  // We have many bogus diagnostics if we allow diagnostics here. Suppress.
798  // FIXME: silence them in the callers.
799  result = llvm::dyn_cast_or_null<clang::CXXRecordDecl>
800  (lh.findScope(std_name, cling::LookupHelper::NoDiagnostics, resultType));
801  }
802  return result;
803 }
804 
805 
806 ////////////////////////////////////////////////////////////////////////////////
807 
808 bool ROOT::TMetaUtils::RequireCompleteType(const cling::Interpreter &interp, const clang::CXXRecordDecl *cl)
809 {
810  clang::QualType qType(cl->getTypeForDecl(),0);
811  return RequireCompleteType(interp,cl->getLocation(),qType);
812 }
813 
814 ////////////////////////////////////////////////////////////////////////////////
815 
816 bool ROOT::TMetaUtils::RequireCompleteType(const cling::Interpreter &interp, clang::SourceLocation Loc, clang::QualType Type)
817 {
818  clang::Sema& S = interp.getCI()->getSema();
819  // Here we might not have an active transaction to handle
820  // the caused instantiation decl.
821  cling::Interpreter::PushTransactionRAII RAII(const_cast<cling::Interpreter*>(&interp));
822  return S.RequireCompleteType(Loc, Type, clang::diag::err_incomplete_type);
823 }
824 
825 ////////////////////////////////////////////////////////////////////////////////
826 
827 bool ROOT::TMetaUtils::IsBase(const clang::CXXRecordDecl *cl, const clang::CXXRecordDecl *base,
828  const clang::CXXRecordDecl *context, const cling::Interpreter &interp)
829 {
830  if (!cl || !base) {
831  return false;
832  }
833 
834  if (!cl->getDefinition() || !cl->isCompleteDefinition()) {
835  RequireCompleteType(interp,cl);
836  }
837 
838  if (!CheckDefinition(cl, context) || !CheckDefinition(base, context)) {
839  return false;
840  }
841 
842  if (!base->hasDefinition()) {
843  ROOT::TMetaUtils::Error("IsBase", "Missing definition for class %s\n", base->getName().str().c_str());
844  return false;
845  }
846  return cl->isDerivedFrom(base);
847 }
848 
849 ////////////////////////////////////////////////////////////////////////////////
850 
851 bool ROOT::TMetaUtils::IsBase(const clang::FieldDecl &m, const char* basename, const cling::Interpreter &interp)
852 {
853  const clang::CXXRecordDecl* CRD = llvm::dyn_cast<clang::CXXRecordDecl>(ROOT::TMetaUtils::GetUnderlyingRecordDecl(m.getType()));
854  if (!CRD) {
855  return false;
856  }
857 
858  const clang::NamedDecl *base
859  = ScopeSearch(basename, interp, true /*diagnose*/, 0);
860 
861  if (base) {
862  return IsBase(CRD, llvm::dyn_cast<clang::CXXRecordDecl>( base ),
863  llvm::dyn_cast<clang::CXXRecordDecl>(m.getDeclContext()),interp);
864  }
865  return false;
866 }
867 
868 ////////////////////////////////////////////////////////////////////////////////
869 
870 int ROOT::TMetaUtils::ElementStreamer(std::ostream& finalString,
871  const clang::NamedDecl &forcontext,
872  const clang::QualType &qti,
873  const char *R__t,int rwmode,
874  const cling::Interpreter &interp,
875  const char *tcl)
876 {
877  static const clang::CXXRecordDecl *TObject_decl
878  = ROOT::TMetaUtils::ScopeSearch("TObject", interp, true /*diag*/, 0);
879  enum {
880  kBIT_ISTOBJECT = 0x10000000,
881  kBIT_HASSTREAMER = 0x20000000,
882  kBIT_ISSTRING = 0x40000000,
883 
884  kBIT_ISPOINTER = 0x00001000,
885  kBIT_ISFUNDAMENTAL = 0x00000020,
886  kBIT_ISENUM = 0x00000008
887  };
888 
889  const clang::Type &ti( * qti.getTypePtr() );
890  std::string tiName;
891  ROOT::TMetaUtils::GetQualifiedName(tiName, clang::QualType(&ti,0), forcontext);
892 
893  std::string objType(ROOT::TMetaUtils::ShortTypeName(tiName.c_str()));
894 
895  const clang::Type *rawtype = ROOT::TMetaUtils::GetUnderlyingType(clang::QualType(&ti,0));
896  std::string rawname;
897  ROOT::TMetaUtils::GetQualifiedName(rawname, clang::QualType(rawtype,0), forcontext);
898 
899  clang::CXXRecordDecl *cxxtype = rawtype->getAsCXXRecordDecl() ;
900  int isStre = cxxtype && ROOT::TMetaUtils::ClassInfo__HasMethod(cxxtype,"Streamer",interp);
901  int isTObj = cxxtype && (IsBase(cxxtype,TObject_decl,nullptr,interp) || rawname == "TObject");
902 
903  long kase = 0;
904 
905  if (ti.isPointerType()) kase |= kBIT_ISPOINTER;
906  if (rawtype->isFundamentalType()) kase |= kBIT_ISFUNDAMENTAL;
907  if (rawtype->isEnumeralType()) kase |= kBIT_ISENUM;
908 
909 
910  if (isTObj) kase |= kBIT_ISTOBJECT;
911  if (isStre) kase |= kBIT_HASSTREAMER;
912  if (tiName == "string") kase |= kBIT_ISSTRING;
913  if (tiName == "string*") kase |= kBIT_ISSTRING;
914 
915 
916  if (tcl == 0) {
917  tcl = " internal error in rootcling ";
918  }
919  // if (strcmp(objType,"string")==0) RStl::Instance().GenerateTClassFor( "string", interp, normCtxt );
920 
921  if (rwmode == 0) { //Read mode
922 
923  if (R__t) finalString << " " << tiName << " " << R__t << ";" << std::endl;
924  switch (kase) {
925 
926  case kBIT_ISFUNDAMENTAL:
927  if (!R__t) return 0;
928  finalString << " R__b >> " << R__t << ";" << std::endl;
929  break;
930 
931  case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
932  if (!R__t) return 1;
933  finalString << " " << R__t << " = (" << tiName << ")R__b.ReadObjectAny(" << tcl << ");" << std::endl;
934  break;
935 
936  case kBIT_ISENUM:
937  if (!R__t) return 0;
938  // fprintf(fp, " R__b >> (Int_t&)%s;\n",R__t);
939  // On some platforms enums and not 'Int_t' and casting to a reference to Int_t
940  // induces the silent creation of a temporary which is 'filled' __instead of__
941  // the desired enum. So we need to take it one step at a time.
942  finalString << " Int_t readtemp;" << std::endl
943  << " R__b >> readtemp;" << std::endl
944  << " " << R__t << " = static_cast<" << tiName << ">(readtemp);" << std::endl;
945  break;
946 
947  case kBIT_HASSTREAMER:
948  case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
949  if (!R__t) return 0;
950  finalString << " " << R__t << ".Streamer(R__b);" << std::endl;
951  break;
952 
953  case kBIT_HASSTREAMER|kBIT_ISPOINTER:
954  if (!R__t) return 1;
955  //fprintf(fp, " fprintf(stderr,\"info is %%p %%d\\n\",R__b.GetInfo(),R__b.GetInfo()?R__b.GetInfo()->GetOldVersion():-1);\n");
956  finalString << " if (R__b.GetInfo() && R__b.GetInfo()->GetOldVersion()<=3) {" << std::endl;
957  if (cxxtype && cxxtype->isAbstract()) {
958  finalString << " R__ASSERT(0);// " << objType << " is abstract. We assume that older file could not be produced using this streaming method." << std::endl;
959  } else {
960  finalString << " " << R__t << " = new " << objType << ";" << std::endl
961  << " " << R__t << "->Streamer(R__b);" << std::endl;
962  }
963  finalString << " } else {" << std::endl
964  << " " << R__t << " = (" << tiName << ")R__b.ReadObjectAny(" << tcl << ");" << std::endl
965  << " }" << std::endl;
966  break;
967 
968  case kBIT_ISSTRING:
969  if (!R__t) return 0;
970  finalString << " {TString R__str;" << std::endl
971  << " R__str.Streamer(R__b);" << std::endl
972  << " " << R__t << " = R__str.Data();}" << std::endl;
973  break;
974 
975  case kBIT_ISSTRING|kBIT_ISPOINTER:
976  if (!R__t) return 0;
977  finalString << " {TString R__str;" << std::endl
978  << " R__str.Streamer(R__b);" << std::endl
979  << " " << R__t << " = new string(R__str.Data());}" << std::endl;
980  break;
981 
982  case kBIT_ISPOINTER:
983  if (!R__t) return 1;
984  finalString << " " << R__t << " = (" << tiName << ")R__b.ReadObjectAny(" << tcl << ");" << std::endl;
985  break;
986 
987  default:
988  if (!R__t) return 1;
989  finalString << " R__b.StreamObject(&" << R__t << "," << tcl << ");" << std::endl;
990  break;
991  }
992 
993  } else { //Write case
994 
995  switch (kase) {
996 
997  case kBIT_ISFUNDAMENTAL:
998  case kBIT_ISPOINTER|kBIT_ISTOBJECT|kBIT_HASSTREAMER:
999  if (!R__t) return 0;
1000  finalString << " R__b << " << R__t << ";" << std::endl;
1001  break;
1002 
1003  case kBIT_ISENUM:
1004  if (!R__t) return 0;
1005  finalString << " { void *ptr_enum = (void*)&" << R__t << ";\n";
1006  finalString << " R__b >> *reinterpret_cast<Int_t*>(ptr_enum); }" << std::endl;
1007  break;
1008 
1009  case kBIT_HASSTREAMER:
1010  case kBIT_HASSTREAMER|kBIT_ISTOBJECT:
1011  if (!R__t) return 0;
1012  finalString << " ((" << objType << "&)" << R__t << ").Streamer(R__b);" << std::endl;
1013  break;
1014 
1015  case kBIT_HASSTREAMER|kBIT_ISPOINTER:
1016  if (!R__t) return 1;
1017  finalString << " R__b.WriteObjectAny(" << R__t << "," << tcl << ");" << std::endl;
1018  break;
1019 
1020  case kBIT_ISSTRING:
1021  if (!R__t) return 0;
1022  finalString << " {TString R__str(" << R__t << ".c_str());" << std::endl
1023  << " R__str.Streamer(R__b);};" << std::endl;
1024  break;
1025 
1026  case kBIT_ISSTRING|kBIT_ISPOINTER:
1027  if (!R__t) return 0;
1028  finalString << " {TString R__str(" << R__t << "->c_str());" << std::endl
1029  << " R__str.Streamer(R__b);}" << std::endl;
1030  break;
1031 
1032  case kBIT_ISPOINTER:
1033  if (!R__t) return 1;
1034  finalString << " R__b.WriteObjectAny(" << R__t << "," << tcl <<");" << std::endl;
1035  break;
1036 
1037  default:
1038  if (!R__t) return 1;
1039  finalString << " R__b.StreamObject((" << objType << "*)&" << R__t << "," << tcl << ");" << std::endl;
1040  break;
1041  }
1042  }
1043  return 0;
1044 }
1045 
1046 ////////////////////////////////////////////////////////////////////////////////
1047 /// Checks if default constructor exists and accessible
1048 
1049 bool ROOT::TMetaUtils::CheckDefaultConstructor(const clang::CXXRecordDecl* cl, const cling::Interpreter& interpreter)
1050 {
1051  clang::CXXRecordDecl* ncCl = const_cast<clang::CXXRecordDecl*>(cl);
1052 
1053  // We may induce template instantiation
1054  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interpreter));
1055 
1056  if (auto* Ctor = interpreter.getCI()->getSema().LookupDefaultConstructor(ncCl)) {
1057  if (Ctor->getAccess() == clang::AS_public && !Ctor->isDeleted()) {
1058  return true;
1059  }
1060  }
1061 
1062  return false;
1063 }
1064 
1065 
1066 ////////////////////////////////////////////////////////////////////////////////
1067 /// Checks IO constructor - must be public and with specified argument
1068 
1070  const char *typeOfArg,
1071  const clang::CXXRecordDecl *expectedArgType,
1072  const cling::Interpreter& interpreter)
1073 {
1074  if (typeOfArg && !expectedArgType) {
1075  const cling::LookupHelper& lh = interpreter.getLookupHelper();
1076  // We can not use findScope since the type we are given are usually,
1077  // only forward declared (and findScope explicitly reject them).
1078  clang::QualType instanceType = lh.findType(typeOfArg, cling::LookupHelper::WithDiagnostics);
1079  if (!instanceType.isNull())
1080  expectedArgType = instanceType->getAsCXXRecordDecl();
1081  }
1082 
1083  if (!expectedArgType)
1084  return EIOCtorCategory::kAbsent;
1085 
1086  // FIXME: We should not iterate here. That costs memory!
1087  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interpreter));
1088  for (auto iter = cl->ctor_begin(), end = cl->ctor_end(); iter != end; ++iter)
1089  {
1090  if ((iter->getAccess() != clang::AS_public) || (iter->getNumParams() != 1))
1091  continue;
1092 
1093  // We can reach this constructor.
1094  clang::QualType argType((*iter->param_begin())->getType());
1095  argType = argType.getDesugaredType(cl->getASTContext());
1096  // Deal with pointers and references: ROOT-7723
1097  auto ioCtorCategory = EIOCtorCategory::kAbsent;
1098  if (argType->isPointerType()) {
1099  ioCtorCategory = EIOCtorCategory::kIOPtrType;
1100  argType = argType->getPointeeType();
1101  } else if (argType->isReferenceType()) {
1102  ioCtorCategory = EIOCtorCategory::kIORefType;
1103  argType = argType.getNonReferenceType();
1104  } else
1105  continue;
1106 
1107  argType = argType.getDesugaredType(cl->getASTContext());
1108  const clang::CXXRecordDecl *argDecl = argType->getAsCXXRecordDecl();
1109  if (argDecl) {
1110  if (argDecl->getCanonicalDecl() == expectedArgType->getCanonicalDecl()) {
1111  return ioCtorCategory;
1112  }
1113  } else {
1114  std::string realArg = argType.getAsString();
1115  std::string clarg("class ");
1116  clarg += typeOfArg;
1117  if (realArg == clarg)
1118  return ioCtorCategory;
1119  }
1120  } // for each constructor
1121 
1122  return EIOCtorCategory::kAbsent;
1123 }
1124 
1125 
1126 ////////////////////////////////////////////////////////////////////////////////
1127 /// Check if class has constructor of provided type - either default or with single argument
1128 
1130  const RConstructorType &ioctortype,
1131  const cling::Interpreter& interpreter)
1132 {
1133  const char *arg = ioctortype.GetName();
1134 
1135  if (!ioctortype.GetType() && (!arg || !arg[0])) {
1136  // We are looking for a constructor with zero non-default arguments.
1137 
1138  return CheckDefaultConstructor(cl, interpreter) ? EIOCtorCategory::kDefault : EIOCtorCategory::kAbsent;
1139  }
1140 
1141  return CheckIOConstructor(cl, arg, ioctortype.GetType(), interpreter);
1142 }
1143 
1144 
1145 ////////////////////////////////////////////////////////////////////////////////
1146 
1147 const clang::CXXMethodDecl *GetMethodWithProto(const clang::Decl* cinfo,
1148  const char *method, const char *proto,
1149  const cling::Interpreter &interp,
1150  bool diagnose)
1151 {
1152  const clang::FunctionDecl* funcD
1153  = interp.getLookupHelper().findFunctionProto(cinfo, method, proto,
1154  diagnose ? cling::LookupHelper::WithDiagnostics
1155  : cling::LookupHelper::NoDiagnostics);
1156  if (funcD)
1157  return llvm::dyn_cast<const clang::CXXMethodDecl>(funcD);
1158 
1159  return nullptr;
1160 }
1161 
1162 
1163 ////////////////////////////////////////////////////////////////////////////////
1164 
1165 namespace ROOT {
1166  namespace TMetaUtils {
1167  RConstructorType::RConstructorType(const char *type_of_arg, const cling::Interpreter &interp) : fArgTypeName(type_of_arg),fArgType(nullptr)
1168  {
1169  const cling::LookupHelper& lh = interp.getLookupHelper();
1170  // We can not use findScope since the type we are given are usually,
1171  // only forward declared (and findScope explicitly reject them).
1172  clang::QualType instanceType = lh.findType(type_of_arg, cling::LookupHelper::WithDiagnostics);
1173  if (!instanceType.isNull())
1174  fArgType = instanceType->getAsCXXRecordDecl();
1175  }
1176  const char *RConstructorType::GetName() const { return fArgTypeName.c_str(); }
1177  const clang::CXXRecordDecl *RConstructorType::GetType() const { return fArgType; }
1178  }
1179 }
1180 
1181 ////////////////////////////////////////////////////////////////////////////////
1182 /// return true if we can find an constructor calleable without any arguments
1183 /// or with one the IOCtor special types.
1184 
1185 bool ROOT::TMetaUtils::HasIOConstructor(const clang::CXXRecordDecl *cl,
1186  std::string& arg,
1187  const RConstructorTypes& ctorTypes,
1188  const cling::Interpreter &interp)
1189 {
1190  if (cl->isAbstract()) return false;
1191 
1192  for (auto & ctorType : ctorTypes) {
1193 
1194  auto ioCtorCat = ROOT::TMetaUtils::CheckConstructor(cl, ctorType, interp);
1195 
1196  if (EIOCtorCategory::kAbsent == ioCtorCat)
1197  continue;
1198 
1199  std::string proto( ctorType.GetName() );
1200  bool defaultCtor = proto.empty();
1201  if (defaultCtor) {
1202  arg.clear();
1203  } else {
1204  // I/O constructors can take pointers or references to ctorTypes
1205  proto += " *";
1206  if (EIOCtorCategory::kIOPtrType == ioCtorCat) {
1207  arg = "( ("; //(MyType*)nullptr
1208  } else if (EIOCtorCategory::kIORefType == ioCtorCat) {
1209  arg = "( *("; //*(MyType*)nullptr
1210  }
1211  arg += proto;
1212  arg += ")nullptr )";
1213  }
1214  // Check for private operator new
1215  const clang::CXXMethodDecl *method
1216  = GetMethodWithProto(cl, "operator new", "size_t", interp,
1217  cling::LookupHelper::NoDiagnostics);
1218  if (method && method->getAccess() != clang::AS_public) {
1219  // The non-public op new is not going to improve for other c'tors.
1220  return false;
1221  }
1222 
1223  // This one looks good!
1224  return true;
1225  }
1226  return false;
1227 }
1228 
1229 ////////////////////////////////////////////////////////////////////////////////
1230 
1231 bool ROOT::TMetaUtils::NeedDestructor(const clang::CXXRecordDecl *cl,
1232  const cling::Interpreter& interp)
1233 {
1234  if (!cl) return false;
1235 
1236  if (cl->hasUserDeclaredDestructor()) {
1237 
1238  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interp));
1239  clang::CXXDestructorDecl *dest = cl->getDestructor();
1240  if (dest) {
1241  return (dest->getAccess() == clang::AS_public);
1242  } else {
1243  return true; // no destructor, so let's assume it means default?
1244  }
1245  }
1246  return true;
1247 }
1248 
1249 ////////////////////////////////////////////////////////////////////////////////
1250 /// Return true, if the function (defined by the name and prototype) exists and is public
1251 
1252 bool ROOT::TMetaUtils::CheckPublicFuncWithProto(const clang::CXXRecordDecl *cl,
1253  const char *methodname,
1254  const char *proto,
1255  const cling::Interpreter &interp,
1256  bool diagnose)
1257 {
1258  const clang::CXXMethodDecl *method
1259  = GetMethodWithProto(cl,methodname,proto, interp,
1260  diagnose ? cling::LookupHelper::WithDiagnostics
1261  : cling::LookupHelper::NoDiagnostics);
1262  return (method && method->getAccess() == clang::AS_public);
1263 }
1264 
1265 ////////////////////////////////////////////////////////////////////////////////
1266 /// Return true if the class has a method DirectoryAutoAdd(TDirectory *)
1267 
1268 bool ROOT::TMetaUtils::HasDirectoryAutoAdd(const clang::CXXRecordDecl *cl, const cling::Interpreter &interp)
1269 {
1270  // Detect if the class has a DirectoryAutoAdd
1271 
1272  // Detect if the class or one of its parent has a DirectoryAutoAdd
1273  const char *proto = "TDirectory*";
1274  const char *name = "DirectoryAutoAdd";
1275 
1276  return CheckPublicFuncWithProto(cl,name,proto,interp, false /*diags*/);
1277 }
1278 
1279 
1280 ////////////////////////////////////////////////////////////////////////////////
1281 /// Return true if the class has a method Merge(TCollection*,TFileMergeInfo*)
1282 
1283 bool ROOT::TMetaUtils::HasNewMerge(const clang::CXXRecordDecl *cl, const cling::Interpreter &interp)
1284 {
1285  // Detect if the class has a 'new' Merge function.
1286 
1287  // Detect if the class or one of its parent has a DirectoryAutoAdd
1288  const char *proto = "TCollection*,TFileMergeInfo*";
1289  const char *name = "Merge";
1290 
1291  return CheckPublicFuncWithProto(cl,name,proto,interp, false /*diags*/);
1292 }
1293 
1294 ////////////////////////////////////////////////////////////////////////////////
1295 /// Return true if the class has a method Merge(TCollection*)
1296 
1297 bool ROOT::TMetaUtils::HasOldMerge(const clang::CXXRecordDecl *cl, const cling::Interpreter &interp)
1298 {
1299  // Detect if the class has an old fashion Merge function.
1300 
1301  // Detect if the class or one of its parent has a DirectoryAutoAdd
1302  const char *proto = "TCollection*";
1303  const char *name = "Merge";
1304 
1305  return CheckPublicFuncWithProto(cl,name,proto, interp, false /*diags*/);
1306 }
1307 
1308 
1309 ////////////////////////////////////////////////////////////////////////////////
1310 /// Return true if the class has a method ResetAfterMerge(TFileMergeInfo *)
1311 
1312 bool ROOT::TMetaUtils::HasResetAfterMerge(const clang::CXXRecordDecl *cl, const cling::Interpreter &interp)
1313 {
1314  // Detect if the class has a 'new' Merge function.
1315  // bool hasMethod = cl.HasMethod("DirectoryAutoAdd");
1316 
1317  // Detect if the class or one of its parent has a DirectoryAutoAdd
1318  const char *proto = "TFileMergeInfo*";
1319  const char *name = "ResetAfterMerge";
1320 
1321  return CheckPublicFuncWithProto(cl,name,proto, interp, false /*diags*/);
1322 }
1323 
1324 
1325 ////////////////////////////////////////////////////////////////////////////////
1326 /// Return true if the class has a custom member function streamer.
1327 
1329  const clang::CXXRecordDecl* clxx,
1330  const cling::Interpreter &interp,
1331  const TNormalizedCtxt &normCtxt)
1332 {
1333  static const char *proto = "TBuffer&";
1334 
1335  const clang::CXXMethodDecl *method
1336  = GetMethodWithProto(clxx,"Streamer",proto, interp,
1337  cling::LookupHelper::NoDiagnostics);
1338  const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1339 
1340  return (method && method->getDeclContext() == clxx_as_context
1341  && ( cl.RequestNoStreamer() || !cl.RequestStreamerInfo()));
1342 }
1343 
1344 ////////////////////////////////////////////////////////////////////////////////
1345 /// Return true if the class has a custom member function streamer.
1346 
1348  const clang::CXXRecordDecl* clxx,
1349  const cling::Interpreter &interp,
1350  const TNormalizedCtxt &normCtxt)
1351 {
1352  static const char *proto = "TBuffer&,TClass*";
1353 
1354  const clang::CXXMethodDecl *method
1355  = GetMethodWithProto(clxx,"Streamer",proto, interp,
1356  cling::LookupHelper::NoDiagnostics);
1357  const clang::DeclContext *clxx_as_context = llvm::dyn_cast<clang::DeclContext>(clxx);
1358 
1359  return (method && method->getDeclContext() == clxx_as_context
1360  && ( cl.RequestNoStreamer() || !cl.RequestStreamerInfo()));
1361 }
1362 
1363 
1364 ////////////////////////////////////////////////////////////////////////////////
1365 /// Main implementation relying on GetFullyQualifiedTypeName
1366 /// All other GetQualifiedName functions leverage this one except the
1367 /// one for namespaces.
1368 
1369 void ROOT::TMetaUtils::GetQualifiedName(std::string &qual_name, const clang::QualType &type, const clang::NamedDecl &forcontext)
1370 {
1371  ROOT::TMetaUtils::GetFullyQualifiedTypeName(qual_name, type, forcontext.getASTContext());
1372 }
1373 
1374 //----
1375 std::string ROOT::TMetaUtils::GetQualifiedName(const clang::QualType &type, const clang::NamedDecl &forcontext)
1376 {
1377  std::string result;
1379  type,
1380  forcontext);
1381  return result;
1382 }
1383 
1384 
1385 ////////////////////////////////////////////////////////////////////////////////
1386 
1387 void ROOT::TMetaUtils::GetQualifiedName(std::string& qual_type, const clang::Type &type, const clang::NamedDecl &forcontext)
1388 {
1389  clang::QualType qualType(&type,0);
1391  qualType,
1392  forcontext);
1393 }
1394 
1395 //---
1396 std::string ROOT::TMetaUtils::GetQualifiedName(const clang::Type &type, const clang::NamedDecl &forcontext)
1397 {
1398  std::string result;
1400  type,
1401  forcontext);
1402  return result;
1403 }
1404 
1405 // //______________________________________________________________________________
1406 // void ROOT::TMetaUtils::GetQualifiedName(std::string &qual_name, const clang::NamespaceDecl &cl)
1407 // {
1408 // GetQualifiedName(qual_name,cl);
1409 // }
1410 //
1411 // //----
1412 // std::string ROOT::TMetaUtils::GetQualifiedName(const clang::NamespaceDecl &cl){
1413 // return GetQualifiedName(cl);
1414 // }
1415 
1416 ////////////////////////////////////////////////////////////////////////////////
1417 /// This implementation does not rely on GetFullyQualifiedTypeName
1418 
1419 void ROOT::TMetaUtils::GetQualifiedName(std::string &qual_name, const clang::NamedDecl &cl)
1420 {
1421  llvm::raw_string_ostream stream(qual_name);
1422  clang::PrintingPolicy policy( cl.getASTContext().getPrintingPolicy() );
1423  policy.SuppressTagKeyword = true; // Never get the class or struct keyword
1424  policy.SuppressUnwrittenScope = true; // Don't write the inline or anonymous namespace names.
1425 
1426  cl.getNameForDiagnostic(stream,policy,true);
1427  stream.flush(); // flush to string.
1428 
1429  if ( qual_name == "(anonymous " ) {
1430  size_t pos = qual_name.find(':');
1431  qual_name.erase(0,pos+2);
1432  }
1433 }
1434 
1435 //----
1436 std::string ROOT::TMetaUtils::GetQualifiedName(const clang::NamedDecl &cl){
1437  std::string result;
1439  return result;
1440 }
1441 
1442 
1443 ////////////////////////////////////////////////////////////////////////////////
1444 
1445 void ROOT::TMetaUtils::GetQualifiedName(std::string &qual_name, const clang::RecordDecl &recordDecl)
1446 {
1447  const clang::Type* declType ( recordDecl.getTypeForDecl() );
1448  clang::QualType qualType(declType,0);
1450  qualType,
1451  recordDecl);
1452 }
1453 
1454 //----
1455 std::string ROOT::TMetaUtils::GetQualifiedName(const clang::RecordDecl &recordDecl)
1456 {
1457  std::string result;
1458  ROOT::TMetaUtils::GetQualifiedName(result,recordDecl);
1459  return result;
1460 }
1461 
1462 ////////////////////////////////////////////////////////////////////////////////
1463 
1465 {
1466  ROOT::TMetaUtils::GetQualifiedName(qual_name, *annotated.GetRecordDecl());
1467 }
1468 
1469 //----
1471 {
1472  std::string result;
1473  ROOT::TMetaUtils::GetQualifiedName(result, annotated);
1474  return result;
1475 }
1476 
1477 ////////////////////////////////////////////////////////////////////////////////
1478 /// Create the data member name-type map for given class
1479 
1480 void ROOT::TMetaUtils::CreateNameTypeMap(const clang::CXXRecordDecl &cl, ROOT::MembersTypeMap_t& nameType)
1481 {
1482  std::stringstream dims;
1483  std::string typenameStr;
1484 
1485  const clang::ASTContext& astContext = cl.getASTContext();
1486 
1487  // Loop over the non static data member.
1488  for(clang::RecordDecl::field_iterator field_iter = cl.field_begin(), end = cl.field_end();
1489  field_iter != end;
1490  ++field_iter){
1491  // The CINT based code was filtering away static variables (they are not part of
1492  // the list starting with field_begin in clang), and const enums (which should
1493  // also not be part of this list).
1494  // It was also filtering out the 'G__virtualinfo' artificial member.
1495 
1496  typenameStr.clear();
1497  dims.str("");
1498  dims.clear();
1499 
1500  clang::QualType fieldType(field_iter->getType());
1501  if (fieldType->isConstantArrayType()) {
1502  const clang::ConstantArrayType *arrayType = llvm::dyn_cast<clang::ConstantArrayType>(fieldType.getTypePtr());
1503  while (arrayType) {
1504  dims << "[" << arrayType->getSize().getLimitedValue() << "]";
1505  fieldType = arrayType->getElementType();
1506  arrayType = llvm::dyn_cast<clang::ConstantArrayType>(arrayType->getArrayElementTypeNoTypeQual());
1507  }
1508  }
1509 
1510  GetFullyQualifiedTypeName(typenameStr, fieldType, astContext);
1511  nameType[field_iter->getName().str()] = ROOT::Internal::TSchemaType(typenameStr.c_str(),dims.str().c_str());
1512  }
1513 
1514  // And now the base classes
1515  // We also need to look at the base classes.
1516  for(clang::CXXRecordDecl::base_class_const_iterator iter = cl.bases_begin(), end = cl.bases_end();
1517  iter != end;
1518  ++iter){
1519  std::string basename( iter->getType()->getAsCXXRecordDecl()->getNameAsString() ); // Intentionally using only the unqualified name.
1520  nameType[basename] = ROOT::Internal::TSchemaType(basename.c_str(),"");
1521  }
1522 }
1523 
1524 ////////////////////////////////////////////////////////////////////////////////
1525 
1526 const clang::FunctionDecl *ROOT::TMetaUtils::GetFuncWithProto(const clang::Decl* cinfo,
1527  const char *method,
1528  const char *proto,
1529  const cling::Interpreter &interp,
1530  bool diagnose)
1531 {
1532  return interp.getLookupHelper().findFunctionProto(cinfo, method, proto,
1533  diagnose ? cling::LookupHelper::WithDiagnostics
1534  : cling::LookupHelper::NoDiagnostics);
1535 }
1536 
1537 ////////////////////////////////////////////////////////////////////////////////
1538 /// It looks like the template specialization decl actually contains _less_ information
1539 /// on the location of the code than the decl (in case where there is forward declaration,
1540 /// that is what the specialization points to.
1541 ///
1542 /// const clang::CXXRecordDecl* clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
1543 /// if (clxx) {
1544 /// switch(clxx->getTemplateSpecializationKind()) {
1545 /// case clang::TSK_Undeclared:
1546 /// // We want the default behavior
1547 /// break;
1548 /// case clang::TSK_ExplicitInstantiationDeclaration:
1549 /// case clang::TSK_ExplicitInstantiationDefinition:
1550 /// case clang::TSK_ImplicitInstantiation: {
1551 /// // We want the location of the template declaration:
1552 /// const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
1553 /// if (tmplt_specialization) {
1554 /// return GetLineNumber(const_cast< clang::ClassTemplateSpecializationDecl *>(tmplt_specialization)->getSpecializedTemplate());
1555 /// }
1556 /// break;
1557 /// }
1558 /// case clang::TSK_ExplicitSpecialization:
1559 /// // We want the default behavior
1560 /// break;
1561 /// default:
1562 /// break;
1563 /// }
1564 /// }
1565 
1566 long ROOT::TMetaUtils::GetLineNumber(const clang::Decl *decl)
1567 {
1568  clang::SourceLocation sourceLocation = decl->getLocation();
1569  clang::SourceManager& sourceManager = decl->getASTContext().getSourceManager();
1570 
1571  if (!sourceLocation.isValid() ) {
1572  return -1;
1573  }
1574 
1575  if (!sourceLocation.isFileID()) {
1576  sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
1577  }
1578 
1579  if (sourceLocation.isValid() && sourceLocation.isFileID()) {
1580  return sourceManager.getLineNumber(sourceManager.getFileID(sourceLocation),sourceManager.getFileOffset(sourceLocation));
1581  }
1582  else {
1583  return -1;
1584  }
1585 }
1586 
1587 ////////////////////////////////////////////////////////////////////////////////
1588 /// Return true if the type is a Double32_t or Float16_t or
1589 /// is a instance template that depends on Double32_t or Float16_t.
1590 
1591 bool ROOT::TMetaUtils::hasOpaqueTypedef(clang::QualType instanceType, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
1592 {
1593  while (llvm::isa<clang::PointerType>(instanceType.getTypePtr())
1594  || llvm::isa<clang::ReferenceType>(instanceType.getTypePtr()))
1595  {
1596  instanceType = instanceType->getPointeeType();
1597  }
1598 
1599  const clang::ElaboratedType* etype
1600  = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
1601  if (etype) {
1602  instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
1603  }
1604 
1605  // There is no typedef to worried about, except for the opaque ones.
1606 
1607  // Technically we should probably used our own list with just
1608  // Double32_t and Float16_t
1609  if (normCtxt.GetTypeWithAlternative().count(instanceType.getTypePtr())) {
1610  return true;
1611  }
1612 
1613 
1614  bool result = false;
1615  const clang::CXXRecordDecl* clxx = instanceType->getAsCXXRecordDecl();
1616  if (clxx && clxx->getTemplateSpecializationKind() != clang::TSK_Undeclared) {
1617  // do the template thing.
1618  const clang::TemplateSpecializationType* TST
1619  = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
1620  if (TST==0) {
1621  // std::string type_name;
1622  // type_name = GetQualifiedName( instanceType, *clxx );
1623  // fprintf(stderr,"ERROR: Could not findS TST for %s\n",type_name.c_str());
1624  return false;
1625  }
1626  for(clang::TemplateSpecializationType::iterator
1627  I = TST->begin(), E = TST->end();
1628  I!=E; ++I)
1629  {
1630  if (I->getKind() == clang::TemplateArgument::Type) {
1631  // std::string arg;
1632  // arg = GetQualifiedName( I->getAsType(), *clxx );
1633  // fprintf(stderr,"DEBUG: looking at %s\n", arg.c_str());
1634  result |= ROOT::TMetaUtils::hasOpaqueTypedef(I->getAsType(), normCtxt);
1635  }
1636  }
1637  }
1638  return result;
1639 }
1640 
1641 ////////////////////////////////////////////////////////////////////////////////
1642 /// Return true if any of the argument is or contains a double32.
1643 
1645  const cling::Interpreter &interp,
1646  const TNormalizedCtxt &normCtxt)
1647 {
1648  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
1649  if (!clxx || clxx->getTemplateSpecializationKind() == clang::TSK_Undeclared) return false;
1650 
1651  clang::QualType instanceType = interp.getLookupHelper().findType(cl.GetNormalizedName(),
1652  cling::LookupHelper::WithDiagnostics);
1653  if (instanceType.isNull()) {
1654  //Error(0,"Could not find the clang::Type for %s\n",cl.GetNormalizedName());
1655  return false;
1656  }
1657 
1658  return ROOT::TMetaUtils::hasOpaqueTypedef(instanceType, normCtxt);
1659 }
1660 
1661 ////////////////////////////////////////////////////////////////////////////////
1662 /// Extract attr string
1663 
1664 int ROOT::TMetaUtils::extractAttrString(clang::Attr* attribute, std::string& attrString)
1665 {
1666  clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(attribute);
1667  if (!annAttr) {
1668  //TMetaUtils::Error(0,"Could not cast Attribute to AnnotatedAttribute\n");
1669  return 1;
1670  }
1671  attrString = annAttr->getAnnotation();
1672  return 0;
1673 }
1674 
1675 ////////////////////////////////////////////////////////////////////////////////
1676 
1677 int ROOT::TMetaUtils::extractPropertyNameValFromString(const std::string attributeStr,std::string& attrName, std::string& attrValue)
1678 {
1679  // if separator found, extract name and value
1680  size_t substrFound (attributeStr.find(propNames::separator));
1681  if (substrFound==std::string::npos) {
1682  //TMetaUtils::Error(0,"Could not find property name-value separator (%s)\n",ROOT::TMetaUtils::PropertyNameValSeparator.c_str());
1683  return 1;
1684  }
1685  size_t EndPart1 = attributeStr.find_first_of(propNames::separator) ;
1686  attrName = attributeStr.substr(0, EndPart1);
1687  const int separatorLength(propNames::separator.size());
1688  attrValue = attributeStr.substr(EndPart1 + separatorLength);
1689  return 0;
1690 }
1691 
1692 ////////////////////////////////////////////////////////////////////////////////
1693 
1694 int ROOT::TMetaUtils::extractPropertyNameVal(clang::Attr* attribute, std::string& attrName, std::string& attrValue)
1695 {
1696  std::string attrString;
1697  int ret = extractAttrString(attribute, attrString);
1698  if (0!=ret) return ret;
1699  return extractPropertyNameValFromString(attrString, attrName,attrValue);
1700 }
1701 
1702 ////////////////////////////////////////////////////////////////////////////////
1703 /// This routine counts on the "propName<separator>propValue" format
1704 
1706  const std::string& propName,
1707  std::string& propValue)
1708 {
1709  for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1710  attrIt!=decl.attr_end();++attrIt){
1711  clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1712  if (!annAttr) continue;
1713 
1714  llvm::StringRef attribute = annAttr->getAnnotation();
1715  std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1716  if (split.first != propName.c_str()) continue;
1717  else {
1718  propValue = split.second;
1719  return true;
1720  }
1721  }
1722  return false;
1723 }
1724 
1725 ////////////////////////////////////////////////////////////////////////////////
1726 /// This routine counts on the "propName<separator>propValue" format
1727 
1729  const std::string& propName,
1730  int& propValue)
1731 {
1732  for (clang::Decl::attr_iterator attrIt = decl.attr_begin();
1733  attrIt!=decl.attr_end();++attrIt){
1734  clang::AnnotateAttr* annAttr = clang::dyn_cast<clang::AnnotateAttr>(*attrIt);
1735  if (!annAttr) continue;
1736 
1737  llvm::StringRef attribute = annAttr->getAnnotation();
1738  std::pair<llvm::StringRef,llvm::StringRef> split = attribute.split(propNames::separator.c_str());
1739  if (split.first != propName.c_str()) continue;
1740  else {
1741  return split.second.getAsInteger(10,propValue);
1742  }
1743  }
1744  return false;
1745 }
1746 
1747 ////////////////////////////////////////////////////////////////////////////////
1748 /// FIXME: a function of 450+ lines!
1749 
1750 void ROOT::TMetaUtils::WriteClassInit(std::ostream& finalString,
1751  const AnnotatedRecordDecl &cl,
1752  const clang::CXXRecordDecl *decl,
1753  const cling::Interpreter &interp,
1754  const TNormalizedCtxt &normCtxt,
1755  const RConstructorTypes& ctorTypes,
1756  bool& needCollectionProxy)
1757 {
1758  std::string classname = TClassEdit::GetLong64_Name(cl.GetNormalizedName());
1759 
1760  std::string mappedname;
1761  ROOT::TMetaUtils::GetCppName(mappedname,classname.c_str());
1762  std::string csymbol = classname;
1763  std::string args;
1764 
1765  if ( ! TClassEdit::IsStdClass( classname.c_str() ) ) {
1766 
1767  // Prefix the full class name with '::' except for the STL
1768  // containers and std::string. This is to request the
1769  // real class instead of the class in the namespace ROOT::Shadow
1770  csymbol.insert(0,"::");
1771  }
1772 
1773  int stl = TClassEdit::IsSTLCont(classname);
1774  bool bset = TClassEdit::IsSTLBitset(classname.c_str());
1775 
1776  bool isStd = TMetaUtils::IsStdClass(*decl);
1777  const cling::LookupHelper& lh = interp.getLookupHelper();
1778  bool isString = TMetaUtils::IsOfType(*decl,"std::string",lh);
1779 
1780  bool isStdNotString = isStd && !isString;
1781 
1782  finalString << "namespace ROOT {" << "\n";
1783 
1784  if (!ClassInfo__HasMethod(decl,"Dictionary",interp) || IsTemplate(*decl))
1785  {
1786  finalString << " static TClass *" << mappedname.c_str() << "_Dictionary();\n"
1787  << " static void " << mappedname.c_str() << "_TClassManip(TClass*);\n";
1788 
1789 
1790  }
1791 
1792  if (HasIOConstructor(decl, args, ctorTypes, interp)) {
1793  finalString << " static void *new_" << mappedname.c_str() << "(void *p = nullptr);" << "\n";
1794 
1795  if (args.size()==0 && NeedDestructor(decl, interp))
1796  {
1797  finalString << " static void *newArray_";
1798  finalString << mappedname.c_str();
1799  finalString << "(Long_t size, void *p);";
1800  finalString << "\n";
1801  }
1802  }
1803 
1804  if (NeedDestructor(decl, interp)) {
1805  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";
1806  }
1807  if (HasDirectoryAutoAdd(decl, interp)) {
1808  finalString << " static void directoryAutoAdd_" << mappedname.c_str() << "(void *obj, TDirectory *dir);" << "\n";
1809  }
1810  if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) {
1811  finalString << " static void streamer_" << mappedname.c_str() << "(TBuffer &buf, void *obj);" << "\n";
1812  }
1813  if (HasCustomConvStreamerMemberFunction(cl, decl, interp, normCtxt)) {
1814  finalString << " static void conv_streamer_" << mappedname.c_str() << "(TBuffer &buf, void *obj, const TClass*);" << "\n";
1815  }
1816  if (HasNewMerge(decl, interp) || HasOldMerge(decl, interp)) {
1817  finalString << " static Long64_t merge_" << mappedname.c_str() << "(void *obj, TCollection *coll,TFileMergeInfo *info);" << "\n";
1818  }
1819  if (HasResetAfterMerge(decl, interp)) {
1820  finalString << " static void reset_" << mappedname.c_str() << "(void *obj, TFileMergeInfo *info);" << "\n";
1821  }
1822 
1823  //--------------------------------------------------------------------------
1824  // Check if we have any schema evolution rules for this class
1825  /////////////////////////////////////////////////////////////////////////////
1826 
1827  ROOT::SchemaRuleClassMap_t::iterator rulesIt1 = ROOT::gReadRules.find( classname.c_str() );
1828  ROOT::SchemaRuleClassMap_t::iterator rulesIt2 = ROOT::gReadRawRules.find( classname.c_str() );
1829 
1830  ROOT::MembersTypeMap_t nameTypeMap;
1831  CreateNameTypeMap( *decl, nameTypeMap ); // here types for schema evo are written
1832 
1833  //--------------------------------------------------------------------------
1834  // Process the read rules
1835  /////////////////////////////////////////////////////////////////////////////
1836 
1837  if( rulesIt1 != ROOT::gReadRules.end() ) {
1838  int i = 0;
1839  finalString << "\n // Schema evolution read functions\n";
1840  std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt1->second.begin();
1841  while( rIt != rulesIt1->second.end() ) {
1842 
1843  //--------------------------------------------------------------------
1844  // Check if the rules refer to valid data members
1845  ///////////////////////////////////////////////////////////////////////
1846 
1847  std::string error_string;
1848  if( !HasValidDataMembers( *rIt, nameTypeMap, error_string ) ) {
1849  Warning(0, "%s", error_string.c_str());
1850  rIt = rulesIt1->second.erase(rIt);
1851  continue;
1852  }
1853 
1854  //---------------------------------------------------------------------
1855  // Write the conversion function if necessary
1856  ///////////////////////////////////////////////////////////////////////
1857 
1858  if( rIt->find( "code" ) != rIt->end() ) {
1859  WriteReadRuleFunc( *rIt, i++, mappedname, nameTypeMap, finalString );
1860  }
1861  ++rIt;
1862  }
1863  }
1864 
1865 
1866 
1867 
1868  //--------------------------------------------------------------------------
1869  // Process the read raw rules
1870  /////////////////////////////////////////////////////////////////////////////
1871 
1872  if( rulesIt2 != ROOT::gReadRawRules.end() ) {
1873  int i = 0;
1874  finalString << "\n // Schema evolution read raw functions\n";
1875  std::list<ROOT::SchemaRuleMap_t>::iterator rIt = rulesIt2->second.begin();
1876  while( rIt != rulesIt2->second.end() ) {
1877 
1878  //--------------------------------------------------------------------
1879  // Check if the rules refer to valid data members
1880  ///////////////////////////////////////////////////////////////////////
1881 
1882  std::string error_string;
1883  if( !HasValidDataMembers( *rIt, nameTypeMap, error_string ) ) {
1884  Warning(0, "%s", error_string.c_str());
1885  rIt = rulesIt2->second.erase(rIt);
1886  continue;
1887  }
1888 
1889  //---------------------------------------------------------------------
1890  // Write the conversion function
1891  ///////////////////////////////////////////////////////////////////////
1892 
1893  if( rIt->find( "code" ) == rIt->end() )
1894  continue;
1895 
1896  WriteReadRawRuleFunc( *rIt, i++, mappedname, nameTypeMap, finalString );
1897  ++rIt;
1898  }
1899  }
1900 
1901  finalString << "\n" << " // Function generating the singleton type initializer" << "\n";
1902 
1903  finalString << " static TGenericClassInfo *GenerateInitInstanceLocal(const " << csymbol << "*)" << "\n" << " {" << "\n";
1904 
1905  finalString << " " << csymbol << " *ptr = nullptr;" << "\n";
1906 
1907  //fprintf(fp, " static ::ROOT::ClassInfo< %s > \n",classname.c_str());
1908  if (ClassInfo__HasMethod(decl,"IsA",interp) ) {
1909  finalString << " static ::TVirtualIsAProxy* isa_proxy = new ::TInstrumentedIsAProxy< " << csymbol << " >(nullptr);" << "\n";
1910  }
1911  else {
1912  finalString << " static ::TVirtualIsAProxy* isa_proxy = new ::TIsAProxy(typeid(" << csymbol << "));" << "\n";
1913  }
1914  finalString << " static ::ROOT::TGenericClassInfo " << "\n" << " instance(\"" << classname.c_str() << "\", ";
1915 
1916  if (ClassInfo__HasMethod(decl,"Class_Version",interp)) {
1917  finalString << csymbol << "::Class_Version(), ";
1918  } else if (bset) {
1919  finalString << "2, "; // bitset 'version number'
1920  } else if (stl) {
1921  finalString << "-2, "; // "::TStreamerInfo::Class_Version(), ";
1922  } else if( cl.HasClassVersion() ) {
1923  finalString << cl.RequestedVersionNumber() << ", ";
1924  } else { // if (cl_input.RequestStreamerInfo()) {
1925 
1926  // Need to find out if the operator>> is actually defined for this class.
1927  static const char *versionFunc = "GetClassVersion";
1928  // int ncha = strlen(classname.c_str())+strlen(versionFunc)+5;
1929  // char *funcname= new char[ncha];
1930  // snprintf(funcname,ncha,"%s<%s >",versionFunc,classname.c_str());
1931  std::string proto = classname + "*";
1932  const clang::Decl* ctxt = llvm::dyn_cast<clang::Decl>((*cl).getDeclContext());
1933  const clang::FunctionDecl *methodinfo
1934  = ROOT::TMetaUtils::GetFuncWithProto(ctxt, versionFunc, proto.c_str(),
1935  interp, cling::LookupHelper::NoDiagnostics);
1936  // delete [] funcname;
1937 
1938  if (methodinfo &&
1939  ROOT::TMetaUtils::GetFileName(*methodinfo, interp).find("Rtypes.h") == llvm::StringRef::npos) {
1940 
1941  // GetClassVersion was defined in the header file.
1942  //fprintf(fp, "GetClassVersion((%s *)0x0), ",classname.c_str());
1943  finalString << "GetClassVersion< ";
1944  finalString << classname.c_str();
1945  finalString << " >(), ";
1946  }
1947  //static char temporary[1024];
1948  //sprintf(temporary,"GetClassVersion<%s>( (%s *) 0x0 )",classname.c_str(),classname.c_str());
1949  //fprintf(stderr,"DEBUG: %s has value %d\n",classname.c_str(),(int)G__int(G__calc(temporary)));
1950  }
1951 
1952  std::string filename = ROOT::TMetaUtils::GetFileName(*cl, interp);
1953  if (filename.length() > 0) {
1954  for (unsigned int i=0; i<filename.length(); i++) {
1955  if (filename[i]=='\\') filename[i]='/';
1956  }
1957  }
1958  finalString << "\"" << filename << "\", " << ROOT::TMetaUtils::GetLineNumber(cl)
1959  << "," << "\n" << " typeid(" << csymbol
1960  << "), ::ROOT::Internal::DefineBehavior(ptr, ptr)," << "\n" << " ";
1961 
1962  if (ClassInfo__HasMethod(decl,"Dictionary",interp) && !IsTemplate(*decl)) {
1963  finalString << "&" << csymbol << "::Dictionary, ";
1964  } else {
1965  finalString << "&" << mappedname << "_Dictionary, ";
1966  }
1967 
1968  enum {
1969  TClassTable__kHasCustomStreamerMember = 0x10 // See TClassTable.h
1970  };
1971 
1972  Int_t rootflag = cl.RootFlag();
1973  if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) {
1974  rootflag = rootflag | TClassTable__kHasCustomStreamerMember;
1975  }
1976  finalString << "isa_proxy, " << rootflag << "," << "\n" << " sizeof(" << csymbol << ") );" << "\n";
1977  if (HasIOConstructor(decl, args, ctorTypes, interp)) {
1978  finalString << " instance.SetNew(&new_" << mappedname.c_str() << ");" << "\n";
1979  if (args.size()==0 && NeedDestructor(decl, interp))
1980  finalString << " instance.SetNewArray(&newArray_" << mappedname.c_str() << ");" << "\n";
1981  }
1982  if (NeedDestructor(decl, interp)) {
1983  finalString << " instance.SetDelete(&delete_" << mappedname.c_str() << ");" << "\n" << " instance.SetDeleteArray(&deleteArray_" << mappedname.c_str() << ");" << "\n" << " instance.SetDestructor(&destruct_" << mappedname.c_str() << ");" << "\n";
1984  }
1985  if (HasDirectoryAutoAdd(decl, interp)) {
1986  finalString << " instance.SetDirectoryAutoAdd(&directoryAutoAdd_" << mappedname.c_str() << ");" << "\n";
1987  }
1988  if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) {
1989  // We have a custom member function streamer or an older (not StreamerInfo based) automatic streamer.
1990  finalString << " instance.SetStreamerFunc(&streamer_" << mappedname.c_str() << ");" << "\n";
1991  }
1992  if (HasCustomConvStreamerMemberFunction(cl, decl, interp, normCtxt)) {
1993  // We have a custom member function streamer or an older (not StreamerInfo based) automatic streamer.
1994  finalString << " instance.SetConvStreamerFunc(&conv_streamer_" << mappedname.c_str() << ");" << "\n";
1995  }
1996  if (HasNewMerge(decl, interp) || HasOldMerge(decl, interp)) {
1997  finalString << " instance.SetMerge(&merge_" << mappedname.c_str() << ");" << "\n";
1998  }
1999  if (HasResetAfterMerge(decl, interp)) {
2000  finalString << " instance.SetResetAfterMerge(&reset_" << mappedname.c_str() << ");" << "\n";
2001  }
2002  if (bset) {
2003  finalString << " instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << "Pushback" << "<Internal::TStdBitsetHelper< " << classname.c_str() << " > >()));" << "\n";
2004 
2005  needCollectionProxy = true;
2006  } else if (stl != 0 &&
2007  ((stl > 0 && stl<ROOT::kSTLend) || (stl < 0 && stl>-ROOT::kSTLend)) && // is an stl container
2008  (stl != ROOT::kSTLbitset && stl !=-ROOT::kSTLbitset) ){ // is no bitset
2009  int idx = classname.find("<");
2010  int stlType = (idx!=(int)std::string::npos) ? TClassEdit::STLKind(classname.substr(0,idx)) : 0;
2011  const char* methodTCP=0;
2012  switch(stlType) {
2013  case ROOT::kSTLvector:
2014  case ROOT::kSTLlist:
2015  case ROOT::kSTLdeque:
2016  case ROOT::kROOTRVec:
2017  methodTCP="Pushback";
2018  break;
2019  case ROOT::kSTLforwardlist:
2020  methodTCP="Pushfront";
2021  break;
2022  case ROOT::kSTLmap:
2023  case ROOT::kSTLmultimap:
2026  methodTCP="MapInsert";
2027  break;
2028  case ROOT::kSTLset:
2029  case ROOT::kSTLmultiset:
2032  methodTCP="Insert";
2033  break;
2034  }
2035  // FIXME Workaround: for the moment we do not generate coll proxies with unique ptrs since
2036  // they imply copies and therefore do not compile.
2037  auto classNameForIO = TClassEdit::GetNameForIO(classname);
2038  finalString << " instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP << "< " << classNameForIO.c_str() << " >()));" << "\n";
2039 
2040  needCollectionProxy = true;
2041  }
2042 
2043  //---------------------------------------------------------------------------
2044  // Register Alternate spelling of the class name.
2045  /////////////////////////////////////////////////////////////////////////////
2046 
2047  if (cl.GetRequestedName()[0] && classname != cl.GetRequestedName()) {
2048  finalString << "\n" << " ::ROOT::AddClassAlternate(\""
2049  << classname << "\",\"" << cl.GetRequestedName() << "\");\n";
2050  }
2051 
2052  if (!cl.GetDemangledTypeInfo().empty()
2053  && cl.GetDemangledTypeInfo() != classname
2054  && cl.GetDemangledTypeInfo() != cl.GetRequestedName()) {
2055  finalString << "\n" << " ::ROOT::AddClassAlternate(\""
2056  << classname << "\",\"" << cl.GetDemangledTypeInfo() << "\");\n";
2057 
2058  }
2059 
2060  //---------------------------------------------------------------------------
2061  // Pass the schema evolution rules to TGenericClassInfo
2062  /////////////////////////////////////////////////////////////////////////////
2063 
2064  if( (rulesIt1 != ROOT::gReadRules.end() && rulesIt1->second.size()>0) || (rulesIt2 != ROOT::gReadRawRules.end() && rulesIt2->second.size()>0) ) {
2065  finalString << "\n" << " ::ROOT::Internal::TSchemaHelper* rule;" << "\n";
2066  }
2067 
2068  if( rulesIt1 != ROOT::gReadRules.end() ) {
2069  finalString << "\n" << " // the io read rules" << "\n" << " std::vector<::ROOT::Internal::TSchemaHelper> readrules(" << rulesIt1->second.size() << ");" << "\n";
2070  ROOT::WriteSchemaList( rulesIt1->second, "readrules", finalString );
2071  finalString << " instance.SetReadRules( readrules );" << "\n";
2072  }
2073 
2074  if( rulesIt2 != ROOT::gReadRawRules.end() ) {
2075  finalString << "\n" << " // the io read raw rules" << "\n" << " std::vector<::ROOT::Internal::TSchemaHelper> readrawrules(" << rulesIt2->second.size() << ");" << "\n";
2076  ROOT::WriteSchemaList( rulesIt2->second, "readrawrules", finalString );
2077  finalString << " instance.SetReadRawRules( readrawrules );" << "\n";
2078  }
2079 
2080  finalString << " return &instance;" << "\n" << " }" << "\n";
2081 
2082  if (!isStdNotString && !ROOT::TMetaUtils::hasOpaqueTypedef(cl, interp, normCtxt)) {
2083  // The GenerateInitInstance for STL are not unique and should not be externally accessible
2084  finalString << " TGenericClassInfo *GenerateInitInstance(const " << csymbol << "*)" << "\n" << " {\n return GenerateInitInstanceLocal((" << csymbol << "*)nullptr);\n }" << "\n";
2085  }
2086 
2087  finalString << " // Static variable to force the class initialization" << "\n";
2088  // must be one long line otherwise UseDummy does not work
2089 
2090 
2091  finalString << " static ::ROOT::TGenericClassInfo *_R__UNIQUE_DICT_(Init) = GenerateInitInstanceLocal((const " << csymbol << "*)nullptr); R__UseDummy(_R__UNIQUE_DICT_(Init));" << "\n";
2092 
2093  if (!ClassInfo__HasMethod(decl,"Dictionary",interp) || IsTemplate(*decl)) {
2094  finalString << "\n" << " // Dictionary for non-ClassDef classes" << "\n"
2095  << " static TClass *" << mappedname << "_Dictionary() {\n"
2096  << " TClass* theClass ="
2097  << "::ROOT::GenerateInitInstanceLocal((const " << csymbol << "*)nullptr)->GetClass();\n"
2098  << " " << mappedname << "_TClassManip(theClass);\n";
2099  finalString << " return theClass;\n";
2100  finalString << " }\n\n";
2101 
2102  // Now manipulate tclass in order to percolate the properties expressed as
2103  // annotations of the decls.
2104  std::string manipString;
2105  std::string attribute_s;
2106  std::string attrName, attrValue;
2107  // Class properties
2108  bool attrMapExtracted = false;
2109  if (decl->hasAttrs()){
2110  // Loop on the attributes
2111  for (clang::Decl::attr_iterator attrIt = decl->attr_begin();
2112  attrIt!=decl->attr_end();++attrIt){
2113  if ( 0!=ROOT::TMetaUtils::extractAttrString(*attrIt,attribute_s)){
2114  continue;
2115  }
2116  if (0!=ROOT::TMetaUtils::extractPropertyNameValFromString(attribute_s, attrName, attrValue)){
2117  continue;
2118  }
2119  if (attrName == "name" ||
2120  attrName == "pattern" ||
2121  attrName == "rootmap") continue;
2122  // A general property
2123  // 1) We need to create the property map (in the gen code)
2124  // 2) we need to take out the map (in the gen code)
2125  // 3) We need to bookkep the fact that the map is created and out (in this source)
2126  // 4) We fill the map (in the gen code)
2127  if (!attrMapExtracted){
2128  manipString+=" theClass->CreateAttributeMap();\n";
2129  manipString+=" TDictAttributeMap* attrMap( theClass->GetAttributeMap() );\n";
2130  attrMapExtracted=true;
2131  }
2132  manipString+=" attrMap->AddProperty(\""+attrName +"\",\""+attrValue+"\");\n";
2133  }
2134  } // end of class has properties
2135 
2136  // Member properties
2137  // Loop on declarations inside the class, including data members
2138  for(clang::CXXRecordDecl::decl_iterator internalDeclIt = decl->decls_begin();
2139  internalDeclIt != decl->decls_end(); ++internalDeclIt){
2140  if (!(!(*internalDeclIt)->isImplicit()
2141  && (clang::isa<clang::FieldDecl>(*internalDeclIt) ||
2142  clang::isa<clang::VarDecl>(*internalDeclIt)))) continue; // Check if it's a var or a field
2143 
2144  // Now let's check the attributes of the var/field
2145  if (!internalDeclIt->hasAttrs()) continue;
2146 
2147  attrMapExtracted = false;
2148  bool memberPtrCreated = false;
2149 
2150  for (clang::Decl::attr_iterator attrIt = internalDeclIt->attr_begin();
2151  attrIt!=internalDeclIt->attr_end();++attrIt){
2152 
2153  // Get the attribute as string
2154  if ( 0!=ROOT::TMetaUtils::extractAttrString(*attrIt,attribute_s)){
2155  continue;
2156  }
2157 
2158  // Check the name of the decl
2159  clang::NamedDecl* namedInternalDecl = clang::dyn_cast<clang::NamedDecl> (*internalDeclIt);
2160  if (!namedInternalDecl) {
2161  TMetaUtils::Error(0,"Cannot convert field declaration to clang::NamedDecl");
2162  continue;
2163  };
2164  const std::string memberName(namedInternalDecl->getName());
2165  const std::string cppMemberName="theMember_"+memberName;
2166 
2167  // Prepare a string to get the data member, it can be used later.
2168  const std::string dataMemberCreation= " TDataMember* "+cppMemberName+" = theClass->GetDataMember(\""+memberName+"\");\n";
2169 
2170  // Let's now attack regular properties
2171 
2172  if (0!=ROOT::TMetaUtils::extractPropertyNameValFromString(attribute_s, attrName, attrValue)){
2173  continue;
2174  }
2175 
2176  // Skip these
2177  if (attrName == propNames::comment ||
2178  attrName == propNames::iotype ||
2179  attrName == propNames::ioname ) continue;
2180 
2181  if (!memberPtrCreated){
2182  manipString+=dataMemberCreation;
2183  memberPtrCreated=true;
2184  }
2185 
2186  if (!attrMapExtracted){
2187  manipString+=" "+cppMemberName+"->CreateAttributeMap();\n";
2188  manipString+=" TDictAttributeMap* memberAttrMap_"+memberName+"( theMember_"+memberName+"->GetAttributeMap() );\n";
2189  attrMapExtracted=true;
2190  }
2191 
2192  manipString+=" memberAttrMap_"+memberName+"->AddProperty(\""+attrName +"\",\""+attrValue+"\");\n";
2193 
2194 
2195  } // End loop on attributes
2196  } // End loop on internal declarations
2197 
2198 
2199  finalString << " static void " << mappedname << "_TClassManip(TClass* " << (manipString.empty() ? "":"theClass") << "){\n"
2200  << manipString
2201  << " }\n\n";
2202  } // End of !ClassInfo__HasMethod(decl,"Dictionary") || IsTemplate(*decl))
2203 
2204  finalString << "} // end of namespace ROOT" << "\n" << "\n";
2205 }
2206 
2207 ////////////////////////////////////////////////////////////////////////////////
2208 /// Return true if one of the class' enclosing scope is a namespace and
2209 /// set fullname to the fully qualified name,
2210 /// clsname to the name within a namespace
2211 /// and nsname to the namespace fully qualified name.
2212 
2213 bool ROOT::TMetaUtils::GetNameWithinNamespace(std::string &fullname,
2214  std::string &clsname,
2215  std::string &nsname,
2216  const clang::CXXRecordDecl *cl)
2217 {
2218  fullname.clear();
2219  nsname.clear();
2220 
2221  ROOT::TMetaUtils::GetQualifiedName(fullname,*cl);
2222  clsname = fullname;
2223 
2224  // Inline namespace are stripped from the normalized name, we need to
2225  // strip it from the prefix we want to remove.
2226  auto ctxt = cl->getEnclosingNamespaceContext();
2227  while(ctxt && ctxt!=cl && ctxt->isInlineNamespace()) {
2228  ctxt = ctxt->getParent();
2229  }
2230  if (ctxt) {
2231  const clang::NamedDecl *namedCtxt = llvm::dyn_cast<clang::NamedDecl>(ctxt);
2232  if (namedCtxt && namedCtxt!=cl) {
2233  const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(namedCtxt);
2234  if (nsdecl != 0 && !nsdecl->isAnonymousNamespace()) {
2235  ROOT::TMetaUtils::GetQualifiedName(nsname,*nsdecl);
2236  clsname.erase (0, nsname.size() + 2);
2237  return true;
2238  }
2239  }
2240  }
2241  return false;
2242 }
2243 
2244 ////////////////////////////////////////////////////////////////////////////////
2245 
2246 const clang::DeclContext *GetEnclosingSpace(const clang::RecordDecl &cl)
2247 {
2248  const clang::DeclContext *ctxt = cl.getDeclContext();
2249  while(ctxt && !ctxt->isNamespace()) {
2250  ctxt = ctxt->getParent();
2251  }
2252  return ctxt;
2253 }
2254 
2255 ////////////////////////////////////////////////////////////////////////////////
2256 /// Write all the necessary opening part of the namespace and
2257 /// return the number of closing brackets needed
2258 /// For example for Space1::Space2
2259 /// we write: namespace Space1 { namespace Space2 {
2260 /// and return 2.
2261 
2262 int ROOT::TMetaUtils::WriteNamespaceHeader(std::ostream &out, const clang::DeclContext *ctxt)
2263 {
2264  int closing_brackets = 0;
2265 
2266  //fprintf(stderr,"DEBUG: in WriteNamespaceHeader for %s with %s\n",
2267  // cl.Fullname(),namespace_obj.Fullname());
2268  if (ctxt && ctxt->isNamespace()) {
2269  closing_brackets = WriteNamespaceHeader(out,ctxt->getParent());
2270  const clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(ctxt);
2271  if (ns) {
2272  for (int indent = 0; indent < closing_brackets; ++indent)
2273  out << " ";
2274  if (ns->isInline())
2275  out << "inline ";
2276  out << "namespace " << ns->getNameAsString() << " {" << std::endl;
2277  closing_brackets++;
2278  }
2279  }
2280 
2281  return closing_brackets;
2282 }
2283 
2284 ////////////////////////////////////////////////////////////////////////////////
2285 
2286 int ROOT::TMetaUtils::WriteNamespaceHeader(std::ostream &out, const clang::RecordDecl *cl)
2287 {
2288  return WriteNamespaceHeader(out, GetEnclosingSpace(*cl));
2289 }
2290 
2291 ////////////////////////////////////////////////////////////////////////////////
2292 
2293 bool ROOT::TMetaUtils::NeedTemplateKeyword(const clang::CXXRecordDecl *cl)
2294 {
2295  clang::TemplateSpecializationKind kind = cl->getTemplateSpecializationKind();
2296  if (kind == clang::TSK_Undeclared ) {
2297  // Note a template;
2298  return false;
2299  } else if (kind == clang::TSK_ExplicitSpecialization) {
2300  // This is a specialized templated class
2301  return false;
2302  } else {
2303  // This is an automatically or explicitly instantiated templated class.
2304  return true;
2305  }
2306 }
2307 
2308 ////////////////////////////////////////////////////////////////////////////////
2309 /// return true if we can find a custom operator new with placement
2310 
2311 bool ROOT::TMetaUtils::HasCustomOperatorNewPlacement(const char *which, const clang::RecordDecl &cl, const cling::Interpreter &interp)
2312 {
2313  const char *name = which;
2314  const char *proto = "size_t";
2315  const char *protoPlacement = "size_t,void*";
2316 
2317  // First search in the enclosing namespaces
2318  const clang::FunctionDecl *operatornew
2319  = ROOT::TMetaUtils::GetFuncWithProto(llvm::dyn_cast<clang::Decl>(cl.getDeclContext()),
2320  name, proto, interp,
2321  cling::LookupHelper::NoDiagnostics);
2322  const clang::FunctionDecl *operatornewPlacement
2323  = ROOT::TMetaUtils::GetFuncWithProto(llvm::dyn_cast<clang::Decl>(cl.getDeclContext()),
2324  name, protoPlacement, interp,
2325  cling::LookupHelper::NoDiagnostics);
2326 
2327  const clang::DeclContext *ctxtnew = 0;
2328  const clang::DeclContext *ctxtnewPlacement = 0;
2329 
2330  if (operatornew) {
2331  ctxtnew = operatornew->getParent();
2332  }
2333  if (operatornewPlacement) {
2334  ctxtnewPlacement = operatornewPlacement->getParent();
2335  }
2336 
2337  // Then in the class and base classes
2338  operatornew = ROOT::TMetaUtils::GetFuncWithProto(&cl, name, proto, interp,
2339  false /*diags*/);
2340  operatornewPlacement
2341  = ROOT::TMetaUtils::GetFuncWithProto(&cl, name, protoPlacement, interp,
2342  false /*diags*/);
2343 
2344  if (operatornew) {
2345  ctxtnew = operatornew->getParent();
2346  }
2347  if (operatornewPlacement) {
2348  ctxtnewPlacement = operatornewPlacement->getParent();
2349  }
2350 
2351  if (ctxtnewPlacement == 0) {
2352  return false;
2353  }
2354  if (ctxtnew == 0) {
2355  // Only a new with placement, no hiding
2356  return true;
2357  }
2358  // Both are non zero
2359  if (ctxtnew == ctxtnewPlacement) {
2360  // Same declaration ctxt, no hiding
2361  return true;
2362  }
2363  const clang::CXXRecordDecl* clnew = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnew);
2364  const clang::CXXRecordDecl* clnewPlacement = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnewPlacement);
2365  if (clnew == 0 && clnewPlacement == 0) {
2366  // They are both in different namespaces, I am not sure of the rules.
2367  // we probably ought to find which one is closest ... for now bail
2368  // (because rootcling was also bailing on that).
2369  return true;
2370  }
2371  if (clnew != 0 && clnewPlacement == 0) {
2372  // operator new is class method hiding the outer scope operator new with placement.
2373  return false;
2374  }
2375  if (clnew == 0 && clnewPlacement != 0) {
2376  // operator new is a not class method and can not hide new with placement which is a method
2377  return true;
2378  }
2379  // Both are class methods
2380  if (clnew->isDerivedFrom(clnewPlacement)) {
2381  // operator new is in a more derived part of the hierarchy, it is hiding operator new with placement.
2382  return false;
2383  }
2384  // operator new with placement is in a more derived part of the hierarchy, it can't be hidden by operator new.
2385  return true;
2386 }
2387 
2388 ////////////////////////////////////////////////////////////////////////////////
2389 /// return true if we can find a custom operator new with placement
2390 
2391 bool ROOT::TMetaUtils::HasCustomOperatorNewPlacement(const clang::RecordDecl &cl, const cling::Interpreter &interp)
2392 {
2393  return HasCustomOperatorNewPlacement("operator new",cl, interp);
2394 }
2395 
2396 ////////////////////////////////////////////////////////////////////////////////
2397 /// return true if we can find a custom operator new with placement
2398 
2399 bool ROOT::TMetaUtils::HasCustomOperatorNewArrayPlacement(const clang::RecordDecl &cl, const cling::Interpreter &interp)
2400 {
2401  return HasCustomOperatorNewPlacement("operator new[]",cl, interp);
2402 }
2403 
2404 ////////////////////////////////////////////////////////////////////////////////
2405 /// std::string NormalizedName;
2406 /// GetNormalizedName(NormalizedName, decl->getASTContext().getTypeDeclType(decl), interp, normCtxt);
2407 
2408 void ROOT::TMetaUtils::WriteAuxFunctions(std::ostream& finalString,
2409  const AnnotatedRecordDecl &cl,
2410  const clang::CXXRecordDecl *decl,
2411  const cling::Interpreter &interp,
2412  const RConstructorTypes& ctorTypes,
2413  const TNormalizedCtxt &normCtxt)
2414 {
2415  std::string classname = TClassEdit::GetLong64_Name(cl.GetNormalizedName());
2416 
2417  std::string mappedname;
2418  ROOT::TMetaUtils::GetCppName(mappedname,classname.c_str());
2419 
2420  // Write the functions that are need for the TGenericClassInfo.
2421  // This includes
2422  // IsA
2423  // operator new
2424  // operator new[]
2425  // operator delete
2426  // operator delete[]
2427 
2428  ROOT::TMetaUtils::GetCppName(mappedname,classname.c_str());
2429 
2430  if ( ! TClassEdit::IsStdClass( classname.c_str() ) ) {
2431 
2432  // Prefix the full class name with '::' except for the STL
2433  // containers and std::string. This is to request the
2434  // real class instead of the class in the namespace ROOT::Shadow
2435  classname.insert(0,"::");
2436  }
2437 
2438  finalString << "namespace ROOT {" << "\n";
2439 
2440  std::string args;
2441  if (HasIOConstructor(decl, args, ctorTypes, interp)) {
2442  // write the constructor wrapper only for concrete classes
2443  finalString << " // Wrappers around operator new" << "\n";
2444  finalString << " static void *new_" << mappedname.c_str() << "(void *p) {" << "\n" << " return p ? ";
2445  if (HasCustomOperatorNewPlacement(*decl, interp)) {
2446  finalString << "new(p) ";
2447  finalString << classname.c_str();
2448  finalString << args;
2449  finalString << " : ";
2450  } else {
2451  finalString << "::new((::ROOT::Internal::TOperatorNewHelper*)p) ";
2452  finalString << classname.c_str();
2453  finalString << args;
2454  finalString << " : ";
2455  }
2456  finalString << "new " << classname.c_str() << args << ";" << "\n";
2457  finalString << " }" << "\n";
2458 
2459  if (args.size()==0 && NeedDestructor(decl, interp)) {
2460  // Can not can newArray if the destructor is not public.
2461  finalString << " static void *newArray_";
2462  finalString << mappedname.c_str();
2463  finalString << "(Long_t nElements, void *p) {";
2464  finalString << "\n";
2465  finalString << " return p ? ";
2466  if (HasCustomOperatorNewArrayPlacement(*decl, interp)) {
2467  finalString << "new(p) ";
2468  finalString << classname.c_str();
2469  finalString << "[nElements] : ";
2470  } else {
2471  finalString << "::new((::ROOT::Internal::TOperatorNewHelper*)p) ";
2472  finalString << classname.c_str();
2473  finalString << "[nElements] : ";
2474  }
2475  finalString << "new ";
2476  finalString << classname.c_str();
2477  finalString << "[nElements];";
2478  finalString << "\n";
2479  finalString << " }";
2480  finalString << "\n";
2481  }
2482  }
2483 
2484  if (NeedDestructor(decl, interp)) {
2485  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  }
2487 
2488  if (HasDirectoryAutoAdd(decl, interp)) {
2489  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  }
2491 
2492  if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) {
2493  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  }
2495 
2496  if (HasCustomConvStreamerMemberFunction(cl, decl, interp, normCtxt)) {
2497  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  }
2499 
2500  if (HasNewMerge(decl, interp)) {
2501  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";
2502  } else if (HasOldMerge(decl, interp)) {
2503  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  }
2505 
2506  if (HasResetAfterMerge(decl, interp)) {
2507  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";
2508  }
2509  finalString << "} // end of namespace ROOT for class " << classname.c_str() << "\n" << "\n";
2510 }
2511 
2512 ////////////////////////////////////////////////////////////////////////////////
2513 /// Write interface function for STL members
2514 
2516  const cling::Interpreter &interp,
2517  const TNormalizedCtxt &normCtxt)
2518 {
2519  std::string a;
2520  std::string clName;
2521  TMetaUtils::GetCppName(clName, ROOT::TMetaUtils::GetFileName(*cl.GetRecordDecl(), interp).str().c_str());
2522  int version = ROOT::TMetaUtils::GetClassVersion(cl.GetRecordDecl(),interp);
2523  if (version == 0) return;
2524  if (version < 0 && !(cl.RequestStreamerInfo()) ) return;
2525 
2526 
2527  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
2528  if (clxx == 0) return;
2529 
2530  // We also need to look at the base classes.
2531  for(clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
2532  iter != end;
2533  ++iter)
2534  {
2535  int k = ROOT::TMetaUtils::IsSTLContainer(*iter);
2536  if (k!=0) {
2537  Internal::RStl::Instance().GenerateTClassFor( iter->getType(), interp, normCtxt);
2538  }
2539  }
2540 
2541  // Loop over the non static data member.
2542  for(clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
2543  field_iter != end;
2544  ++field_iter)
2545  {
2546  std::string mTypename;
2547  ROOT::TMetaUtils::GetQualifiedName(mTypename, field_iter->getType(), *clxx);
2548 
2549  //member is a string
2550  {
2551  const char*shortTypeName = ROOT::TMetaUtils::ShortTypeName(mTypename.c_str());
2552  if (!strcmp(shortTypeName, "string")) {
2553  continue;
2554  }
2555  }
2556 
2557  if (!ROOT::TMetaUtils::IsStreamableObject(**field_iter, interp)) continue;
2558 
2559  int k = ROOT::TMetaUtils::IsSTLContainer( **field_iter );
2560  if (k!=0) {
2561  // fprintf(stderr,"Add %s which is also",m.Type()->Name());
2562  // fprintf(stderr," %s\n",R__TrueName(**field_iter) );
2563  clang::QualType utype(ROOT::TMetaUtils::GetUnderlyingType(field_iter->getType()),0);
2564  Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
2565  }
2566  }
2567 }
2568 
2569 ////////////////////////////////////////////////////////////////////////////////
2570 /// TrueName strips the typedefs and array dimensions.
2571 
2572 std::string ROOT::TMetaUtils::TrueName(const clang::FieldDecl &m)
2573 {
2574  const clang::Type *rawtype = m.getType()->getCanonicalTypeInternal().getTypePtr();
2575  if (rawtype->isArrayType()) {
2576  rawtype = rawtype->getBaseElementTypeUnsafe ();
2577  }
2578 
2579  std::string result;
2580  ROOT::TMetaUtils::GetQualifiedName(result, clang::QualType(rawtype,0), m);
2581  return result;
2582 }
2583 
2584 ////////////////////////////////////////////////////////////////////////////////
2585 /// Return the version number of the class or -1
2586 /// if the function Class_Version does not exist.
2587 
2588 int ROOT::TMetaUtils::GetClassVersion(const clang::RecordDecl *cl, const cling::Interpreter& interp)
2589 {
2590  const clang::CXXRecordDecl* CRD = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
2591  if (!CRD) {
2592  // Must be an enum or namespace.
2593  // FIXME: Make it work for a namespace!
2594  return -1;
2595  }
2596  const clang::FunctionDecl* funcCV = ROOT::TMetaUtils::ClassInfo__HasMethod(CRD,"Class_Version",interp);
2597 
2598  // if we have no Class_Info() return -1.
2599  if (!funcCV) return -1;
2600 
2601  // if we have many Class_Info() (?!) return 1.
2602  if (funcCV == (clang::FunctionDecl*)-1) return 1;
2603 
2604  return GetTrivialIntegralReturnValue(funcCV, interp).second;
2605 }
2606 
2607 ////////////////////////////////////////////////////////////////////////////////
2608 /// If the function contains 'just': return SomeValue;
2609 /// this routine will extract this value and return it.
2610 /// The first element is set to true we have the body of the function and it
2611 /// is indeed a trivial function with just a return of a value.
2612 /// The second element contains the value (or -1 is case of failure)
2613 
2614 std::pair<bool, int>
2615 ROOT::TMetaUtils::GetTrivialIntegralReturnValue(const clang::FunctionDecl *funcCV, const cling::Interpreter &interp)
2616 {
2617  using res_t = std::pair<bool, int>;
2618 
2619  const clang::CompoundStmt* FuncBody
2620  = llvm::dyn_cast_or_null<clang::CompoundStmt>(funcCV->getBody());
2621  if (!FuncBody)
2622  return res_t{false, -1};
2623  if (FuncBody->size() != 1) {
2624  // This is a non-ClassDef(), complex function - it might depend on state
2625  // and thus we'll need the runtime and cannot determine the result
2626  // statically.
2627  return res_t{false, -1};
2628  }
2629  const clang::ReturnStmt* RetStmt
2630  = llvm::dyn_cast<clang::ReturnStmt>(FuncBody->body_back());
2631  if (!RetStmt)
2632  return res_t{false, -1};
2633  const clang::Expr* RetExpr = RetStmt->getRetValue();
2634  // ClassDef controls the content of Class_Version() but not the return
2635  // expression which is CPP expanded from what the user provided as second
2636  // ClassDef argument. It's usually just be an integer literal but it could
2637  // also be an enum or a variable template for all we know.
2638  // Go through ICE to be more general.
2639  llvm::APSInt RetRes;
2640  if (!RetExpr->isIntegerConstantExpr(RetRes, funcCV->getASTContext()))
2641  return res_t{false, -1};
2642  if (RetRes.isSigned()) {
2643  return res_t{true, (Version_t)RetRes.getSExtValue()};
2644  }
2645  // else
2646  return res_t{true, (Version_t)RetRes.getZExtValue()};
2647 }
2648 
2649 ////////////////////////////////////////////////////////////////////////////////
2650 /// Is this an STL container.
2651 
2653 {
2654  return TMetaUtils::IsSTLCont(*annotated.GetRecordDecl());
2655 }
2656 
2657 ////////////////////////////////////////////////////////////////////////////////
2658 /// Is this an STL container?
2659 
2661 {
2662  clang::QualType type = m.getType();
2663  clang::RecordDecl *decl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(type);
2664 
2665  if (decl) return TMetaUtils::IsSTLCont(*decl);
2666  else return ROOT::kNotSTL;
2667 }
2668 
2669 ////////////////////////////////////////////////////////////////////////////////
2670 /// Is this an STL container?
2671 
2672 int ROOT::TMetaUtils::IsSTLContainer(const clang::CXXBaseSpecifier &base)
2673 {
2674  clang::QualType type = base.getType();
2675  clang::RecordDecl *decl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(type);
2676 
2677  if (decl) return TMetaUtils::IsSTLCont(*decl);
2678  else return ROOT::kNotSTL;
2679 }
2680 
2681 ////////////////////////////////////////////////////////////////////////////////
2682 /// Calls the given lambda on every header in the given module.
2683 /// includeDirectlyUsedModules designates if the foreach should also loop over
2684 /// the headers in all modules that are directly used via a `use` declaration
2685 /// in the modulemap.
2686 void ROOT::TMetaUtils::foreachHeaderInModule(const clang::Module &module,
2687  const std::function<void(const clang::Module::Header &)> &closure,
2688  bool includeDirectlyUsedModules)
2689 {
2690  // Iterates over all headers in a module and calls the closure on each.
2691 
2692  // FIXME: We currently have to hardcode '4' to do this. Maybe we
2693  // will have a nicer way to do this in the future.
2694  // NOTE: This is on purpose '4', not '5' which is the size of the
2695  // vector. The last element is the list of excluded headers which we
2696  // obviously don't want to check here.
2697  const std::size_t publicHeaderIndex = 4;
2698 
2699  // Integrity check in case this array changes its size at some point.
2700  const std::size_t maxArrayLength = ((sizeof module.Headers) / (sizeof *module.Headers));
2701  static_assert(publicHeaderIndex + 1 == maxArrayLength,
2702  "'Headers' has changed it's size, we need to update publicHeaderIndex");
2703 
2704  // Make a list of modules and submodules that we can check for headers.
2705  // We use a SetVector to prevent an infinite loop in unlikely case the
2706  // modules somehow are messed up and don't form a tree...
2707  llvm::SetVector<const clang::Module *> modules;
2708  modules.insert(&module);
2709  for (size_t i = 0; i < modules.size(); ++i) {
2710  const clang::Module *M = modules[i];
2711  for (const clang::Module *subModule : M->submodules())
2712  modules.insert(subModule);
2713  }
2714 
2715  for (const clang::Module *m : modules) {
2716  if (includeDirectlyUsedModules) {
2717  for (clang::Module *used : m->DirectUses) {
2718  foreachHeaderInModule(*used, closure, true);
2719  }
2720  }
2721 
2722  for (std::size_t i = 0; i < publicHeaderIndex; i++) {
2723  auto &headerList = m->Headers[i];
2724  for (const clang::Module::Header &moduleHeader : headerList) {
2725  closure(moduleHeader);
2726  }
2727  }
2728  }
2729 }
2730 
2731 ////////////////////////////////////////////////////////////////////////////////
2732 /// Return the absolute type of typeDesc.
2733 /// E.g.: typeDesc = "class TNamed**", returns "TNamed".
2734 /// we remove * and const keywords. (we do not want to remove & ).
2735 /// You need to use the result immediately before it is being overwritten.
2736 
2737 const char *ROOT::TMetaUtils::ShortTypeName(const char *typeDesc)
2738 {
2739  static char t[4096];
2740  static const char* constwd = "const ";
2741  static const char* constwdend = "const";
2742 
2743  const char *s;
2744  char *p=t;
2745  int lev=0;
2746  for (s=typeDesc;*s;s++) {
2747  if (*s=='<') lev++;
2748  if (*s=='>') lev--;
2749  if (lev==0 && *s=='*') continue;
2750  if (lev==0 && (strncmp(constwd,s,strlen(constwd))==0
2751  ||strcmp(constwdend,s)==0 ) ) {
2752  s+=strlen(constwd)-1; // -1 because the loop adds 1
2753  continue;
2754  }
2755  if (lev==0 && *s==' ' && *(s+1)!='*') { p = t; continue;}
2756  if (p - t > (long)sizeof(t)) {
2757  printf("ERROR (rootcling): type name too long for StortTypeName: %s\n",
2758  typeDesc);
2759  p[0] = 0;
2760  return t;
2761  }
2762  *p++ = *s;
2763  }
2764  p[0]=0;
2765 
2766  return t;
2767 }
2768 
2769 bool ROOT::TMetaUtils::IsStreamableObject(const clang::FieldDecl &m,
2770  const cling::Interpreter& interp)
2771 {
2772  const char *comment = ROOT::TMetaUtils::GetComment( m ).data();
2773 
2774  // Transient
2775  if (comment[0] == '!') return false;
2776 
2777  clang::QualType type = m.getType();
2778 
2779  if (type->isReferenceType()) {
2780  // Reference can not be streamed.
2781  return false;
2782  }
2783 
2784  std::string mTypeName = type.getAsString(m.getASTContext().getPrintingPolicy());
2785  if (!strcmp(mTypeName.c_str(), "string") || !strcmp(mTypeName.c_str(), "string*")) {
2786  return true;
2787  }
2788  if (!strcmp(mTypeName.c_str(), "std::string") || !strcmp(mTypeName.c_str(), "std::string*")) {
2789  return true;
2790  }
2791 
2793  return true;
2794  }
2795 
2796  const clang::Type *rawtype = type.getTypePtr()->getBaseElementTypeUnsafe ();
2797 
2798  if (rawtype->isPointerType()) {
2799  //Get to the 'raw' type.
2800  clang::QualType pointee;
2801  while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
2802  {
2803  rawtype = pointee.getTypePtr();
2804  }
2805  }
2806 
2807  if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2808  // not an ojbect.
2809  return false;
2810  }
2811 
2812  const clang::CXXRecordDecl *cxxdecl = rawtype->getAsCXXRecordDecl();
2813  if (cxxdecl && ROOT::TMetaUtils::ClassInfo__HasMethod(cxxdecl,"Streamer", interp)) {
2814  if (!(ROOT::TMetaUtils::ClassInfo__HasMethod(cxxdecl,"Class_Version", interp))) return true;
2815  int version = ROOT::TMetaUtils::GetClassVersion(cxxdecl,interp);
2816  if (version > 0) return true;
2817  }
2818  return false;
2819 }
2820 
2821 ////////////////////////////////////////////////////////////////////////////////
2822 /// Return the absolute type of typeDesc.
2823 /// E.g.: typeDesc = "class TNamed**", returns "TNamed".
2824 /// we remove * and const keywords. (we do not want to remove & ).
2825 /// You need to use the result immediately before it is being overwritten.
2826 
2827 std::string ROOT::TMetaUtils::ShortTypeName(const clang::FieldDecl &m)
2828 {
2829  const clang::Type *rawtype = m.getType().getTypePtr();
2830 
2831  //Get to the 'raw' type.
2832  clang::QualType pointee;
2833  while ( rawtype->isPointerType() && ((pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull()) && pointee.getTypePtr() != rawtype)
2834  {
2835  rawtype = pointee.getTypePtr();
2836  }
2837 
2838  std::string result;
2839  ROOT::TMetaUtils::GetQualifiedName(result, clang::QualType(rawtype,0), m);
2840  return result;
2841 }
2842 
2843 ////////////////////////////////////////////////////////////////////////////////
2844 
2845 clang::RecordDecl *ROOT::TMetaUtils::GetUnderlyingRecordDecl(clang::QualType type)
2846 {
2848 
2849  if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2850  // not an object.
2851  return nullptr;
2852  }
2853  return rawtype->getAsCXXRecordDecl();
2854 }
2855 
2856 ////////////////////////////////////////////////////////////////////////////////
2857 /// Generate the code of the class
2858 /// If the requestor is genreflex, request the new streamer format
2859 
2861  const AnnotatedRecordDecl &cl,
2862  const cling::Interpreter &interp,
2863  const TNormalizedCtxt &normCtxt,
2864  std::ostream& dictStream,
2865  const RConstructorTypes& ctorTypes,
2866  bool isGenreflex=false)
2867 {
2868  const clang::CXXRecordDecl* decl = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
2869 
2870  if (!decl || !decl->isCompleteDefinition()) {
2871  return;
2872  }
2873 
2874  std::string fullname;
2876  if (TClassEdit::IsSTLCont(fullname) ) {
2877  Internal::RStl::Instance().GenerateTClassFor(cl.GetNormalizedName(), llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl()), interp, normCtxt);
2878  return;
2879  }
2880 
2881  if (ROOT::TMetaUtils::ClassInfo__HasMethod(cl,"Streamer",interp)) {
2882  // The !genreflex is there to prevent genreflex to select collections which are data members
2883  // This is to maintain the behaviour of ROOT5 and ROOT6 up to 6.07 included.
2884  if (cl.RootFlag() && !isGenreflex) ROOT::TMetaUtils::WritePointersSTL(cl, interp, normCtxt); // In particular this detect if the class has a version number.
2885  if (!(cl.RequestNoStreamer())) {
2886  (*WriteStreamerFunc)(cl, interp, normCtxt, dictStream, isGenreflex || cl.RequestStreamerInfo());
2887  } else
2888  ROOT::TMetaUtils::Info(0, "Class %s: Do not generate Streamer() [*** custom streamer ***]\n",fullname.c_str());
2889  } else {
2890  ROOT::TMetaUtils::Info(0, "Class %s: Streamer() not declared\n", fullname.c_str());
2891 
2892  // See comment above about the !isGenreflex
2893  if (cl.RequestStreamerInfo() && !isGenreflex) ROOT::TMetaUtils::WritePointersSTL(cl, interp, normCtxt);
2894  }
2895  ROOT::TMetaUtils::WriteAuxFunctions(dictStream, cl, decl, interp, ctorTypes, normCtxt);
2896 }
2897 
2898 ////////////////////////////////////////////////////////////////////////////////
2899 /// Add any unspecified template parameters to the class template instance,
2900 /// mentioned anywhere in the type.
2901 ///
2902 /// Note: this does not strip any typedef but could be merged with cling::utils::Transform::GetPartiallyDesugaredType
2903 /// if we can safely replace TClassEdit::IsStd with a test on the declaring scope
2904 /// and if we can resolve the fact that the added parameter do not take into account possible use/dependences on Double32_t
2905 /// and if we decide that adding the default is the right long term solution or not.
2906 /// Whether it is or not depend on the I/O on whether the default template argument might change or not
2907 /// and whether they (should) affect the on disk layout (for STL containers, we do know they do not).
2908 
2909 clang::QualType ROOT::TMetaUtils::AddDefaultParameters(clang::QualType instanceType,
2910  const cling::Interpreter &interpreter,
2911  const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
2912 {
2913  const clang::ASTContext& Ctx = interpreter.getCI()->getASTContext();
2914 
2915  clang::QualType originalType = instanceType;
2916 
2917  // In case of name* we need to strip the pointer first, add the default and attach
2918  // the pointer once again.
2919  if (llvm::isa<clang::PointerType>(instanceType.getTypePtr())) {
2920  // Get the qualifiers.
2921  clang::Qualifiers quals = instanceType.getQualifiers();
2922  clang::QualType newPointee = AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2923  if (newPointee != instanceType->getPointeeType()) {
2924  instanceType = Ctx.getPointerType(newPointee);
2925  // Add back the qualifiers.
2926  instanceType = Ctx.getQualifiedType(instanceType, quals);
2927  }
2928  return instanceType;
2929  }
2930 
2931  // In case of Int_t& we need to strip the pointer first, desugar and attach
2932  // the pointer once again.
2933  if (llvm::isa<clang::ReferenceType>(instanceType.getTypePtr())) {
2934  // Get the qualifiers.
2935  bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(instanceType.getTypePtr());
2936  clang::Qualifiers quals = instanceType.getQualifiers();
2937  clang::QualType newPointee = AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2938 
2939  if (newPointee != instanceType->getPointeeType()) {
2940  // Add the r- or l- value reference type back to the desugared one
2941  if (isLValueRefTy)
2942  instanceType = Ctx.getLValueReferenceType(newPointee);
2943  else
2944  instanceType = Ctx.getRValueReferenceType(newPointee);
2945  // Add back the qualifiers.
2946  instanceType = Ctx.getQualifiedType(instanceType, quals);
2947  }
2948  return instanceType;
2949  }
2950 
2951  // Treat the Scope.
2952  bool prefix_changed = false;
2953  clang::NestedNameSpecifier* prefix = 0;
2954  clang::Qualifiers prefix_qualifiers = instanceType.getLocalQualifiers();
2955  const clang::ElaboratedType* etype
2956  = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
2957  if (etype) {
2958  // We have to also handle the prefix.
2959  prefix = AddDefaultParametersNNS(Ctx, etype->getQualifier(), interpreter, normCtxt);
2960  prefix_changed = prefix != etype->getQualifier();
2961  instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
2962  }
2963 
2964  // In case of template specializations iterate over the arguments and
2965  // add unspecified default parameter.
2966 
2967  const clang::TemplateSpecializationType* TST
2968  = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
2969 
2970  const clang::ClassTemplateSpecializationDecl* TSTdecl
2971  = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instanceType.getTypePtr()->getAsCXXRecordDecl());
2972 
2973  // Don't add the default paramater onto std classes.
2974  // We really need this for __shared_ptr which add a enum constant value which
2975  // is spelled in its 'numeral' form and thus the resulting type name is
2976  // incorrect. We also can used this for any of the STL collections where we
2977  // know we don't want the default argument. For the other members of the
2978  // std namespace this is dubious (because TMetaUtils::GetNormalizedName would
2979  // not drop those defaults). [I.e. the real test ought to be is std and
2980  // name is __shared_ptr or vector or list or set or etc.]
2981  bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
2982 
2983  bool mightHaveChanged = false;
2984  if (TST && TSTdecl) {
2985 
2986  clang::Sema& S = interpreter.getCI()->getSema();
2987  clang::TemplateDecl *Template = TSTdecl->getSpecializedTemplate()->getMostRecentDecl();
2988  clang::TemplateParameterList *Params = Template->getTemplateParameters();
2989  clang::TemplateParameterList::iterator Param = Params->begin(); // , ParamEnd = Params->end();
2990  //llvm::SmallVectorImpl<TemplateArgument> Converted; // Need to contains the other arguments.
2991  // Converted seems to be the same as our 'desArgs'
2992 
2993  unsigned int dropDefault = normCtxt.GetConfig().DropDefaultArg(*Template);
2994 
2995  llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
2996  unsigned int Idecl = 0, Edecl = TSTdecl->getTemplateArgs().size();
2997  unsigned int maxAddArg = TSTdecl->getTemplateArgs().size() - dropDefault;
2998  for(clang::TemplateSpecializationType::iterator
2999  I = TST->begin(), E = TST->end();
3000  Idecl != Edecl;
3001  I!=E ? ++I : 0, ++Idecl, ++Param) {
3002 
3003  if (I != E) {
3004 
3005  if (I->getKind() == clang::TemplateArgument::Template) {
3006  clang::TemplateName templateName = I->getAsTemplate();
3007  clang::TemplateDecl* templateDecl = templateName.getAsTemplateDecl();
3008  if (templateDecl) {
3009  clang::DeclContext* declCtxt = templateDecl->getDeclContext();
3010 
3011  if (declCtxt && !templateName.getAsQualifiedTemplateName()){
3012  clang::NamespaceDecl* ns = clang::dyn_cast<clang::NamespaceDecl>(declCtxt);
3013  clang::NestedNameSpecifier* nns;
3014  if (ns) {
3015  nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx, ns);
3016  } else if (clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(declCtxt)) {
3017  nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx,TD, false /*FullyQualified*/);
3018  } else {
3019  // TU scope
3020  desArgs.push_back(*I);
3021  continue;
3022  }
3023  clang::TemplateName templateNameWithNSS ( Ctx.getQualifiedTemplateName(nns, false, templateDecl) );
3024  desArgs.push_back(clang::TemplateArgument(templateNameWithNSS));
3025  mightHaveChanged = true;
3026  continue;
3027  }
3028  }
3029  }
3030 
3031  if (I->getKind() != clang::TemplateArgument::Type) {
3032  desArgs.push_back(*I);
3033  continue;
3034  }
3035 
3036  clang::QualType SubTy = I->getAsType();
3037 
3038  // Check if the type needs more desugaring and recurse.
3039  // (Originally this was limited to elaborated and templated type,
3040  // but we also need to do it for pointer and reference type
3041  // and who knows what, so do it always)
3042  clang::QualType newSubTy = AddDefaultParameters(SubTy,
3043  interpreter,
3044  normCtxt);
3045  if (SubTy != newSubTy) {
3046  mightHaveChanged = true;
3047  desArgs.push_back(clang::TemplateArgument(newSubTy));
3048  } else {
3049  desArgs.push_back(*I);
3050  }
3051  // Converted.push_back(TemplateArgument(ArgTypeForTemplate));
3052  } else if (!isStdDropDefault && Idecl < maxAddArg) {
3053 
3054  mightHaveChanged = true;
3055 
3056  const clang::TemplateArgument& templateArg
3057  = TSTdecl->getTemplateArgs().get(Idecl);
3058  if (templateArg.getKind() != clang::TemplateArgument::Type) {
3059  desArgs.push_back(templateArg);
3060  continue;
3061  }
3062  clang::QualType SubTy = templateArg.getAsType();
3063 
3064  clang::SourceLocation TemplateLoc = Template->getSourceRange ().getBegin(); //NOTE: not sure that this is the 'right' location.
3065  clang::SourceLocation RAngleLoc = TSTdecl->getSourceRange().getBegin(); // NOTE: most likely wrong, I think this is expecting the location of right angle
3066 
3067  clang::TemplateTypeParmDecl *TTP = llvm::dyn_cast<clang::TemplateTypeParmDecl>(*Param);
3068  {
3069  // We may induce template instantiation
3070  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interpreter));
3071  clang::sema::HackForDefaultTemplateArg raii;
3072  bool HasDefaultArgs;
3073  clang::TemplateArgumentLoc ArgType = S.SubstDefaultTemplateArgumentIfAvailable(
3074  Template,
3075  TemplateLoc,
3076  RAngleLoc,
3077  TTP,
3078  desArgs,
3079  HasDefaultArgs);
3080  // The substition can fail, in which case there would have been compilation
3081  // error printed on the screen.
3082  if (ArgType.getArgument().isNull()
3083  || ArgType.getArgument().getKind() != clang::TemplateArgument::Type) {
3084  ROOT::TMetaUtils::Error("ROOT::TMetaUtils::AddDefaultParameters",
3085  "Template parameter substitution failed for %s around %s\n",
3086  instanceType.getAsString().c_str(), SubTy.getAsString().c_str());
3087  break;
3088  }
3089  clang::QualType BetterSubTy = ArgType.getArgument().getAsType();
3090  SubTy = cling::utils::Transform::GetPartiallyDesugaredType(Ctx,BetterSubTy,normCtxt.GetConfig(),/*fullyQualified=*/ true);
3091  }
3092  SubTy = AddDefaultParameters(SubTy,interpreter,normCtxt);
3093  desArgs.push_back(clang::TemplateArgument(SubTy));
3094  } else {
3095  // We are past the end of the list of specified arguements and we
3096  // do not want to add the default, no need to continue.
3097  break;
3098  }
3099  }
3100 
3101  // If we added default parameter, allocate new type in the AST.
3102  if (mightHaveChanged) {
3103  instanceType = Ctx.getTemplateSpecializationType(TST->getTemplateName(),
3104  desArgs,
3105  TST->getCanonicalTypeInternal());
3106  }
3107  }
3108 
3109  if (!prefix_changed && !mightHaveChanged) return originalType;
3110  if (prefix) {
3111  instanceType = Ctx.getElaboratedType(clang::ETK_None,prefix,instanceType);
3112  instanceType = Ctx.getQualifiedType(instanceType,prefix_qualifiers);
3113  }
3114  return instanceType;
3115 }
3116 
3117 ////////////////////////////////////////////////////////////////////////////////
3118 /// ValidArrayIndex return a static string (so use it or copy it immediatly, do not
3119 /// call GrabIndex twice in the same expression) containing the size of the
3120 /// array data member.
3121 /// In case of error, or if the size is not specified, GrabIndex returns 0.
3122 /// If errnum is not null, *errnum updated with the error number:
3123 /// Cint::G__DataMemberInfo::G__VALID : valid array index
3124 /// Cint::G__DataMemberInfo::G__NOT_INT : array index is not an int
3125 /// Cint::G__DataMemberInfo::G__NOT_DEF : index not defined before array
3126 /// (this IS an error for streaming to disk)
3127 /// Cint::G__DataMemberInfo::G__IS_PRIVATE: index exist in a parent class but is private
3128 /// Cint::G__DataMemberInfo::G__UNKNOWN : index is not known
3129 /// If errstr is not null, *errstr is updated with the address of a static
3130 /// string containing the part of the index with is invalid.
3131 
3132 llvm::StringRef ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(const clang::DeclaratorDecl &m, int *errnum, llvm::StringRef *errstr)
3133 {
3134  llvm::StringRef title;
3135 
3136  // Try to get the comment either from the annotation or the header file if present
3137  if (clang::AnnotateAttr *A = m.getAttr<clang::AnnotateAttr>())
3138  title = A->getAnnotation();
3139  else
3140  // Try to get the comment from the header file if present
3141  title = ROOT::TMetaUtils::GetComment( m );
3142 
3143  // Let's see if the user provided us with some information
3144  // with the format: //[dimension] this is the dim of the array
3145  // dimension can be an arithmetical expression containing, literal integer,
3146  // the operator *,+ and - and data member of integral type. In addition the
3147  // data members used for the size of the array need to be defined prior to
3148  // the array.
3149 
3150  if (errnum) *errnum = VALID;
3151 
3152  if (title.size() == 0 || (title[0] != '[')) return llvm::StringRef();
3153  size_t rightbracket = title.find(']');
3154  if (rightbracket == llvm::StringRef::npos) return llvm::StringRef();
3155 
3156  std::string working;
3157  llvm::StringRef indexvar(title.data()+1,rightbracket-1);
3158 
3159  // now we should have indexvar=dimension
3160  // Let's see if this is legal.
3161  // which means a combination of data member and digit separated by '*','+','-'
3162  // First we remove white spaces.
3163  unsigned int i;
3164  size_t indexvarlen = indexvar.size();
3165  for ( i=0; i<indexvarlen; i++) {
3166  if (!isspace(indexvar[i])) {
3167  working += indexvar[i];
3168  }
3169  };
3170 
3171  // Now we go through all indentifiers
3172  const char *tokenlist = "*+-";
3173  char *current = const_cast<char*>(working.c_str());
3174  current = strtok(current,tokenlist); // this method does not need to be reentrant
3175 
3176  while (current!=0) {
3177  // Check the token
3178  if (isdigit(current[0])) {
3179  for(i=0;i<strlen(current);i++) {
3180  if (!isdigit(current[i])) {
3181  // Error we only access integer.
3182  //NOTE: *** Need to print an error;
3183  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not an interger\n",
3184  // member.MemberOf()->Name(), member.Name(), current);
3185  if (errstr) *errstr = current;
3186  if (errnum) *errnum = NOT_INT;
3187  return llvm::StringRef();
3188  }
3189  }
3190  } else { // current token is not a digit
3191  // first let's see if it is a data member:
3192  const clang::CXXRecordDecl *parent_clxx = llvm::dyn_cast<clang::CXXRecordDecl>(m.getDeclContext());
3193  const clang::FieldDecl *index1 = nullptr;
3194  if (parent_clxx)
3195  index1 = GetDataMemberFromAll(*parent_clxx, current );
3196  if ( index1 ) {
3197  if ( IsFieldDeclInt(index1) ) {
3198  // Let's see if it has already been written down in the
3199  // Streamer.
3200  // Let's see if we already wrote it down in the
3201  // streamer.
3202  for(clang::RecordDecl::field_iterator field_iter = parent_clxx->field_begin(), end = parent_clxx->field_end();
3203  field_iter != end;
3204  ++field_iter)
3205  {
3206  if ( field_iter->getNameAsString() == m.getNameAsString() ) {
3207  // we reached the current data member before
3208  // reaching the index so we have not written it yet!
3209  //NOTE: *** Need to print an error;
3210  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) has not been defined before the array \n",
3211  // member.MemberOf()->Name(), member.Name(), current);
3212  if (errstr) *errstr = current;
3213  if (errnum) *errnum = NOT_DEF;
3214  return llvm::StringRef();
3215  }
3216  if ( field_iter->getNameAsString() == index1->getNameAsString() ) {
3217  break;
3218  }
3219  } // end of while (m_local.Next())
3220  } else {
3221  //NOTE: *** Need to print an error;
3222  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
3223  // member.MemberOf()->Name(), member.Name(), current);
3224  if (errstr) *errstr = current;
3225  if (errnum) *errnum = NOT_INT;
3226  return llvm::StringRef();
3227  }
3228  } else {
3229  // There is no variable by this name in this class, let see
3230  // the base classes!:
3231  int found = 0;
3232  if (parent_clxx)
3233  index1 = GetDataMemberFromAllParents( *parent_clxx, current );
3234  if ( index1 ) {
3235  if ( IsFieldDeclInt(index1) ) {
3236  found = 1;
3237  } else {
3238  // We found a data member but it is the wrong type
3239  //NOTE: *** Need to print an error;
3240  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
3241  // member.MemberOf()->Name(), member.Name(), current);
3242  if (errnum) *errnum = NOT_INT;
3243  if (errstr) *errstr = current;
3244  //NOTE: *** Need to print an error;
3245  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
3246  // member.MemberOf()->Name(), member.Name(), current);
3247  if (errnum) *errnum = NOT_INT;
3248  if (errstr) *errstr = current;
3249  return llvm::StringRef();
3250  }
3251  if ( found && (index1->getAccess() == clang::AS_private) ) {
3252  //NOTE: *** Need to print an error;
3253  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is a private member of %s \n",
3254  if (errstr) *errstr = current;
3255  if (errnum) *errnum = IS_PRIVATE;
3256  return llvm::StringRef();
3257  }
3258  }
3259  if (!found) {
3260  //NOTE: *** Need to print an error;
3261  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not known \n",
3262  // member.MemberOf()->Name(), member.Name(), indexvar);
3263  if (errstr) *errstr = indexvar;
3264  if (errnum) *errnum = UNKNOWN;
3265  return llvm::StringRef();
3266  } // end of if not found
3267  } // end of if is a data member of the class
3268  } // end of if isdigit
3269 
3270  current = strtok(0,tokenlist);
3271  } // end of while loop on tokens
3272 
3273  return indexvar;
3274 
3275 }
3276 
3277 ////////////////////////////////////////////////////////////////////////////////
3278 /// Return (in the argument 'output') a mangled version of the C++ symbol/type (pass as 'input')
3279 /// that can be used in C++ as a variable name.
3280 
3281 void ROOT::TMetaUtils::GetCppName(std::string &out, const char *in)
3282 {
3283  unsigned int i = 0;
3284  char c;
3285  out.clear();
3286  while((c = in[i++])) {
3287  const char *repl = nullptr;
3288  switch(c) {
3289  case '+': repl = "pL"; break;
3290  case '-': repl = "mI"; break;
3291  case '*': repl = "mU"; break;
3292  case '/': repl = "dI"; break;
3293  case '&': repl = "aN"; break;
3294  case '%': repl = "pE"; break;
3295  case '|': repl = "oR"; break;
3296  case '^': repl = "hA"; break;
3297  case '>': repl = "gR"; break;
3298  case '<': repl = "lE"; break;
3299  case '=': repl = "eQ"; break;
3300  case '~': repl = "wA"; break;
3301  case '.': repl = "dO"; break;
3302  case '(': repl = "oP"; break;
3303  case ')': repl = "cP"; break;
3304  case '[': repl = "oB"; break;
3305  case ']': repl = "cB"; break;
3306  case '!': repl = "nO"; break;
3307  case ',': repl = "cO"; break;
3308  case '$': repl = "dA"; break;
3309  case ' ': repl = "sP"; break;
3310  case ':': repl = "cL"; break;
3311  case '"': repl = "dQ"; break;
3312  case '@': repl = "aT"; break;
3313  case '\'': repl = "sQ"; break;
3314  case '\\': repl = "fI"; break;
3315  }
3316  if (repl)
3317  out.append(repl);
3318  else
3319  out.push_back(c);
3320  }
3321 
3322  // Remove initial numbers if any
3323  auto firstNonNumber = out.find_first_not_of("0123456789");
3324  if (firstNonNumber != std::string::npos)
3325  out.replace(0,firstNonNumber,"");
3326 }
3327 
3328 static clang::SourceLocation
3329 getFinalSpellingLoc(clang::SourceManager& sourceManager,
3330  clang::SourceLocation sourceLoc) {
3331  // Follow macro expansion until we hit a source file.
3332  if (!sourceLoc.isFileID()) {
3333  return sourceManager.getExpansionRange(sourceLoc).getEnd();
3334  }
3335  return sourceLoc;
3336 }
3337 
3338 ////////////////////////////////////////////////////////////////////////////////
3339 /// Return the header file to be included to declare the Decl.
3340 
3341 llvm::StringRef ROOT::TMetaUtils::GetFileName(const clang::Decl& decl,
3342  const cling::Interpreter& interp)
3343 {
3344  // It looks like the template specialization decl actually contains _less_ information
3345  // on the location of the code than the decl (in case where there is forward declaration,
3346  // that is what the specialization points to).
3347  //
3348  // const clang::CXXRecordDecl* clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
3349  // if (clxx) {
3350  // switch(clxx->getTemplateSpecializationKind()) {
3351  // case clang::TSK_Undeclared:
3352  // // We want the default behavior
3353  // break;
3354  // case clang::TSK_ExplicitInstantiationDeclaration:
3355  // case clang::TSK_ExplicitInstantiationDefinition:
3356  // case clang::TSK_ImplicitInstantiation: {
3357  // // We want the location of the template declaration:
3358  // const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
3359  // if (tmplt_specialization) {
3360  // // return GetFileName(const_cast< clang::ClassTemplateSpecializationDecl *>(tmplt_specialization)->getSpecializedTemplate());
3361  // }
3362  // break;
3363  // }
3364  // case clang::TSK_ExplicitSpecialization:
3365  // // We want the default behavior
3366  // break;
3367  // default:
3368  // break;
3369  // }
3370  // }
3371 
3372  using namespace clang;
3373  SourceLocation headerLoc = decl.getLocation();
3374 
3375  static const char invalidFilename[] = "";
3376  if (!headerLoc.isValid()) return invalidFilename;
3377 
3378  HeaderSearch& HdrSearch = interp.getCI()->getPreprocessor().getHeaderSearchInfo();
3379 
3380  SourceManager& sourceManager = decl.getASTContext().getSourceManager();
3381  headerLoc = getFinalSpellingLoc(sourceManager, headerLoc);
3382  FileID headerFID = sourceManager.getFileID(headerLoc);
3383  SourceLocation includeLoc
3384  = getFinalSpellingLoc(sourceManager,
3385  sourceManager.getIncludeLoc(headerFID));
3386 
3387  const FileEntry *headerFE = sourceManager.getFileEntryForID(headerFID);
3388  while (includeLoc.isValid() && sourceManager.isInSystemHeader(includeLoc)) {
3389  const DirectoryLookup *foundDir = 0;
3390  // use HeaderSearch on the basename, to make sure it takes a header from
3391  // the include path (e.g. not from /usr/include/bits/)
3392  assert(headerFE && "Couldn't find FileEntry from FID!");
3393  const FileEntry *FEhdr
3394  = HdrSearch.LookupFile(llvm::sys::path::filename(headerFE->getName()),
3395  SourceLocation(),
3396  true /*isAngled*/, 0/*FromDir*/, foundDir,
3397  ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3398  0/*Searchpath*/, 0/*RelPath*/,
3399  0/*SuggestedModule*/, 0/*RequestingModule*/,
3400  0/*IsMapped*/, nullptr /*IsFrameworkFound*/,
3401  false /*SkipCache*/,
3402  false /*BuildSystemModule*/,
3403  false /*OpenFile*/, true /*CacheFailures*/);
3404  if (FEhdr) break;
3405  headerFID = sourceManager.getFileID(includeLoc);
3406  headerFE = sourceManager.getFileEntryForID(headerFID);
3407  // If we have a system header in a module we can't just trace back the
3408  // original include with the preprocessor. But it should be enough if
3409  // we trace it back to the top-level system header that includes this
3410  // declaration.
3411  if (interp.getCI()->getLangOpts().Modules && !headerFE) {
3412  assert(decl.isFirstDecl() && "Couldn't trace back include from a decl"
3413  " that is not from an AST file");
3414  assert(StringRef(includeLoc.printToString(sourceManager)).startswith("<module-includes>"));
3415  break;
3416  }
3417  includeLoc = getFinalSpellingLoc(sourceManager,
3418  sourceManager.getIncludeLoc(headerFID));
3419  }
3420 
3421  if (!headerFE) return invalidFilename;
3422  llvm::StringRef headerFileName = headerFE->getName();
3423 
3424  // Now headerFID references the last valid system header or the original
3425  // user file.
3426  // Find out how to include it by matching file name to include paths.
3427  // We assume that the file "/A/B/C/D.h" can at some level be included as
3428  // "C/D.h". Be we cannot know whether that happens to be a different file
3429  // with the same name. Thus we first find the longest stem that can be
3430  // reached, say B/C/D.h. Then we find the shortest one, say C/D.h, that
3431  // points to the same file as the long version. If such a short version
3432  // exists it will be returned. If it doesn't the long version is returned.
3433  bool isAbsolute = llvm::sys::path::is_absolute(headerFileName);
3434  const FileEntry* FELong = 0;
3435  // Find the longest available match.
3436  for (llvm::sys::path::const_iterator
3437  IDir = llvm::sys::path::begin(headerFileName),
3438  EDir = llvm::sys::path::end(headerFileName);
3439  !FELong && IDir != EDir; ++IDir) {
3440  if (isAbsolute) {
3441  // skip "/" part
3442  isAbsolute = false;
3443  continue;
3444  }
3445  size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3446  llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3447  assert(trailingPart.data() + trailingPart.size()
3448  == headerFileName.data() + headerFileName.size()
3449  && "Mismatched partitioning of file name!");
3450  const DirectoryLookup* FoundDir = 0;
3451  FELong = HdrSearch.LookupFile(trailingPart, SourceLocation(),
3452  true /*isAngled*/, 0/*FromDir*/, FoundDir,
3453  ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3454  0/*Searchpath*/, 0/*RelPath*/,
3455  0/*SuggestedModule*/, 0/*RequestingModule*/,
3456  0/*IsMapped*/, nullptr /*IsFrameworkFound*/);
3457  }
3458 
3459  if (!FELong) {
3460  // We did not find any file part in any search path.
3461  return invalidFilename;
3462  }
3463 
3464  // Iterates through path *parts* "C"; we need trailing parts "C/D.h"
3465  for (llvm::sys::path::reverse_iterator
3466  IDir = llvm::sys::path::rbegin(headerFileName),
3467  EDir = llvm::sys::path::rend(headerFileName);
3468  IDir != EDir; ++IDir) {
3469  size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3470  llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3471  assert(trailingPart.data() + trailingPart.size()
3472  == headerFileName.data() + headerFileName.size()
3473  && "Mismatched partitioning of file name!");
3474  const DirectoryLookup* FoundDir = 0;
3475  // Can we find it, and is it the same file as the long version?
3476  // (or are we back to the previously found spelling, which is fine, too)
3477  if (HdrSearch.LookupFile(trailingPart, SourceLocation(),
3478  true /*isAngled*/, 0/*FromDir*/, FoundDir,
3479  ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3480  0/*Searchpath*/, 0/*RelPath*/,
3481  0/*SuggestedModule*/, 0/*RequestingModule*/,
3482  0/*IsMapped*/, nullptr /*IsFrameworkFound*/) == FELong) {
3483  return trailingPart;
3484  }
3485  }
3486 
3487  return invalidFilename;
3488 }
3489 
3490 ////////////////////////////////////////////////////////////////////////////////
3491 
3492 void ROOT::TMetaUtils::GetFullyQualifiedTypeName(std::string &typenamestr,
3493  const clang::QualType &qtype,
3494  const clang::ASTContext &astContext)
3495 {
3496  std::string fqname = cling::utils::TypeName::GetFullyQualifiedName(qtype, astContext);
3497  TClassEdit::TSplitType splitname(fqname.c_str(),
3500 }
3501 
3502 ////////////////////////////////////////////////////////////////////////////////
3503 
3504 void ROOT::TMetaUtils::GetFullyQualifiedTypeName(std::string &typenamestr,
3505  const clang::QualType &qtype,
3506  const cling::Interpreter &interpreter)
3507 {
3508  // We need this because GetFullyQualifiedTypeName is triggering deserialization
3509  // This calling the same name function GetFullyQualifiedTypeName, but this should stay here because
3510  // callee doesn't have an interpreter pointer
3511  cling::Interpreter::PushTransactionRAII RAII(const_cast<cling::Interpreter*>(&interpreter));
3512 
3513  GetFullyQualifiedTypeName(typenamestr,
3514  qtype,
3515  interpreter.getCI()->getASTContext());
3516 }
3517 
3518 ////////////////////////////////////////////////////////////////////////////////
3519 /// Get the template specialisation decl and template decl behind the qualtype
3520 /// Returns true if successfully found, false otherwise
3521 
3522 bool ROOT::TMetaUtils::QualType2Template(const clang::QualType& qt,
3523  clang::ClassTemplateDecl*& ctd,
3524  clang::ClassTemplateSpecializationDecl*& ctsd)
3525 {
3526  using namespace clang;
3527  const Type* theType = qt.getTypePtr();
3528  if (!theType){
3529  ctd=nullptr;
3530  ctsd=nullptr;
3531  return false;
3532  }
3533 
3534  if (theType->isPointerType()) {
3535  return QualType2Template(theType->getPointeeType(), ctd, ctsd);
3536  }
3537 
3538  if (const RecordType* rType = llvm::dyn_cast<RecordType>(theType)) {
3539  ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(rType->getDecl());
3540  if (ctsd) {
3541  ctd = ctsd->getSpecializedTemplate();
3542  return true;
3543  }
3544  }
3545 
3546  if (const SubstTemplateTypeParmType* sttpType = llvm::dyn_cast<SubstTemplateTypeParmType>(theType)){
3547  return QualType2Template(sttpType->getReplacementType(), ctd, ctsd);
3548  }
3549 
3550 
3551  ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(qt->getAsCXXRecordDecl());
3552  if(ctsd){
3553  ctd = ctsd->getSpecializedTemplate();
3554  return true;
3555  }
3556 
3557  ctd=nullptr;
3558  ctsd=nullptr;
3559  return false;
3560 }
3561 
3562 ////////////////////////////////////////////////////////////////////////////////
3563 /// Extract from a qualtype the class template if this makes sense.
3564 /// Retuns the ClassTemplateDecl or nullptr otherwise.
3565 
3566 clang::ClassTemplateDecl* ROOT::TMetaUtils::QualType2ClassTemplateDecl(const clang::QualType& qt)
3567 {
3568  using namespace clang;
3569  ClassTemplateSpecializationDecl* ctsd;
3570  ClassTemplateDecl* ctd;
3571  QualType2Template(qt,ctd,ctsd);
3572  return ctd;
3573 }
3574 
3575 ////////////////////////////////////////////////////////////////////////////////
3576 /// These manipulations are necessary because a template specialisation type
3577 /// does not inherit from a record type (there is an asymmetry between
3578 /// the decls and the types in the clang interface).
3579 /// We may need therefore to step into the "Decl dimension" to then get back
3580 /// to the "type dimension".
3581 
3582 clang::TemplateName ROOT::TMetaUtils::ExtractTemplateNameFromQualType(const clang::QualType& qt)
3583 {
3584  using namespace clang;
3585  TemplateName theTemplateName;
3586 
3587  const Type* theType = qt.getTypePtr();
3588 
3589  if (const TemplateSpecializationType* tst = llvm::dyn_cast_or_null<const TemplateSpecializationType>(theType)) {
3590  theTemplateName = tst->getTemplateName();
3591  } // We step into the decl dimension
3592  else if (ClassTemplateDecl* ctd = QualType2ClassTemplateDecl(qt)) {
3593  theTemplateName = TemplateName(ctd);
3594  }
3595 
3596  return theTemplateName;
3597 }
3598 
3599 ////////////////////////////////////////////////////////////////////////////////
3600 
3601 static bool areEqualTypes(const clang::TemplateArgument& tArg,
3602  llvm::SmallVectorImpl<clang::TemplateArgument>& preceedingTArgs,
3603  const clang::NamedDecl& tPar,
3604  const cling::Interpreter& interp,
3605  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt)
3606 {
3607  using namespace ROOT::TMetaUtils;
3608  using namespace clang;
3609 
3610  // Check if this is a type for security
3611  TemplateTypeParmDecl* ttpdPtr = const_cast<TemplateTypeParmDecl*>(llvm::dyn_cast<TemplateTypeParmDecl>(&tPar));
3612  if (!ttpdPtr) return false;
3613  if (!ttpdPtr->hasDefaultArgument()) return false; // we should not be here in this case, but we protect us.
3614 
3615  // Try the fast solution
3616  QualType tParQualType = ttpdPtr->getDefaultArgument();
3617  const QualType tArgQualType = tArg.getAsType();
3618 
3619  // Now the equality tests for non template specialisations.
3620 
3621  // The easy cases:
3622  // template <class T=double> class A; or
3623  // template <class T=A<float>> class B;
3624  if (tParQualType.getTypePtr() == tArgQualType.getTypePtr()) return true;
3625 
3626  // Here the difficulty comes. We have to check if the argument is equal to its
3627  // default. We can do that bootstrapping an argument which has the default value
3628  // based on the preceeding arguments.
3629  // Basically we ask sema to give us the value of the argument given the template
3630  // of behind the parameter and the all the arguments.
3631  // So:
3632 
3633  // Take the template out of the parameter
3634 
3635  const clang::ElaboratedType* etype
3636  = llvm::dyn_cast<clang::ElaboratedType>(tParQualType.getTypePtr());
3637  while (etype) {
3638  tParQualType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3639  etype = llvm::dyn_cast<clang::ElaboratedType>(tParQualType.getTypePtr());
3640  }
3641 
3642  const TemplateSpecializationType* tst =
3643  llvm::dyn_cast<TemplateSpecializationType>(tParQualType.getTypePtr());
3644 
3645  if(!tst) // nothing more to be tried. They are different indeed.
3646  return false;
3647 
3648  ClassTemplateSpecializationDecl* TSTdecl
3649  = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(tArgQualType->getAsCXXRecordDecl());
3650 
3651  if(!TSTdecl) // nothing more to be tried. They are different indeed.
3652  return false;
3653 
3654  TemplateDecl *Template = tst->getTemplateName().getAsTemplateDecl();
3655 
3656  // Take the template location
3657  SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3658 
3659  // Get the position of the "<" (LA) of the specializaion
3660  SourceLocation LAngleLoc = TSTdecl->getSourceRange().getBegin();
3661 
3662 
3663  // Enclose in a scope for the RAII
3664  bool isEqual=false;
3665  TemplateArgument newArg = tArg;
3666  {
3667  clang::Sema& S = interp.getCI()->getSema();
3668  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interp));
3669  clang::sema::HackForDefaultTemplateArg raii; // Hic sunt leones
3670  bool HasDefaultArgs;
3671  TemplateArgumentLoc defTArgLoc = S.SubstDefaultTemplateArgumentIfAvailable(Template,
3672  TemplateLoc,
3673  LAngleLoc,
3674  ttpdPtr,
3675  preceedingTArgs,
3676  HasDefaultArgs);
3677  // The substition can fail, in which case there would have been compilation
3678  // error printed on the screen.
3679  newArg = defTArgLoc.getArgument();
3680  if (newArg.isNull() ||
3681  newArg.getKind() != clang::TemplateArgument::Type) {
3682  ROOT::TMetaUtils::Error("areEqualTypes",
3683  "Template parameter substitution failed!");
3684  }
3685 
3686  ClassTemplateSpecializationDecl* nTSTdecl
3687  = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(newArg.getAsType()->getAsCXXRecordDecl());
3688 // std::cout << "nSTdecl is " << nTSTdecl << std::endl;
3689 
3690  isEqual = (nTSTdecl && nTSTdecl->getMostRecentDecl() == TSTdecl->getMostRecentDecl()) ||
3691  (tParQualType.getTypePtr() == newArg.getAsType().getTypePtr());
3692  }
3693 
3694 
3695  return isEqual;
3696 }
3697 
3698 
3699 ////////////////////////////////////////////////////////////////////////////////
3700 /// std::cout << "Are equal values?\n";
3701 
3702 static bool areEqualValues(const clang::TemplateArgument& tArg,
3703  const clang::NamedDecl& tPar)
3704 {
3705  using namespace clang;
3706  const NonTypeTemplateParmDecl* nttpdPtr = llvm::dyn_cast<NonTypeTemplateParmDecl>(&tPar);
3707  if (!nttpdPtr) return false;
3708  const NonTypeTemplateParmDecl& nttpd = *nttpdPtr;
3709 
3710  if (!nttpd.hasDefaultArgument())
3711  return false;
3712 
3713  // 64 bits wide and signed (non unsigned, that is why "false")
3714  llvm::APSInt defaultValueAPSInt(64, false);
3715  if (Expr* defArgExpr = nttpd.getDefaultArgument()) {
3716  const ASTContext& astCtxt = nttpdPtr->getASTContext();
3717  defArgExpr->isIntegerConstantExpr(defaultValueAPSInt, astCtxt);
3718  }
3719 
3720  const int value = tArg.getAsIntegral().getLimitedValue();
3721 
3722  // std::cout << (value == defaultValueAPSInt ? "yes!":"no") << std::endl;
3723  return value == defaultValueAPSInt;
3724 }
3725 
3726 ////////////////////////////////////////////////////////////////////////////////
3727 /// Check if this NamedDecl is a template parameter with a default argument.
3728 /// This is a single interface to treat both integral and type parameters.
3729 /// Returns true if this is the case, false otherwise
3730 
3731 static bool isTypeWithDefault(const clang::NamedDecl* nDecl)
3732 {
3733  using namespace clang;
3734  if (!nDecl) return false;
3735  if (const TemplateTypeParmDecl* ttpd = llvm::dyn_cast<TemplateTypeParmDecl>(nDecl))
3736  return ttpd->hasDefaultArgument();
3737  if (const NonTypeTemplateParmDecl* nttpd = llvm::dyn_cast<NonTypeTemplateParmDecl>(nDecl))
3738  return nttpd->hasDefaultArgument();
3739  return false;
3740 
3741 }
3742 
3743 static void KeepNParams(clang::QualType& normalizedType,
3744  const clang::QualType& vanillaType,
3745  const cling::Interpreter& interp,
3746  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt);
3747 
3748 // Returns true if normTArg might have changed.
3749 static bool RecurseKeepNParams(clang::TemplateArgument &normTArg,
3750  const clang::TemplateArgument &tArg,
3751  const cling::Interpreter& interp,
3752  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt,
3753  const clang::ASTContext& astCtxt)
3754 {
3755  using namespace ROOT::TMetaUtils;
3756  using namespace clang;
3757 
3758  // Once we know there is no more default parameter, we can run through to the end
3759  // and/or recurse in the template parameter packs.
3760 
3761  // If this is a type,
3762  // we need first of all to recurse: this argument may need to be manipulated
3763  if (tArg.getKind() == clang::TemplateArgument::Type) {
3764  QualType thisNormQualType = normTArg.getAsType();
3765  QualType thisArgQualType = tArg.getAsType();
3766  KeepNParams(thisNormQualType,
3767  thisArgQualType,
3768  interp,
3769  normCtxt);
3770  normTArg = TemplateArgument(thisNormQualType);
3771  return (thisNormQualType != thisArgQualType);
3772  } else if (normTArg.getKind() == clang::TemplateArgument::Pack) {
3773  assert( tArg.getKind() == clang::TemplateArgument::Pack );
3774 
3775  SmallVector<TemplateArgument, 2> desArgs;
3776  bool mightHaveChanged = true;
3777  for (auto I = normTArg.pack_begin(), E = normTArg.pack_end(),
3778  FI = tArg.pack_begin(), FE = tArg.pack_end();
3779  I != E && FI != FE; ++I, ++FI)
3780  {
3781  TemplateArgument pack_arg(*I);
3782  mightHaveChanged |= RecurseKeepNParams(pack_arg, *FI, interp, normCtxt, astCtxt);
3783  desArgs.push_back(pack_arg);
3784  }
3785  if (mightHaveChanged) {
3786  ASTContext &mutableCtx( const_cast<ASTContext&>(astCtxt) );
3787  normTArg = TemplateArgument::CreatePackCopy(mutableCtx, desArgs);
3788  }
3789  return mightHaveChanged;
3790  }
3791  return false;
3792 }
3793 
3794 
3795 ////////////////////////////////////////////////////////////////////////////////
3796 /// This function allows to manipulate the number of arguments in the type
3797 /// of a template specialisation.
3798 
3799 static void KeepNParams(clang::QualType& normalizedType,
3800  const clang::QualType& vanillaType,
3801  const cling::Interpreter& interp,
3802  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt)
3803 {
3804  using namespace ROOT::TMetaUtils;
3805  using namespace clang;
3806 
3807  // If this type has no template specialisation behind, we don't need to do
3808  // anything
3809  ClassTemplateSpecializationDecl* ctsd;
3810  ClassTemplateDecl* ctd;
3811  if (! QualType2Template(vanillaType, ctd, ctsd)) return ;
3812 
3813  // Even if this is a template, if we don't keep any argument, return
3814  const int nArgsToKeep = normCtxt.GetNargsToKeep(ctd);
3815 
3816  // Important in case of early return: we must restore the original qualtype
3817  QualType originalNormalizedType = normalizedType;
3818 
3819  const ASTContext& astCtxt = ctsd->getASTContext();
3820 
3821 
3822  // In case of name* we need to strip the pointer first, add the default and attach
3823  // the pointer once again.
3824  if (llvm::isa<clang::PointerType>(normalizedType.getTypePtr())) {
3825  // Get the qualifiers.
3826  clang::Qualifiers quals = normalizedType.getQualifiers();
3827  auto valNormalizedType = normalizedType->getPointeeType();
3828  KeepNParams(valNormalizedType,vanillaType, interp, normCtxt);
3829  normalizedType = astCtxt.getPointerType(valNormalizedType);
3830  // Add back the qualifiers.
3831  normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3832  return;
3833  }
3834 
3835  // In case of Int_t& we need to strip the pointer first, desugar and attach
3836  // the pointer once again.
3837  if (llvm::isa<clang::ReferenceType>(normalizedType.getTypePtr())) {
3838  // Get the qualifiers.
3839  bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(normalizedType.getTypePtr());
3840  clang::Qualifiers quals = normalizedType.getQualifiers();
3841  auto valNormType = normalizedType->getPointeeType();
3842  KeepNParams(valNormType, vanillaType, interp, normCtxt);
3843 
3844  // Add the r- or l- value reference type back to the desugared one
3845  if (isLValueRefTy)
3846  normalizedType = astCtxt.getLValueReferenceType(valNormType);
3847  else
3848  normalizedType = astCtxt.getRValueReferenceType(valNormType);
3849  // Add back the qualifiers.
3850  normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3851  return;
3852  }
3853 
3854  // Treat the Scope (factorise the code out to reuse it in AddDefaultParameters)
3855  bool prefix_changed = false;
3856  clang::NestedNameSpecifier* prefix = nullptr;
3857  clang::Qualifiers prefix_qualifiers = normalizedType.getLocalQualifiers();
3858  const clang::ElaboratedType* etype
3859  = llvm::dyn_cast<clang::ElaboratedType>(normalizedType.getTypePtr());
3860  if (etype) {
3861  // We have to also handle the prefix.
3862  // TODO: we ought to be running KeepNParams
3863  prefix = AddDefaultParametersNNS(astCtxt, etype->getQualifier(), interp, normCtxt);
3864  prefix_changed = prefix != etype->getQualifier();
3865  normalizedType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3866  }
3867 
3868  // The canonical decl does not necessarily have the template default arguments.
3869  // Need to walk through the redecl chain to find it (we know there will be no
3870  // inconsistencies, at least)
3871  const clang::ClassTemplateDecl* ctdWithDefaultArgs = ctd;
3872  for (const RedeclarableTemplateDecl* rd: ctdWithDefaultArgs->redecls()) {
3873  clang::TemplateParameterList* tpl = rd->getTemplateParameters();
3874  if (tpl->getMinRequiredArguments () < tpl->size()) {
3875  ctdWithDefaultArgs = llvm::dyn_cast<clang::ClassTemplateDecl>(rd);
3876  break;
3877  }
3878  }
3879 
3880  if (!ctdWithDefaultArgs) {
3881  Error("KeepNParams", "Not found template default arguments\n");
3882  normalizedType=originalNormalizedType;
3883  return;
3884  }
3885 
3886  TemplateParameterList* tParsPtr = ctdWithDefaultArgs->getTemplateParameters();
3887  const TemplateParameterList& tPars = *tParsPtr;
3888  const TemplateArgumentList& tArgs = ctsd->getTemplateArgs();
3889 
3890  // We extract the template name from the type
3891  TemplateName theTemplateName = ExtractTemplateNameFromQualType(normalizedType);
3892  if (theTemplateName.isNull()) {
3893  normalizedType=originalNormalizedType;
3894  return;
3895  }
3896 
3897  const TemplateSpecializationType* normalizedTst =
3898  llvm::dyn_cast<TemplateSpecializationType>(normalizedType.getTypePtr());
3899  if (!normalizedTst) {
3900  normalizedType=originalNormalizedType;
3901  return;
3902  }
3903 
3904  const clang::ClassTemplateSpecializationDecl* TSTdecl
3905  = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(normalizedType.getTypePtr()->getAsCXXRecordDecl());
3906  bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
3907 
3908  // Loop over the template parameters and arguments recursively.
3909  // We go down the two lanes: the one of template parameters (decls) and the
3910  // one of template arguments (QualTypes) in parallel. The former are a
3911  // property of the template, independent of its instantiations.
3912  // The latter are a property of the instance itself.
3913  llvm::SmallVector<TemplateArgument, 4> argsToKeep;
3914 
3915  const int nArgs = tArgs.size();
3916  const int nNormArgs = normalizedTst->getNumArgs();
3917 
3918  bool mightHaveChanged = false;
3919 
3920  // becomes true when a parameter has a value equal to its default
3921  for (int formal = 0, inst = 0; formal != nArgs; ++formal, ++inst) {
3922  const NamedDecl* tParPtr = tPars.getParam(formal);
3923  if (!tParPtr) {
3924  Error("KeepNParams", "The parameter number %s is null.\n", formal);
3925  continue;
3926  }
3927 
3928  // Stop if the normalized TemplateSpecializationType has less arguments than
3929  // the one index is pointing at.
3930  // We piggy back on the AddDefaultParameters routine basically.
3931  if (formal == nNormArgs || inst == nNormArgs) break;
3932 
3933  const TemplateArgument& tArg = tArgs.get(formal);
3934  TemplateArgument normTArg(normalizedTst->getArgs()[inst]);
3935 
3936  bool shouldKeepArg = nArgsToKeep < 0 || inst < nArgsToKeep;
3937  if (isStdDropDefault) shouldKeepArg = false;
3938 
3939  // Nothing to do here: either this parameter has no default, or we have to keep it.
3940  // FIXME: Temporary measure to get Atlas started with this.
3941  // We put a hard cut on the number of template arguments to keep, w/o checking if
3942  // they are non default. This makes this feature UNUSABLE for cases like std::vector,
3943  // where 2 different entities would have the same name if an allocator different from
3944  // the default one is by chance used.
3945  if (!isTypeWithDefault(tParPtr) || shouldKeepArg) {
3946  if ( tParPtr->isTemplateParameterPack() ) {
3947  // This is the last template parameter in the template declaration
3948  // but it is signaling that there can be an arbitrary number of arguments
3949  // in the template instance. So to avoid inadvertenly dropping those
3950  // arguments we just process all remaining argument and exit the main loop.
3951  for( ; inst != nNormArgs; ++inst) {
3952  normTArg = normalizedTst->getArgs()[inst];
3953  mightHaveChanged |= RecurseKeepNParams(normTArg, tArg, interp, normCtxt, astCtxt);
3954  argsToKeep.push_back(normTArg);
3955  }
3956  // Done.
3957  break;
3958  }
3959  mightHaveChanged |= RecurseKeepNParams(normTArg, tArg, interp, normCtxt, astCtxt);
3960  argsToKeep.push_back(normTArg);
3961  continue;
3962  } else {
3963  if (!isStdDropDefault) {
3964  // Here we should not break but rather check if the value is the default one.
3965  mightHaveChanged = true;
3966  break;
3967  }
3968  // For std, we want to check the default args values.
3969  }
3970 
3971  // Now, we keep it only if it not is equal to its default, expressed in the arg
3972  // Some gymnastic is needed to decide how to check for equality according to the
3973  // flavour of Type: templateType or Integer
3974  bool equal=false;
3975  auto argKind = tArg.getKind();
3976  if (argKind == clang::TemplateArgument::Type){
3977  // we need all the info
3978  equal = areEqualTypes(tArg, argsToKeep, *tParPtr, interp, normCtxt);
3979  } else if (argKind == clang::TemplateArgument::Integral){
3980  equal = areEqualValues(tArg, *tParPtr);
3981  }
3982  if (!equal) {
3983  mightHaveChanged |= RecurseKeepNParams(normTArg, tArg, interp, normCtxt, astCtxt);
3984  argsToKeep.push_back(normTArg);
3985  } else {
3986  mightHaveChanged = true;
3987  }
3988 
3989 
3990  } // of loop over parameters and arguments
3991 
3992  if (!prefix_changed && !mightHaveChanged) {
3993  normalizedType = originalNormalizedType;
3994  return;
3995  }
3996 
3997  // now, let's remanipulate our Qualtype
3998  if (mightHaveChanged) {
3999  Qualifiers qualifiers = normalizedType.getLocalQualifiers();
4000  normalizedType = astCtxt.getTemplateSpecializationType(theTemplateName,
4001  argsToKeep,
4002  normalizedType.getTypePtr()->getCanonicalTypeInternal());
4003  normalizedType = astCtxt.getQualifiedType(normalizedType, qualifiers);
4004  }
4005 
4006  // Here we have (prefix_changed==true || mightHaveChanged), in both case
4007  // we need to reconstruct the type.
4008  if (prefix) {
4009  normalizedType = astCtxt.getElaboratedType(clang::ETK_None,prefix,normalizedType);
4010  normalizedType = astCtxt.getQualifiedType(normalizedType,prefix_qualifiers);
4011  }
4012 
4013 }
4014 
4015 ////////////////////////////////////////////////////////////////////////////////
4016 /// Return the type normalized for ROOT,
4017 /// keeping only the ROOT opaque typedef (Double32_t, etc.) and
4018 /// adding default template argument for all types except those explicitly
4019 /// requested to be drop by the user.
4020 /// Default template for STL collections are not yet removed by this routine.
4021 
4022 clang::QualType ROOT::TMetaUtils::GetNormalizedType(const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
4023 {
4024  clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4025 
4026  // Modules can trigger deserialization.
4027  cling::Interpreter::PushTransactionRAII RAII(const_cast<cling::Interpreter*>(&interpreter));
4028  clang::QualType normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt, type, normCtxt.GetConfig(), true /* fully qualify */);
4029 
4030  // Readd missing default template parameters
4031  normalizedType = ROOT::TMetaUtils::AddDefaultParameters(normalizedType, interpreter, normCtxt);
4032 
4033  // Get the number of arguments to keep in case they are not default.
4034  KeepNParams(normalizedType,type,interpreter,normCtxt);
4035 
4036  return normalizedType;
4037 }
4038 
4039 ////////////////////////////////////////////////////////////////////////////////
4040 /// Return the type name normalized for ROOT,
4041 /// keeping only the ROOT opaque typedef (Double32_t, etc.) and
4042 /// adding default template argument for all types except the STL collections
4043 /// where we remove the default template argument if any.
4044 ///
4045 /// This routine might actually belong in the interpreter because
4046 /// cache the clang::Type might be intepreter specific.
4047 
4048 void ROOT::TMetaUtils::GetNormalizedName(std::string &norm_name, const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
4049 {
4050  if (type.isNull()) {
4051  norm_name = "";
4052  return;
4053  }
4054 
4055  clang::QualType normalizedType = GetNormalizedType(type,interpreter,normCtxt);
4056 
4057  clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
4058  clang::PrintingPolicy policy(ctxt.getPrintingPolicy());
4059  policy.SuppressTagKeyword = true; // Never get the class or struct keyword
4060  policy.SuppressScope = true; // Force the scope to be coming from a clang::ElaboratedType.
4061  policy.AnonymousTagLocations = false; // Do not extract file name + line number for anonymous types.
4062  // The scope suppression is required for getting rid of the anonymous part of the name of a class defined in an anonymous namespace.
4063  // This gives us more control vs not using the clang::ElaboratedType and relying on the Policy.SuppressUnwrittenScope which would
4064  // strip both the anonymous and the inline namespace names (and we probably do not want the later to be suppressed).
4065 
4066  std::string normalizedNameStep1;
4067 
4068  // getAsStringInternal can trigger deserialization
4069  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interpreter));
4070  normalizedType.getAsStringInternal(normalizedNameStep1,policy);
4071 
4072  // Still remove the std:: and default template argument for STL container and
4073  // normalize the location and amount of white spaces.
4076 
4077  // The result of this routine is by definition a fully qualified name. There is an implicit starting '::' at the beginning of the name.
4078  // Depending on how the user typed their code, in particular typedef declarations, we may end up with an explicit '::' being
4079  // part of the result string. For consistency, we must remove it.
4080  if (norm_name.length()>2 && norm_name[0]==':' && norm_name[1]==':') {
4081  norm_name.erase(0,2);
4082  }
4083 
4084 }
4085 
4086 ////////////////////////////////////////////////////////////////////////////////
4087 
4088 void ROOT::TMetaUtils::GetNormalizedName(std::string &norm_name,
4089  const clang::TypeDecl* typeDecl,
4090  const cling::Interpreter &interpreter)
4091 {
4092  ROOT::TMetaUtils::TNormalizedCtxt tNormCtxt(interpreter.getLookupHelper());
4093  const clang::Sema &sema = interpreter.getSema();
4094  clang::ASTContext& astCtxt = sema.getASTContext();
4095  clang::QualType qualType = astCtxt.getTypeDeclType(typeDecl);
4096 
4098  qualType,
4099  interpreter,
4100  tNormCtxt);
4101 }
4102 
4103 ////////////////////////////////////////////////////////////////////////////////
4104 std::pair<std::string,clang::QualType>
4105 ROOT::TMetaUtils::GetNameTypeForIO(const clang::QualType& thisType,
4106  const cling::Interpreter &interpreter,
4107  const TNormalizedCtxt &normCtxt,
4108  TClassEdit::EModType mode)
4109 {
4110  std::string thisTypeName;
4111  GetNormalizedName(thisTypeName, thisType, interpreter, normCtxt );
4112  bool hasChanged;
4113  auto thisTypeNameForIO = TClassEdit::GetNameForIO(thisTypeName, mode, &hasChanged);
4114  if (!hasChanged) return std::make_pair(thisTypeName,thisType);
4115 
4117  ROOT::TMetaUtils::Info("ROOT::TMetaUtils::GetTypeForIO",
4118  "Name changed from %s to %s\n", thisTypeName.c_str(), thisTypeNameForIO.c_str());
4119  }
4120 
4121  auto& lookupHelper = interpreter.getLookupHelper();
4122 
4123  const clang::Type* typePtrForIO;
4124  lookupHelper.findScope(thisTypeNameForIO,
4125  cling::LookupHelper::DiagSetting::NoDiagnostics,
4126  &typePtrForIO);
4127 
4128  // This should never happen
4129  if (!typePtrForIO) {
4130  ROOT::TMetaUtils::Fatal("ROOT::TMetaUtils::GetTypeForIO",
4131  "Type not found: %s.",thisTypeNameForIO.c_str());
4132  }
4133 
4134  clang::QualType typeForIO(typePtrForIO,0);
4135 
4136  // Check if this is a class. Indeed it could well be a POD
4137  if (!typeForIO->isRecordType()) {
4138  return std::make_pair(thisTypeNameForIO,typeForIO);
4139  }
4140 
4141  auto thisDeclForIO = typeForIO->getAsCXXRecordDecl();
4142  if (!thisDeclForIO) {
4143  ROOT::TMetaUtils::Error("ROOT::TMetaUtils::GetTypeForIO",
4144  "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());
4145  return std::make_pair(thisTypeName,thisType);
4146  }
4147 
4148  return std::make_pair(thisTypeNameForIO,typeForIO);
4149 }
4150 
4151 ////////////////////////////////////////////////////////////////////////////////
4152 
4153 clang::QualType ROOT::TMetaUtils::GetTypeForIO(const clang::QualType& thisType,
4154  const cling::Interpreter &interpreter,
4155  const TNormalizedCtxt &normCtxt,
4156  TClassEdit::EModType mode)
4157 {
4158  return GetNameTypeForIO(thisType, interpreter, normCtxt, mode).second;
4159 }
4160 
4161 ////////////////////////////////////////////////////////////////////////////////
4162 /// Return the dictionary file name for a module
4163 
4164 std::string ROOT::TMetaUtils::GetModuleFileName(const char* moduleName)
4165 {
4166  std::string dictFileName(moduleName);
4167  dictFileName += "_rdict.pcm";
4168  return dictFileName;
4169 }
4170 
4171 int dumpDeclForAssert(const clang::Decl& D, const char* commentStart) {
4172  llvm::errs() << llvm::StringRef(commentStart, 80) << '\n';
4173  D.dump();
4174  return 0;
4175 }
4176 
4177 ////////////////////////////////////////////////////////////////////////////////
4178 /// Returns the comment (// striped away), annotating declaration in a meaningful
4179 /// for ROOT IO way.
4180 /// Takes optional out parameter clang::SourceLocation returning the source
4181 /// location of the comment.
4182 ///
4183 /// CXXMethodDecls, FieldDecls and TagDecls are annotated.
4184 /// CXXMethodDecls declarations and FieldDecls are annotated as follows:
4185 /// Eg. void f(); // comment1
4186 /// int member; // comment2
4187 /// Inline definitions of CXXMethodDecls after the closing } \n. Eg:
4188 /// void f()
4189 /// {...} // comment3
4190 /// TagDecls are annotated in the end of the ClassDef macro. Eg.
4191 /// class MyClass {
4192 /// ...
4193 /// ClassDef(MyClass, 1) // comment4
4194 ///
4195 
4196 llvm::StringRef ROOT::TMetaUtils::GetComment(const clang::Decl &decl, clang::SourceLocation *loc)
4197 {
4198  clang::SourceManager& sourceManager = decl.getASTContext().getSourceManager();
4199  clang::SourceLocation sourceLocation = decl.getEndLoc();
4200 
4201  // If the location is a macro get the expansion location.
4202  sourceLocation = sourceManager.getExpansionRange(sourceLocation).getEnd();
4203  // FIXME: We should optimize this routine instead making it do the wrong thing
4204  // returning an empty comment if the decl came from the AST.
4205  // In order to do that we need to: check if the decl has an attribute and
4206  // return the attribute content (including walking the redecl chain) and if
4207  // this is not the case we should try finding it in the header file.
4208  // This will allow us to move the implementation of TCling*Info::Title() in
4209  // TClingDeclInfo.
4210  if (!decl.hasOwningModule() && sourceManager.isLoadedSourceLocation(sourceLocation)) {
4211  // Do not touch disk for nodes coming from the PCH.
4212  return "";
4213  }
4214 
4215  bool invalid;
4216  const char *commentStart = sourceManager.getCharacterData(sourceLocation, &invalid);
4217  if (invalid)
4218  return "";
4219 
4220  bool skipToSemi = true;
4221  if (const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(&decl)) {
4222  if (FD->isImplicit()) {
4223  // Compiler generated function.
4224  return "";
4225  }
4226  if (FD->isExplicitlyDefaulted() || FD->isDeletedAsWritten()) {
4227  // ctorOrFunc() = xyz; with commentStart pointing somewhere into
4228  // ctorOrFunc.
4229  // We have to skipToSemi
4230  } else if (FD->doesThisDeclarationHaveABody()) {
4231  // commentStart is at body's '}'
4232  // But we might end up e.g. at the ')' of a CPP macro
4233  assert((decl.getEndLoc() != sourceLocation || *commentStart == '}'
4234  || dumpDeclForAssert(*FD, commentStart))
4235  && "Expected macro or end of body at '}'");
4236  if (*commentStart) ++commentStart;
4237 
4238  // We might still have a ';'; skip the spaces and check.
4239  while (*commentStart && isspace(*commentStart)
4240  && *commentStart != '\n' && *commentStart != '\r') {
4241  ++commentStart;
4242  }
4243  if (*commentStart == ';') ++commentStart;
4244 
4245  skipToSemi = false;
4246  }
4247  } else if (const clang::EnumConstantDecl* ECD
4248  = clang::dyn_cast<clang::EnumConstantDecl>(&decl)) {
4249  // either "konstant = 12, //COMMENT" or "lastkonstant // COMMENT"
4250  if (ECD->getNextDeclInContext())
4251  while (*commentStart && *commentStart != ',' && *commentStart != '\r' && *commentStart != '\n')
4252  ++commentStart;
4253  // else commentStart already points to the end.
4254 
4255  skipToSemi = false;
4256  }
4257 
4258  if (skipToSemi) {
4259  while (*commentStart && *commentStart != ';' && *commentStart != '\r' && *commentStart != '\n')
4260  ++commentStart;
4261  if (*commentStart == ';') ++commentStart;
4262  }
4263 
4264  // Now skip the spaces until beginning of comments or EOL.
4265  while ( *commentStart && isspace(*commentStart)
4266  && *commentStart != '\n' && *commentStart != '\r') {
4267  ++commentStart;
4268  }
4269 
4270  if (commentStart[0] != '/' ||
4271  (commentStart[1] != '/' && commentStart[1] != '*')) {
4272  // not a comment
4273  return "";
4274  }
4275 
4276  // Treat by default c++ comments (+2) but also Doxygen comments (+4)
4277  // Int_t fPx; ///< Some doxygen comment for persistent data.
4278  // Int_t fPy; //!< Some doxygen comment for persistent data.
4279  // Int_t fPz; /*!< Some doxygen comment for persistent data. */
4280  // Int_t fPa; /**< Some doxygen comment for persistent data. */
4281  unsigned int skipChars = 2;
4282  if (commentStart[0] == '/' &&
4283  commentStart[1] == '/' &&
4284  (commentStart[2] == '/' || commentStart[2] == '!') &&
4285  commentStart[3] == '<') {
4286  skipChars = 4;
4287  } else if (commentStart[0] == '/' &&
4288  commentStart[1] == '*' &&
4289  (commentStart[2] == '*' || commentStart[2] == '!') &&
4290  commentStart[3] == '<') {
4291  skipChars = 4;
4292  }
4293 
4294  commentStart += skipChars;
4295 
4296  // Now skip the spaces after comment start until EOL.
4297  while ( *commentStart && isspace(*commentStart)
4298  && *commentStart != '\n' && *commentStart != '\r') {
4299  ++commentStart;
4300  }
4301  const char* commentEnd = commentStart;
4302  // Even for /* comments we only take the first line into account.
4303  while (*commentEnd && *commentEnd != '\n' && *commentEnd != '\r') {
4304  ++commentEnd;
4305  }
4306 
4307  // "Skip" (don't include) trailing space.
4308  // *commentEnd points behind comment end thus check commentEnd[-1]
4309  while (commentEnd > commentStart && isspace(commentEnd[-1])) {
4310  --commentEnd;
4311  }
4312 
4313  if (loc) {
4314  // Find the true beginning of a comment.
4315  unsigned offset = commentStart - sourceManager.getCharacterData(sourceLocation);
4316  *loc = sourceLocation.getLocWithOffset(offset - 1);
4317  }
4318 
4319  return llvm::StringRef(commentStart, commentEnd - commentStart);
4320 }
4321 
4322 ////////////////////////////////////////////////////////////////////////////////
4323 /// Return the class comment after the ClassDef:
4324 /// class MyClass {
4325 /// ...
4326 /// ClassDef(MyClass, 1) // class comment
4327 ///
4328 
4329 llvm::StringRef ROOT::TMetaUtils::GetClassComment(const clang::CXXRecordDecl &decl,
4330  clang::SourceLocation *loc,
4331  const cling::Interpreter &interpreter)
4332 {
4333  using namespace clang;
4334  SourceLocation commentSLoc;
4335  llvm::StringRef comment;
4336 
4337  Sema& sema = interpreter.getCI()->getSema();
4338 
4339  const Decl* DeclFileLineDecl
4340  = interpreter.getLookupHelper().findFunctionProto(&decl, "DeclFileLine", "",
4341  cling::LookupHelper::NoDiagnostics);
4342  if (!DeclFileLineDecl) return llvm::StringRef();
4343 
4344  // For now we allow only a special macro (ClassDef) to have meaningful comments
4345  SourceLocation maybeMacroLoc = DeclFileLineDecl->getLocation();
4346  bool isClassDefMacro = maybeMacroLoc.isMacroID() && sema.findMacroSpelling(maybeMacroLoc, "ClassDef");
4347  if (isClassDefMacro) {
4348  comment = ROOT::TMetaUtils::GetComment(*DeclFileLineDecl, &commentSLoc);
4349  if (comment.size()) {
4350  if (loc){
4351  *loc = commentSLoc;
4352  }
4353  return comment;
4354  }
4355  }
4356  return llvm::StringRef();
4357 }
4358 
4359 ////////////////////////////////////////////////////////////////////////////////
4360 /// Return the base/underlying type of a chain of array or pointers type.
4361 /// Does not yet support the array and pointer part being intermixed.
4362 
4364 {
4365  const clang::Type *rawtype = type.getTypePtr();
4366 
4367  // NOTE: We probably meant isa<clang::ElaboratedType>
4368  if (rawtype->isElaboratedTypeSpecifier() ) {
4369  rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4370  }
4371  if (rawtype->isArrayType()) {
4372  rawtype = type.getTypePtr()->getBaseElementTypeUnsafe ();
4373  }
4374  if (rawtype->isPointerType() || rawtype->isReferenceType() ) {
4375  //Get to the 'raw' type.
4376  clang::QualType pointee;
4377  while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
4378  {
4379  rawtype = pointee.getTypePtr();
4380 
4381  if (rawtype->isElaboratedTypeSpecifier() ) {
4382  rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4383  }
4384  if (rawtype->isArrayType()) {
4385  rawtype = rawtype->getBaseElementTypeUnsafe ();
4386  }
4387  }
4388  }
4389  if (rawtype->isArrayType()) {
4390  rawtype = rawtype->getBaseElementTypeUnsafe ();
4391  }
4392  return rawtype;
4393 }
4394 
4395 ////////////////////////////////////////////////////////////////////////////////
4396 /// Return true, if the decl is part of the std namespace.
4397 
4398 bool ROOT::TMetaUtils::IsStdClass(const clang::RecordDecl &cl)
4399 {
4401 }
4402 
4403 ////////////////////////////////////////////////////////////////////////////////
4404 /// Return true, if the decl is part of the std namespace and we want
4405 /// its default parameter dropped.
4406 
4407 bool ROOT::TMetaUtils::IsStdDropDefaultClass(const clang::RecordDecl &cl)
4408 {
4409  // Might need to reduce it to shared_ptr and STL collection.s
4411  static const char *names[] =
4412  { "shared_ptr", "__shared_ptr",
4413  "vector", "list", "deque", "map", "multimap", "set", "multiset", "bitset"};
4414  llvm::StringRef clname(cl.getName());
4415  for(auto &&name : names) {
4416  if (clname == name) return true;
4417  }
4418  }
4419  return false;
4420 }
4421 
4422 ////////////////////////////////////////////////////////////////////////////////
4423 /// This is a recursive function
4424 
4425 bool ROOT::TMetaUtils::MatchWithDeclOrAnyOfPrevious(const clang::CXXRecordDecl &cl,
4426  const clang::CXXRecordDecl &currentCl)
4427 {
4428  // We found it: let's return true
4429  if (&cl == &currentCl) return true;
4430 
4431  const clang::CXXRecordDecl* previous = currentCl.getPreviousDecl();
4432 
4433  // There is no previous decl, so we cannot possibly find it
4434  if (NULL == previous){
4435  return false;
4436  }
4437 
4438  // We try to find it in the previous
4439  return ROOT::TMetaUtils::MatchWithDeclOrAnyOfPrevious(cl, *previous);
4440 
4441 }
4442 
4443 //______________________________________________________________________________
4444 
4445 bool ROOT::TMetaUtils::IsOfType(const clang::CXXRecordDecl &cl, const std::string& typ, const cling::LookupHelper& lh)
4446 {
4447  // Return true if the decl is of type.
4448  // A proper hashtable for caching results would be the ideal solution
4449  // 1) Only one lookup per type
4450  // 2) No string comparison
4451  // We may use a map which becomes an unordered map if c++11 is enabled?
4452 
4453  const clang::CXXRecordDecl *thisDecl =
4454  llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(typ, cling::LookupHelper::WithDiagnostics));
4455 
4456  // this would be probably an assert given that this state is not reachable unless a mistake is somewhere
4457  if (! thisDecl){
4458  Error("IsOfType","Record decl of type %s not found in the AST.", typ.c_str());
4459  return false;
4460  }
4461 
4462  // Now loop on all previous decls to seek a match
4463  const clang::CXXRecordDecl *mostRecentDecl = thisDecl->getMostRecentDecl();
4464  bool matchFound = MatchWithDeclOrAnyOfPrevious (cl,*mostRecentDecl);
4465 
4466  return matchFound;
4467 }
4468 
4469 ////////////////////////////////////////////////////////////////////////////////
4470 /// type : type name: vector<list<classA,allocator>,allocator>
4471 /// result: 0 : not stl container
4472 /// abs(result): code of container 1=vector,2=list,3=deque,4=map
4473 /// 5=multimap,6=set,7=multiset
4474 
4475 ROOT::ESTLType ROOT::TMetaUtils::IsSTLCont(const clang::RecordDecl &cl)
4476 {
4477  // This routine could be enhanced to also support:
4478  //
4479  // testAlloc: if true, we test allocator, if it is not default result is negative
4480  // result: 0 : not stl container
4481  // abs(result): code of container 1=vector,2=list,3=deque,4=map
4482  // 5=multimap,6=set,7=multiset
4483  // positive val: we have a vector or list with default allocator to any depth
4484  // like vector<list<vector<int>>>
4485  // negative val: STL container other than vector or list, or non default allocator
4486  // For example: vector<deque<int>> has answer -1
4487 
4488  if (!IsStdClass(cl)) {
4489  auto *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(cl.getDeclContext());
4490  if (cl.getName() != "RVec" || nsDecl == nullptr || nsDecl->getName() != "VecOps")
4491  return ROOT::kNotSTL;
4492 
4493  auto *parentNsDecl = llvm::dyn_cast<clang::NamespaceDecl>(cl.getDeclContext()->getParent());
4494  if (parentNsDecl == nullptr || parentNsDecl->getName() != "ROOT")
4495  return ROOT::kNotSTL;
4496  }
4497 
4498  return STLKind(cl.getName());
4499 }
4500 
4502  using namespace clang;
4503  struct SearchTypedef: public TypeVisitor<SearchTypedef, bool> {
4504  bool VisitTypedefType(const TypedefType* TD) {
4505  return true;
4506  }
4507  bool VisitArrayType(const ArrayType* AT) {
4508  return Visit(AT->getElementType().getTypePtr());
4509  }
4510  bool VisitDecltypeType(const DecltypeType* DT) {
4511  return Visit(DT->getUnderlyingType().getTypePtr());
4512  }
4513  bool VisitPointerType(const PointerType* PT) {
4514  return Visit(PT->getPointeeType().getTypePtr());
4515  }
4516  bool VisitReferenceType(const ReferenceType* RT) {
4517  return Visit(RT->getPointeeType().getTypePtr());
4518  }
4519  bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType* STST) {
4520  return Visit(STST->getReplacementType().getTypePtr());
4521  }
4522  bool VisitTemplateSpecializationType(const TemplateSpecializationType* TST) {
4523  for (int I = 0, N = TST->getNumArgs(); I < N; ++I) {
4524  const TemplateArgument& TA = TST->getArg(I);
4525  if (TA.getKind() == TemplateArgument::Type
4526  && Visit(TA.getAsType().getTypePtr()))
4527  return true;
4528  }
4529  return false;
4530  }
4531  bool VisitTemplateTypeParmType(const TemplateTypeParmType* TTPT) {
4532  return false; // shrug...
4533  }
4534  bool VisitTypeOfType(const TypeOfType* TOT) {
4535  return TOT->getUnderlyingType().getTypePtr();
4536  }
4537  bool VisitElaboratedType(const ElaboratedType* ET) {
4538  NestedNameSpecifier* NNS = ET->getQualifier();
4539  while (NNS) {
4540  if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
4541  if (Visit(NNS->getAsType()))
4542  return true;
4543  }
4544  NNS = NNS->getPrefix();
4545  }
4546  return Visit(ET->getNamedType().getTypePtr());
4547  }
4548  };
4549 
4550  SearchTypedef ST;
4551  return ST.Visit(T);
4552 }
4553 
4554 ////////////////////////////////////////////////////////////////////////////////
4555 /// Check if 'input' or any of its template parameter was substituted when
4556 /// instantiating the class template instance and replace it with the
4557 /// partially sugared types we have from 'instance'.
4558 
4559 clang::QualType ROOT::TMetaUtils::ReSubstTemplateArg(clang::QualType input, const clang::Type *instance)
4560 {
4561  if (!instance) return input;
4562  // if there is no typedef in instance then there is nothing guiding any
4563  // template parameter typedef replacement.
4565  return input;
4566 
4567  using namespace llvm;
4568  using namespace clang;
4569  const clang::ASTContext &Ctxt = instance->getAsCXXRecordDecl()->getASTContext();
4570 
4571  // Treat scope (clang::ElaboratedType) if any.
4572  const clang::ElaboratedType* etype
4573  = llvm::dyn_cast<clang::ElaboratedType>(input.getTypePtr());
4574  if (etype) {
4575  // We have to also handle the prefix.
4576 
4577  clang::Qualifiers scope_qualifiers = input.getLocalQualifiers();
4578  assert(instance->getAsCXXRecordDecl()!=0 && "ReSubstTemplateArg only makes sense with a type representing a class.");
4579 
4580  clang::NestedNameSpecifier *scope = ReSubstTemplateArgNNS(Ctxt,etype->getQualifier(),instance);
4581  clang::QualType subTy = ReSubstTemplateArg(clang::QualType(etype->getNamedType().getTypePtr(),0),instance);
4582 
4583  if (scope) subTy = Ctxt.getElaboratedType(clang::ETK_None,scope,subTy);
4584  subTy = Ctxt.getQualifiedType(subTy,scope_qualifiers);
4585  return subTy;
4586  }
4587 
4588  QualType QT = input;
4589 
4590  // In case of Int_t* we need to strip the pointer first, ReSubst and attach
4591  // the pointer once again.
4592  if (isa<clang::PointerType>(QT.getTypePtr())) {
4593  // Get the qualifiers.
4594  Qualifiers quals = QT.getQualifiers();
4595  QualType nQT;
4596  nQT = ReSubstTemplateArg(QT->getPointeeType(),instance);
4597  if (nQT == QT->getPointeeType()) return QT;
4598 
4599  QT = Ctxt.getPointerType(nQT);
4600  // Add back the qualifiers.
4601  QT = Ctxt.getQualifiedType(QT, quals);
4602  return QT;
4603  }
4604 
4605  // In case of Int_t& we need to strip the pointer first, ReSubst and attach
4606  // the reference once again.
4607  if (isa<ReferenceType>(QT.getTypePtr())) {
4608  // Get the qualifiers.
4609  bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
4610  Qualifiers quals = QT.getQualifiers();
4611  QualType nQT;
4612  nQT = ReSubstTemplateArg(QT->getPointeeType(),instance);
4613  if (nQT == QT->getPointeeType()) return QT;
4614 
4615  // Add the r- or l-value reference type back to the desugared one.
4616  if (isLValueRefTy)
4617  QT = Ctxt.getLValueReferenceType(nQT);
4618  else
4619  QT = Ctxt.getRValueReferenceType(nQT);
4620  // Add back the qualifiers.
4621  QT = Ctxt.getQualifiedType(QT, quals);
4622  return QT;
4623  }
4624 
4625  // In case of Int_t[2] we need to strip the array first, ReSubst and attach
4626  // the array once again.
4627  if (isa<clang::ArrayType>(QT.getTypePtr())) {
4628  // Get the qualifiers.
4629  Qualifiers quals = QT.getQualifiers();
4630 
4631  if (const auto arr = dyn_cast<ConstantArrayType>(QT.getTypePtr())) {
4632  QualType newQT= ReSubstTemplateArg(arr->getElementType(),instance);
4633 
4634  if (newQT == arr->getElementType()) return QT;
4635  QT = Ctxt.getConstantArrayType (newQT,
4636  arr->getSize(),
4637  arr->getSizeModifier(),
4638  arr->getIndexTypeCVRQualifiers());
4639 
4640  } else if (const auto arr = dyn_cast<DependentSizedArrayType>(QT.getTypePtr())) {
4641  QualType newQT = ReSubstTemplateArg(arr->getElementType(),instance);
4642 
4643  if (newQT == QT) return QT;
4644  QT = Ctxt.getDependentSizedArrayType (newQT,
4645  arr->getSizeExpr(),
4646  arr->getSizeModifier(),
4647  arr->getIndexTypeCVRQualifiers(),
4648  arr->getBracketsRange());
4649 
4650  } else if (const auto arr = dyn_cast<IncompleteArrayType>(QT.getTypePtr())) {
4651  QualType newQT = ReSubstTemplateArg(arr->getElementType(),instance);
4652 
4653  if (newQT == arr->getElementType()) return QT;
4654  QT = Ctxt.getIncompleteArrayType (newQT,
4655  arr->getSizeModifier(),
4656  arr->getIndexTypeCVRQualifiers());
4657 
4658  } else if (const auto arr = dyn_cast<VariableArrayType>(QT.getTypePtr())) {
4659  QualType newQT = ReSubstTemplateArg(arr->getElementType(),instance);
4660 
4661  if (newQT == arr->getElementType()) return QT;
4662  QT = Ctxt.getVariableArrayType (newQT,
4663  arr->getSizeExpr(),
4664  arr->getSizeModifier(),
4665  arr->getIndexTypeCVRQualifiers(),
4666  arr->getBracketsRange());
4667  }
4668 
4669  // Add back the qualifiers.
4670  QT = Ctxt.getQualifiedType(QT, quals);
4671  return QT;
4672  }
4673 
4674  // If the instance is also an elaborated type, we need to skip
4675  etype = llvm::dyn_cast<clang::ElaboratedType>(instance);
4676  if (etype) {
4677  instance = etype->getNamedType().getTypePtr();
4678  if (!instance) return input;
4679  }
4680 
4681  const clang::TemplateSpecializationType* TST
4682  = llvm::dyn_cast<const clang::TemplateSpecializationType>(instance);
4683 
4684  if (!TST) return input;
4685 
4686  const clang::ClassTemplateSpecializationDecl* TSTdecl
4687  = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instance->getAsCXXRecordDecl());
4688 
4689  if (!TSTdecl) return input;
4690 
4691  const clang::SubstTemplateTypeParmType *substType
4692  = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(input.getTypePtr());
4693 
4694  if (substType) {
4695  // Make sure it got replaced from this template
4696  const clang::ClassTemplateDecl *replacedCtxt = 0;
4697 
4698  const clang::DeclContext *replacedDeclCtxt = substType->getReplacedParameter()->getDecl()->getDeclContext();
4699  const clang::CXXRecordDecl *decl = llvm::dyn_cast<clang::CXXRecordDecl>(replacedDeclCtxt);
4700  unsigned int index = substType->getReplacedParameter()->getIndex();
4701  if (decl) {
4702 
4703  if (decl->getKind() == clang::Decl::ClassTemplatePartialSpecialization) {
4704  const clang::ClassTemplatePartialSpecializationDecl *spec = llvm::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(decl);
4705 
4706  unsigned int depth = substType->getReplacedParameter()->getDepth();
4707 
4708  const TemplateArgument *instanceArgs = spec->getTemplateArgs().data();
4709  unsigned int instanceNArgs = spec->getTemplateArgs().size();
4710 
4711  // Search for the 'right' replacement.
4712 
4713  for(unsigned int A = 0; A < instanceNArgs; ++A) {
4714  if (instanceArgs[A].getKind() == clang::TemplateArgument::Type) {
4715  clang::QualType argQualType = instanceArgs[A].getAsType();
4716 
4717  const clang::TemplateTypeParmType *replacementType;
4718 
4719  replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(argQualType);
4720 
4721  if (!replacementType) {
4722  const clang::SubstTemplateTypeParmType *argType
4723  = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(argQualType);
4724  if (argType) {
4725  clang::QualType replacementQT = argType->getReplacementType();
4726  replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(replacementQT);
4727  }
4728  }
4729  if (replacementType &&
4730  depth == replacementType->getDepth() &&
4731  index == replacementType->getIndex() )
4732  {
4733  index = A;
4734  break;
4735  }
4736  }
4737  }
4738  replacedCtxt = spec->getSpecializedTemplate();
4739  } else {
4740  replacedCtxt = decl->getDescribedClassTemplate();
4741  }
4742  } else if (auto const declguide = llvm::dyn_cast<clang::CXXDeductionGuideDecl>(replacedDeclCtxt)) {
4743  replacedCtxt = llvm::dyn_cast<clang::ClassTemplateDecl>(declguide->getDeducedTemplate());
4744  } else if (auto const ctdecl = llvm::dyn_cast<clang::ClassTemplateDecl>(replacedDeclCtxt)) {
4745  replacedCtxt = ctdecl;
4746  } else {
4747  std::string astDump;
4748  llvm::raw_string_ostream ostream(astDump);
4749  instance->dump(ostream);
4750  ostream.flush();
4751  ROOT::TMetaUtils::Warning("ReSubstTemplateArg","Unexpected type of declaration context for template parameter: %s.\n\tThe responsible class is:\n\t%s\n",
4752  replacedDeclCtxt->getDeclKindName(), astDump.c_str());
4753  replacedCtxt = nullptr;
4754  }
4755 
4756  if ((replacedCtxt && replacedCtxt->getCanonicalDecl() == TSTdecl->getSpecializedTemplate()->getCanonicalDecl())
4757  || /* the following is likely just redundant */
4758  substType->getReplacedParameter()->getDecl()
4759  == TSTdecl->getSpecializedTemplate ()->getTemplateParameters()->getParam(index))
4760  {
4761  if ( index >= TST->getNumArgs() ) {
4762  // The argument replaced was a default template argument that is
4763  // being listed as part of the instance ...
4764  // so we probably don't really know how to spell it ... we would need to recreate it
4765  // (See AddDefaultParameters).
4766  return input;
4767  } else {
4768  return TST->getArg(index).getAsType();
4769  }
4770  }
4771  }
4772  // Maybe a class template instance, recurse and rebuild
4773  const clang::TemplateSpecializationType* inputTST
4774  = llvm::dyn_cast<const clang::TemplateSpecializationType>(input.getTypePtr());
4775  const clang::ASTContext& astCtxt = TSTdecl->getASTContext();
4776 
4777  if (inputTST) {
4778  bool mightHaveChanged = false;
4779  llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
4780  for(clang::TemplateSpecializationType::iterator I = inputTST->begin(), E = inputTST->end();
4781  I != E; ++I) {
4782  if (I->getKind() != clang::TemplateArgument::Type) {
4783  desArgs.push_back(*I);
4784  continue;
4785  }
4786 
4787  clang::QualType SubTy = I->getAsType();
4788  // Check if the type needs more desugaring and recurse.
4789  if (llvm::isa<clang::SubstTemplateTypeParmType>(SubTy)
4790  || llvm::isa<clang::TemplateSpecializationType>(SubTy)) {
4791  clang::QualType newSubTy = ReSubstTemplateArg(SubTy,instance);
4792  mightHaveChanged = SubTy != newSubTy;
4793  if (!newSubTy.isNull()) {
4794  desArgs.push_back(clang::TemplateArgument(newSubTy));
4795  }
4796  } else
4797  desArgs.push_back(*I);
4798  }
4799 
4800  // If desugaring happened allocate new type in the AST.
4801  if (mightHaveChanged) {
4802  clang::Qualifiers qualifiers = input.getLocalQualifiers();
4803  input = astCtxt.getTemplateSpecializationType(inputTST->getTemplateName(),
4804  desArgs,
4805  inputTST->getCanonicalTypeInternal());
4806  input = astCtxt.getQualifiedType(input, qualifiers);
4807  }
4808  }
4809 
4810  return input;
4811 }
4812 
4813 ////////////////////////////////////////////////////////////////////////////////
4814 /// Remove the last n template arguments from the name
4815 
4816 int ROOT::TMetaUtils::RemoveTemplateArgsFromName(std::string& name, unsigned int nArgsToRemove)
4817 {
4818  if ( nArgsToRemove == 0 || name == "")
4819  return 0;
4820 
4821  // We proceed from the right to the left, counting commas which are not
4822  // enclosed by < >.
4823  const unsigned int length = name.length();
4824  unsigned int cur=0; // let's start beyond the first > from the right
4825  unsigned int nArgsRemoved=0;
4826  unsigned int nBraces=0;
4827  char c='@';
4828  while (nArgsRemoved!=nArgsToRemove && cur<length){
4829  c = name[cur];
4830  if (c == '<') nBraces++;
4831  if (c == '>') nBraces--;
4832  if (c == ',' && nBraces==1 /*So we are not in a sub-template*/) nArgsRemoved++;
4833  cur++;
4834  }
4835  cur--;
4836  name = name.substr(0,cur)+">";
4837  return 0;
4838 
4839 }
4840 
4841 ////////////////////////////////////////////////////////////////////////////////
4842 /// Converts STL container name to number. vector -> 1, etc..
4843 
4845 {
4846  static const char *stls[] = //container names
4847  {"any","vector","list", "deque","map","multimap","set","multiset","bitset",
4848  "forward_list","unordered_set","unordered_multiset","unordered_map","unordered_multimap", "RVec", 0};
4849  static const ROOT::ESTLType values[] =
4860  };
4861  // kind of stl container
4862  for(int k=1;stls[k];k++) {if (type.equals(stls[k])) return values[k];}
4863  return ROOT::kNotSTL;
4864 }
4865 
4866 ////////////////////////////////////////////////////////////////////////////////
4867 
4868 const clang::TypedefNameDecl *ROOT::TMetaUtils::GetAnnotatedRedeclarable(const clang::TypedefNameDecl *TND)
4869 {
4870  if (!TND)
4871  return nullptr;
4872 
4873  TND = TND->getMostRecentDecl();
4874  while (TND && !(TND->hasAttrs()))
4875  TND = TND->getPreviousDecl();
4876 
4877  return TND;
4878 }
4879 
4880 ////////////////////////////////////////////////////////////////////////////////
4881 
4882 const clang::TagDecl *ROOT::TMetaUtils::GetAnnotatedRedeclarable(const clang::TagDecl *TD)
4883 {
4884  if (!TD)
4885  return nullptr;
4886 
4887  TD = TD->getMostRecentDecl();
4888  while (TD && !(TD->hasAttrs() && TD->isThisDeclarationADefinition()))
4889  TD = TD->getPreviousDecl();
4890 
4891  return TD;
4892 }
4893 
4894 ////////////////////////////////////////////////////////////////////////////////
4895 /// Extract the immediately outer namespace and then launch the recursion
4896 
4898  std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4899 {
4900  const clang::DeclContext* enclosingNamespaceDeclCtxt = decl.getDeclContext();
4901  if (!enclosingNamespaceDeclCtxt) return;
4902 
4903  const clang::NamespaceDecl* enclosingNamespace =
4904  clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4905  if (!enclosingNamespace) return;
4906 
4907  enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4908  enclosingNamespace->isInline()));
4909 
4910  ExtractCtxtEnclosingNameSpaces(*enclosingNamespace, enclosingNamespaces);
4911 
4912 }
4913 
4914 ////////////////////////////////////////////////////////////////////////////////
4915 /// Extract enclosing namespaces recursively
4916 
4917 void ROOT::TMetaUtils::ExtractCtxtEnclosingNameSpaces(const clang::DeclContext& ctxt,
4918  std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4919 {
4920  const clang::DeclContext* enclosingNamespaceDeclCtxt = ctxt.getParent ();
4921 
4922  // If no parent is found, nothing more to be done
4923  if (!enclosingNamespaceDeclCtxt) {
4924  return;
4925  }
4926 
4927  // Check if the parent is a namespace (it could be a class for example)
4928  // if not, nothing to be done here
4929  const clang::NamespaceDecl* enclosingNamespace = clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4930  if (!enclosingNamespace) return;
4931 
4932  // Add to the list of parent namespaces
4933  enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4934  enclosingNamespace->isInline()));
4935 
4936  // here the recursion
4937  ExtractEnclosingNameSpaces(*enclosingNamespace, enclosingNamespaces);
4938 }
4939 
4940 ////////////////////////////////////////////////////////////////////////////////
4941 /// Extract the names and types of containing scopes.
4942 /// Stop if a class is met and return its pointer.
4943 
4944 const clang::RecordDecl *ROOT::TMetaUtils::ExtractEnclosingScopes(const clang::Decl& decl,
4945  std::list<std::pair<std::string,unsigned int> >& enclosingSc)
4946 {
4947  const clang::DeclContext* enclosingDeclCtxt = decl.getDeclContext();
4948  if (!enclosingDeclCtxt) return nullptr;
4949 
4950  unsigned int scopeType;
4951 
4952  if (auto enclosingNamespacePtr =
4953  clang::dyn_cast<clang::NamespaceDecl>(enclosingDeclCtxt)){
4954  scopeType= enclosingNamespacePtr->isInline() ? 1 : 0; // inline or simple namespace
4955  enclosingSc.push_back(std::make_pair(enclosingNamespacePtr->getNameAsString(),scopeType));
4956  return ExtractEnclosingScopes(*enclosingNamespacePtr, enclosingSc);
4957  }
4958 
4959  if (auto enclosingClassPtr =
4960  clang::dyn_cast<clang::RecordDecl>(enclosingDeclCtxt)){
4961  return enclosingClassPtr;
4962  }
4963 
4964  return nullptr;
4965 }
4966 
4967 ////////////////////////////////////////////////////////////////////////////////
4968 /// Reimplementation of TSystem::ExpandPathName() that cannot be
4969 /// used from TMetaUtils.
4970 
4971 static void replaceEnvVars(const char* varname, std::string& txt)
4972 {
4973  std::string::size_type beginVar = 0;
4974  std::string::size_type endVar = 0;
4975  while ((beginVar = txt.find('$', beginVar)) != std::string::npos
4976  && beginVar + 1 < txt.length()) {
4977  std::string::size_type beginVarName = beginVar + 1;
4978  std::string::size_type endVarName = std::string::npos;
4979  if (txt[beginVarName] == '(') {
4980  // "$(VARNAME)" style.
4981  endVarName = txt.find(')', beginVarName);
4982  ++beginVarName;
4983  if (endVarName == std::string::npos) {
4984  ROOT::TMetaUtils::Error(0, "Missing ')' for '$(' in $%s at %s\n",
4985  varname, txt.c_str() + beginVar);
4986  return;
4987  }
4988  endVar = endVarName + 1;
4989  } else {
4990  // "$VARNAME/..." style.
4991  beginVarName = beginVar + 1;
4992  endVarName = beginVarName;
4993  while (isalnum(txt[endVarName]) || txt[endVarName] == '_')
4994  ++endVarName;
4995  endVar = endVarName;
4996  }
4997 
4998  const char* val = getenv(txt.substr(beginVarName,
4999  endVarName - beginVarName).c_str());
5000  if (!val) val = "";
5001 
5002  txt.replace(beginVar, endVar - beginVar, val);
5003  int lenval = strlen(val);
5004  int delta = lenval - (endVar - beginVar); // these many extra chars,
5005  endVar += delta; // advance the end marker accordingly.
5006 
5007  // Look for the next one
5008  beginVar = endVar + 1;
5009  }
5010 }
5011 
5012 ////////////////////////////////////////////////////////////////////////////////
5013 /// Organise the parameters for cling in order to guarantee relocatability
5014 /// It treats the gcc toolchain and the root include path
5015 /// FIXME: enables relocatability for experiments' framework headers until PCMs
5016 /// are available.
5017 
5018 void ROOT::TMetaUtils::SetPathsForRelocatability(std::vector<std::string>& clingArgs )
5019 {
5020  const char* envInclPath = getenv("ROOT_INCLUDE_PATH");
5021 
5022  if (!envInclPath)
5023  return;
5024  std::istringstream envInclPathsStream(envInclPath);
5025  std::string inclPath;
5026  while (std::getline(envInclPathsStream, inclPath, ':')) {
5027  // Can't use TSystem in here; re-implement TSystem::ExpandPathName().
5028  replaceEnvVars("ROOT_INCLUDE_PATH", inclPath);
5029  if (!inclPath.empty()) {
5030  clingArgs.push_back("-I");
5031  clingArgs.push_back(inclPath);
5032  }
5033  }
5034 }
5035 
5036 ////////////////////////////////////////////////////////////////////////////////
5037 
5038 void ROOT::TMetaUtils::ReplaceAll(std::string& str, const std::string& from, const std::string& to,bool recurse)
5039 {
5040  if(from.empty())
5041  return;
5042  size_t start_pos = 0;
5043  bool changed=true;
5044  while (changed){
5045  changed=false;
5046  start_pos = 0;
5047  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
5048  str.replace(start_pos, from.length(), to);
5049  start_pos += to.length();
5050  if (recurse) changed = true;
5051  }
5052  }
5053 }
5054 
5055 ////////////////////////////////////////////////////////////////////////////////
5056 /// Return the separator suitable for this platform.
5058 {
5060 }
5061 
5062 ////////////////////////////////////////////////////////////////////////////////
5063 
5064 bool ROOT::TMetaUtils::EndsWith(const std::string &theString, const std::string &theSubstring)
5065 {
5066  if (theString.size() < theSubstring.size()) return false;
5067  const unsigned int theSubstringSize = theSubstring.size();
5068  return 0 == theString.compare(theString.size() - theSubstringSize,
5069  theSubstringSize,
5070  theSubstring);
5071 }
5072 
5073 ////////////////////////////////////////////////////////////////////////////////
5074 
5075 bool ROOT::TMetaUtils::BeginsWith(const std::string &theString, const std::string &theSubstring)
5076 {
5077  if (theString.size() < theSubstring.size()) return false;
5078  const unsigned int theSubstringSize = theSubstring.size();
5079  return 0 == theString.compare(0,
5080  theSubstringSize,
5081  theSubstring);
5082 }
5083 
5084 
5085 
5086 ////////////////////////////////////////////////////////////////////////////////
5087 
5088 bool ROOT::TMetaUtils::IsLinkdefFile(const char *filename)
5089 {
5090  // Note, should change this into take llvm::StringRef.
5091 
5092  if ((strstr(filename, "LinkDef") || strstr(filename, "Linkdef") ||
5093  strstr(filename, "linkdef")) && strstr(filename, ".h")) {
5094  return true;
5095  }
5096  size_t len = strlen(filename);
5097  size_t linkdeflen = 9; /* strlen("linkdef.h") */
5098  if (len >= 9) {
5099  if (0 == strncasecmp(filename + (len - linkdeflen), "linkdef", linkdeflen - 2)
5100  && 0 == strcmp(filename + (len - 2), ".h")
5101  ) {
5102  return true;
5103  } else {
5104  return false;
5105  }
5106  } else {
5107  return false;
5108  }
5109 }
5110 
5111 ////////////////////////////////////////////////////////////////////////////////
5112 
5113 bool ROOT::TMetaUtils::IsHeaderName(const std::string &filename)
5114 {
5115  return llvm::sys::path::extension(filename) == ".h" ||
5116  llvm::sys::path::extension(filename) == ".hh" ||
5117  llvm::sys::path::extension(filename) == ".hpp" ||
5118  llvm::sys::path::extension(filename) == ".H" ||
5119  llvm::sys::path::extension(filename) == ".h++" ||
5120  llvm::sys::path::extension(filename) == "hxx" ||
5121  llvm::sys::path::extension(filename) == "Hxx" ||
5122  llvm::sys::path::extension(filename) == "HXX";
5123 }
5124 
5125 ////////////////////////////////////////////////////////////////////////////////
5126 
5127 const std::string ROOT::TMetaUtils::AST2SourceTools::Decls2FwdDecls(const std::vector<const clang::Decl *> &decls,
5128  cling::Interpreter::IgnoreFilesFunc_t ignoreFiles,
5129  const cling::Interpreter &interp,
5130  std::string *logs)
5131 {
5132  clang::Sema &sema = interp.getSema();
5133  cling::Transaction theTransaction(sema);
5134  std::set<clang::Decl *> addedDecls;
5135  for (auto decl : decls) {
5136  // again waiting for cling
5137  clang::Decl *ncDecl = const_cast<clang::Decl *>(decl);
5138  theTransaction.append(ncDecl);
5139  }
5140  std::string newFwdDecl;
5141  llvm::raw_string_ostream llvmOstr(newFwdDecl);
5142 
5143  std::string locallogs;
5144  llvm::raw_string_ostream llvmLogStr(locallogs);
5145  interp.forwardDeclare(theTransaction, sema.getPreprocessor(), sema.getASTContext(), llvmOstr, true,
5146  logs ? &llvmLogStr : nullptr, ignoreFiles);
5147  llvmOstr.flush();
5148  llvmLogStr.flush();
5149  if (logs)
5150  logs->swap(locallogs);
5151  return newFwdDecl;
5152 }
5153 
5154 ////////////////////////////////////////////////////////////////////////////////
5155 /// Take the namespaces which enclose the decl and put them around the
5156 /// definition string.
5157 /// For example, if the definition string is "myClass" which is enclosed by
5158 /// the namespaces ns1 and ns2, one would get:
5159 /// namespace ns2{ namespace ns1 { class myClass; } }
5160 
5162  std::string& defString)
5163 {
5164  auto rcd = EncloseInScopes(decl, defString);
5165  return rcd ? 1:0;
5166 }
5167 
5168 ////////////////////////////////////////////////////////////////////////////////
5169 /// Take the scopes which enclose the decl and put them around the
5170 /// definition string.
5171 /// If a class is encountered, bail out.
5172 
5173 const clang::RecordDecl* ROOT::TMetaUtils::AST2SourceTools::EncloseInScopes(const clang::Decl& decl,
5174  std::string& defString)
5175 {
5176  std::list<std::pair<std::string,unsigned int> > enclosingNamespaces;
5177  auto rcdPtr = ROOT::TMetaUtils::ExtractEnclosingScopes(decl,enclosingNamespaces);
5178 
5179  if (rcdPtr) return rcdPtr;
5180 
5181  // Check if we have enclosing namespaces
5182  static const std::string scopeType [] = {"namespace ", "inline namespace ", "class "};
5183 
5184  std::string scopeName;
5185  std::string scopeContent;
5186  unsigned int scopeIndex;
5187  for (auto const & encScope : enclosingNamespaces){
5188  scopeIndex = encScope.second;
5189  scopeName = encScope.first;
5190  scopeContent = " { " + defString + " }";
5191  defString = scopeType[scopeIndex] +
5192  scopeName +
5193  scopeContent;
5194  }
5195  return nullptr;
5196 }
5197 
5198 ////////////////////////////////////////////////////////////////////////////////
5199 /// Loop over the template parameters and build a string for template arguments
5200 /// using the fully qualified name
5201 /// There are different cases:
5202 /// Case 1: a simple template parameter
5203 /// E.g. template<typename T> class A;
5204 /// Case 2: a non-type: either an integer or an enum
5205 /// E.g. template<int I, Foo > class A; where Foo is enum Foo {red, blue};
5206 /// 2 sub cases here:
5207 /// SubCase 2.a: the parameter is an enum: bail out, cannot be treated.
5208 /// SubCase 2.b: use the fully qualified name
5209 /// Case 3: a TemplateTemplate argument
5210 /// E.g. template <template <typename> class T> class container { };
5211 
5213  const clang::TemplateParameterList& tmplParamList,
5214  const cling::Interpreter& interpreter)
5215 {
5216  templateArgs="<";
5217  for (auto prmIt = tmplParamList.begin();
5218  prmIt != tmplParamList.end(); prmIt++){
5219 
5220  if (prmIt != tmplParamList.begin())
5221  templateArgs += ", ";
5222 
5223  auto nDecl = *prmIt;
5224  std::string typeName;
5225 
5226  // Case 1
5227  if (llvm::isa<clang::TemplateTypeParmDecl>(nDecl)){
5228  typeName = "typename ";
5229  if (nDecl->isParameterPack())
5230  typeName += "... ";
5231  typeName += (*prmIt)->getNameAsString();
5232  }
5233  // Case 2
5234  else if (auto nttpd = llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(nDecl)){
5235  auto theType = nttpd->getType();
5236  // If this is an enum, use int as it is impossible to fwd declare and
5237  // this makes sense since it is not a type...
5238  if (theType.getAsString().find("enum") != std::string::npos){
5239  std::string astDump;
5240  llvm::raw_string_ostream ostream(astDump);
5241  nttpd->dump(ostream);
5242  ostream.flush();
5243  ROOT::TMetaUtils::Warning(0,"Forward declarations of templates with enums as template parameters. The responsible class is: %s\n", astDump.c_str());
5244  return 1;
5245  } else {
5247  theType,
5248  interpreter);
5249  }
5250  }
5251  // Case 3: TemplateTemplate argument
5252  else if (auto ttpd = llvm::dyn_cast<clang::TemplateTemplateParmDecl>(nDecl)){
5253  int retCode = FwdDeclFromTmplDecl(*ttpd,interpreter,typeName);
5254  if (retCode!=0){
5255  std::string astDump;
5256  llvm::raw_string_ostream ostream(astDump);
5257  ttpd->dump(ostream);
5258  ostream.flush();
5259  ROOT::TMetaUtils::Error(0,"Cannot reconstruct template template parameter forward declaration for %s\n", astDump.c_str());
5260  return 1;
5261  }
5262  }
5263 
5264  templateArgs += typeName;
5265  }
5266 
5267  templateArgs+=">";
5268  return 0;
5269 }
5270 
5271 ////////////////////////////////////////////////////////////////////////////////
5272 /// Convert a tmplt decl to its fwd decl
5273 
5274 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromTmplDecl(const clang::TemplateDecl& templDecl,
5275  const cling::Interpreter& interpreter,
5276  std::string& defString)
5277 {
5278  std::string templatePrefixString;
5279  auto tmplParamList= templDecl.getTemplateParameters();
5280  if (!tmplParamList){ // Should never happen
5281  Error(0,
5282  "Cannot extract template parameter list for %s",
5283  templDecl.getNameAsString().c_str());
5284  return 1;
5285  }
5286 
5287  int retCode = PrepareArgsForFwdDecl(templatePrefixString,*tmplParamList,interpreter);
5288  if (retCode!=0){
5289  Warning(0,
5290  "Problems with arguments for forward declaration of class %s\n",
5291  templDecl.getNameAsString().c_str());
5292  return retCode;
5293  }
5294  templatePrefixString = "template " + templatePrefixString + " ";
5295 
5296  defString = templatePrefixString + "class ";
5297  if (templDecl.isParameterPack())
5298  defString += "... ";
5299  defString += templDecl.getNameAsString();
5300  if (llvm::isa<clang::TemplateTemplateParmDecl>(&templDecl)) {
5301  // When fwd declaring the template template arg of
5302  // namespace N { template <template <class T> class C> class X; }
5303  // we don't need to put it into any namespace, and we want no trailing
5304  // ';'
5305  return 0;
5306  }
5307  defString += ';';
5308  return EncloseInNamespaces(templDecl, defString);
5309 }
5310 
5311 ////////////////////////////////////////////////////////////////////////////////
5312 
5313 static int TreatSingleTemplateArg(const clang::TemplateArgument& arg,
5314  std::string& argFwdDecl,
5315  const cling::Interpreter& interpreter,
5316  bool acceptStl=false)
5317 {
5318  using namespace ROOT::TMetaUtils::AST2SourceTools;
5319 
5320  // We do nothing in presence of ints, bools, templates.
5321  // We should probably in presence of templates though...
5322  if (clang::TemplateArgument::Type != arg.getKind()) return 0;
5323 
5324  auto argQualType = arg.getAsType();
5325 
5326  // Recursively remove all *
5327  while (llvm::isa<clang::PointerType>(argQualType.getTypePtr())) argQualType = argQualType->getPointeeType();
5328 
5329  auto argTypePtr = argQualType.getTypePtr();
5330 
5331  // Bail out on enums
5332  if (llvm::isa<clang::EnumType>(argTypePtr)){
5333  return 1;
5334  }
5335 
5336  // If this is a built-in, just return: fwd decl not necessary.
5337  if (llvm::isa<clang::BuiltinType>(argTypePtr)){
5338  return 0;
5339  }
5340 
5341  // Treat typedefs which are arguments
5342  if (auto tdTypePtr = llvm::dyn_cast<clang::TypedefType>(argTypePtr)) {
5343  FwdDeclFromTypeDefNameDecl(*tdTypePtr->getDecl(), interpreter, argFwdDecl);
5344  return 0;
5345  }
5346 
5347  if (auto argRecTypePtr = llvm::dyn_cast<clang::RecordType>(argTypePtr)){
5348  // Now we cannot but have a RecordType
5349  if (auto argRecDeclPtr = argRecTypePtr->getDecl()){
5350  FwdDeclFromRcdDecl(*argRecDeclPtr,interpreter,argFwdDecl,acceptStl);
5351  }
5352  return 0;
5353  }
5354 
5355  return 1;
5356 }
5357 
5358 ////////////////////////////////////////////////////////////////////////////////
5359 /// Convert a tmplt decl to its fwd decl
5360 
5361 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclIfTmplSpec(const clang::RecordDecl& recordDecl,
5362  const cling::Interpreter& interpreter,
5363  std::string& defString,
5364  const std::string &normalizedName)
5365 {
5366  // If this is an explicit specialization, inject it into cling, too, such that it can have
5367  // externalLexicalStorage, see TCling.cxx's ExtVisibleStorageAdder::VisitClassTemplateSpecializationDecl.
5368  if (auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)) {
5369  if (const auto *specDef = tmplSpecDeclPtr->getDefinition()) {
5370  if (specDef->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization)
5371  return 0;
5372  // normalizedName contains scope, no need to enclose in namespace!
5374  std::cout << " Forward declaring template spec " << normalizedName << ":\n";
5375  for (auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()) {
5376  std::string argFwdDecl;
5377  int retCode = TreatSingleTemplateArg(arg, argFwdDecl, interpreter, /*acceptStl=*/false);
5379  std::cout << " o Template argument ";
5380  if (retCode == 0) {
5381  std::cout << "successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5382  } else {
5383  std::cout << "could not be treated. Abort fwd declaration generation.\n";
5384  }
5385  }
5386 
5387  if (retCode != 0) { // A sign we must bail out
5388  return retCode;
5389  }
5390  defString += argFwdDecl + '\n';
5391  }
5392  defString += "template <> class " + normalizedName + ';';
5393  return 0;
5394  }
5395  }
5396 
5397  return 0;
5398 }
5399 
5400 ////////////////////////////////////////////////////////////////////////////////
5401 /// Convert a rcd decl to its fwd decl
5402 /// If this is a template specialisation, treat in the proper way.
5403 /// If it is contained in a class, just fwd declare the class.
5404 
5405 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromRcdDecl(const clang::RecordDecl& recordDecl,
5406  const cling::Interpreter& interpreter,
5407  std::string& defString,
5408  bool acceptStl)
5409 {
5410  // Do not fwd declare the templates in the stl.
5411  if (ROOT::TMetaUtils::IsStdClass(recordDecl) && !acceptStl)
5412  return 0;
5413 
5414  // Do not fwd declare unnamed decls.
5415  if (!recordDecl.getIdentifier())
5416  return 0;
5417 
5418  // We may need to fwd declare the arguments of the template
5419  std::string argsFwdDecl;
5420 
5421  if (auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)){
5422  std::string argFwdDecl;
5424  std::cout << "Class " << recordDecl.getNameAsString()
5425  << " is a template specialisation. Treating its arguments.\n";
5426  for(auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()){
5427  int retCode = TreatSingleTemplateArg(arg, argFwdDecl, interpreter, acceptStl);
5429  std::cout << " o Template argument ";
5430  if (retCode==0){
5431  std::cout << "successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5432  } else {
5433  std::cout << "could not be treated. Abort fwd declaration generation.\n";
5434  }
5435  }
5436 
5437  if (retCode!=0){ // A sign we must bail out
5438  return retCode;
5439  }
5440  argsFwdDecl+=argFwdDecl;
5441  }
5442 
5443  if (acceptStl){
5444  defString=argsFwdDecl;
5445  return 0;
5446  }
5447 
5448  int retCode=0;
5449  if (auto tmplDeclPtr = tmplSpecDeclPtr->getSpecializedTemplate()){
5450  retCode = FwdDeclFromTmplDecl(*tmplDeclPtr,interpreter,defString);
5451  }
5452  defString = argsFwdDecl + "\n" + defString;
5453  return retCode;
5454 
5455  }
5456 
5457  defString = "class " + recordDecl.getNameAsString() + ";";
5458  const clang::RecordDecl* rcd = EncloseInScopes(recordDecl, defString);
5459 
5460  if (rcd){
5461  FwdDeclFromRcdDecl(*rcd, interpreter,defString);
5462  }
5463  // Add a \n here to avoid long lines which contain duplications, for example (from MathCore):
5464  // namespace ROOT { namespace Math { class IBaseFunctionMultiDim; } }namespace ROOT { namespace Fit { template <typename FunType> class Chi2FCN; } }
5465  // namespace ROOT { namespace Math { class IGradientFunctionMultiDim; } }namespace ROOT { namespace Fit { template <typename FunType> class Chi2FCN; } }
5466  defString = argsFwdDecl + "\n" + defString;
5467 
5468  return 0;
5469 }
5470 
5471 ////////////////////////////////////////////////////////////////////////////////
5472 /// Extract "forward declaration" of a typedef.
5473 /// If the typedef is contained in a class, just fwd declare the class.
5474 /// If not, fwd declare the typedef and all the dependent typedefs and types if necessary.
5475 
5476 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromTypeDefNameDecl(const clang::TypedefNameDecl& tdnDecl,
5477  const cling::Interpreter& interpreter,
5478  std::string& fwdDeclString,
5479  std::unordered_set<std::string>* fwdDeclSetPtr)
5480 {
5481  std::string buffer = tdnDecl.getNameAsString();
5482  std::string underlyingName;
5483  auto underlyingType = tdnDecl.getUnderlyingType().getCanonicalType();
5484  if (const clang::TagType* TT
5485  = llvm::dyn_cast<clang::TagType>(underlyingType.getTypePtr())) {
5486  if (clang::NamedDecl* ND = TT->getDecl()) {
5487  if (!ND->getIdentifier()) {
5488  // No fwd decl for unnamed underlying entities.
5489  return 0;
5490  }
5491  }
5492  }
5493 
5494  TNormalizedCtxt nCtxt(interpreter.getLookupHelper());
5495  ROOT::TMetaUtils::GetNormalizedName(underlyingName,
5496  underlyingType,
5497  interpreter,
5498  nCtxt);
5499 
5500  // Heuristic: avoid entities like myclass<myType1, myType2::xyz>
5501  if (underlyingName.find(">::") != std::string::npos)
5502  return 0;
5503 
5504  buffer="typedef "+underlyingName+" "+buffer+";";
5505  const clang::RecordDecl* rcd=EncloseInScopes(tdnDecl,buffer);
5506  if (rcd) {
5507  // We do not need the whole series of scopes, just the class.
5508  // It is enough to trigger an uncomplete type autoload/parse callback
5509  // for example: MyClass::blabla::otherNs::myTypedef
5510  return FwdDeclFromRcdDecl(*rcd, interpreter,fwdDeclString,fwdDeclSetPtr);
5511  }
5512 
5513  // Start Recursion if the underlying type is a TypedefNameDecl
5514  // Note: the simple cast w/o the getSingleStepDesugaredType call
5515  // does not work in case the typedef is in a namespace.
5516  auto& ctxt = tdnDecl.getASTContext();
5517  auto immediatelyUnderlyingType = underlyingType.getSingleStepDesugaredType(ctxt);
5518 
5519  if (auto underlyingTdnTypePtr = llvm::dyn_cast<clang::TypedefType>(immediatelyUnderlyingType.getTypePtr())){
5520  std::string tdnFwdDecl;
5521  auto underlyingTdnDeclPtr = underlyingTdnTypePtr->getDecl();
5522  FwdDeclFromTypeDefNameDecl(*underlyingTdnDeclPtr,
5523  interpreter,
5524  tdnFwdDecl,
5525  fwdDeclSetPtr);
5526  if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(tdnFwdDecl).second)
5527  fwdDeclString+=tdnFwdDecl;
5528  } else if (auto CXXRcdDeclPtr = immediatelyUnderlyingType->getAsCXXRecordDecl()){
5529  std::string classFwdDecl;
5531  std::cout << "Typedef " << tdnDecl.getNameAsString() << " hides a class: "
5532  << CXXRcdDeclPtr->getNameAsString() << std::endl;
5533  int retCode = FwdDeclFromRcdDecl(*CXXRcdDeclPtr,
5534  interpreter,
5535  classFwdDecl,
5536  true /* acceptStl*/);
5537  if (retCode!=0){ // bail out
5538  return 0;
5539  }
5540 
5541  if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(classFwdDecl).second)
5542  fwdDeclString+=classFwdDecl;
5543  }
5544 
5545  fwdDeclString+=buffer;
5546 
5547  return 0;
5548 }
5549 
5550 ////////////////////////////////////////////////////////////////////////////////
5551 /// Get the default value as string.
5552 /// Limited at the moment to:
5553 /// - Integers
5554 /// - Booleans
5555 
5556 int ROOT::TMetaUtils::AST2SourceTools::GetDefArg(const clang::ParmVarDecl& par,
5557  std::string& valAsString,
5558  const clang::PrintingPolicy& ppolicy)
5559 {
5560  auto defArgExprPtr = par.getDefaultArg();
5561  auto& ctxt = par.getASTContext();
5562  if(!defArgExprPtr->isEvaluatable(ctxt)){
5563  return -1;
5564  }
5565 
5566  auto defArgType = par.getType();
5567 
5568  // The value is a boolean
5569  if (defArgType->isBooleanType()){
5570  bool result;
5571  defArgExprPtr->EvaluateAsBooleanCondition (result,ctxt);
5572  valAsString=std::to_string(result);
5573  return 0;
5574  }
5575 
5576  // The value is an integer
5577  if (defArgType->isIntegerType()){
5578  clang::Expr::EvalResult evalResult;
5579  defArgExprPtr->EvaluateAsInt(evalResult, ctxt);
5580  llvm::APSInt result = evalResult.Val.getInt();
5581  auto uintVal = *result.getRawData();
5582  if (result.isNegative()){
5583  long long int intVal=uintVal*-1;
5584  valAsString=std::to_string(intVal);
5585  } else {
5586  valAsString=std::to_string(uintVal);
5587  }
5588 
5589  return 0;
5590  }
5591 
5592  // The value is something else. We go for the generalised printer
5593  llvm::raw_string_ostream rso(valAsString);
5594  defArgExprPtr->printPretty(rso,nullptr,ppolicy);
5595  valAsString = rso.str();
5596  // We can be in presence of a string. Let's escape the characters properly.
5597  ROOT::TMetaUtils::ReplaceAll(valAsString,"\\\"","__TEMP__VAL__");
5598  ROOT::TMetaUtils::ReplaceAll(valAsString,"\"","\\\"");
5599  ROOT::TMetaUtils::ReplaceAll(valAsString,"__TEMP__VAL__","\\\"");
5600 
5601  return 0;
5602 }
5603 
ROOT::TMetaUtils::RConstructorType::GetType
const clang::CXXRecordDecl * GetType() const
Definition: TClingUtils.cxx:1177
c
#define c(i)
Definition: RSha256.hxx:101
ROOT::TMetaUtils::IsSTLContainer
int IsSTLContainer(const AnnotatedRecordDecl &annotated)
Is this an STL container.
Definition: TClingUtils.cxx:2652
ROOT::TMetaUtils::propNames::separator
static const std::string separator("@@@")
m
auto * m
Definition: textangle.C:8
ROOT::TMetaUtils::TClingLookupHelper::IsAlreadyPartiallyDesugaredName
virtual bool IsAlreadyPartiallyDesugaredName(const std::string &nondef, const std::string &nameLong)
Definition: TClingUtils.cxx:577
ROOT::TMetaUtils::AnnotatedRecordDecl::fRequestNoStreamer
bool fRequestNoStreamer
Definition: TClingUtils.h:201
GetMethodWithProto
const clang::CXXMethodDecl * GetMethodWithProto(const clang::Decl *cinfo, const char *method, const char *proto, const cling::Interpreter &interp, bool diagnose)
Definition: TClingUtils.cxx:1147
ROOT::TMetaUtils::GetCppName
void GetCppName(std::string &output, const char *input)
Return (in the argument 'output') a mangled version of the C++ symbol/type (pass as 'input') that can...
Definition: TClingUtils.cxx:3281
ROOT::kSTLdeque
@ kSTLdeque
Definition: ESTLType.h:32
ROOT::TMetaUtils::HasCustomOperatorNewPlacement
bool HasCustomOperatorNewPlacement(char const *, clang::RecordDecl const &, const cling::Interpreter &)
return true if we can find a custom operator new with placement
Definition: TClingUtils.cxx:2311
llvm
Definition: TString.h:850
ROOT::TMetaUtils::propNames::ioname
static const std::string ioname("ioname")
ROOT::TMetaUtils::AnnotatedRecordDecl::fRuleIndex
long fRuleIndex
Definition: TClingUtils.h:195
ROOT::TMetaUtils::TNormalizedCtxtImpl::Config_t
TNormalizedCtxt::Config_t Config_t
Definition: TClingUtils.cxx:86
ROOT::kSTLvector
@ kSTLvector
Definition: ESTLType.h:30
ROOT::TMetaUtils::TNormalizedCtxt::GetNargsToKeep
int GetNargsToKeep(const clang::ClassTemplateDecl *templ) const
Definition: TClingUtils.cxx:355
ROOT::kSTLset
@ kSTLset
Definition: ESTLType.h:35
IsTemplate
bool IsTemplate(const clang::Decl &cl)
Definition: TClingUtils.cxx:762
tt
auto * tt
Definition: textangle.C:16
ROOT::TMetaUtils::AnnotatedRecordDecl::fRequestedName
std::string fRequestedName
Definition: TClingUtils.h:197
ROOT::TMetaUtils::GetUnderlyingType
const clang::Type * GetUnderlyingType(clang::QualType type)
Return the base/underlying type of a chain of array or pointers type.
Definition: TClingUtils.cxx:4363
ROOT::kSTLunorderedmultimap
@ kSTLunorderedmultimap
Definition: ESTLType.h:45
ROOT::kSTLbitset
@ kSTLbitset
Definition: ESTLType.h:37
ROOT::TMetaUtils::IsStreamableObject
bool IsStreamableObject(const clang::FieldDecl &m, const cling::Interpreter &interp)
Definition: TClingUtils.cxx:2769
Version_t
short Version_t
Definition: RtypesCore.h:65
ROOT::TMetaUtils::HasIOConstructor
bool HasIOConstructor(clang::CXXRecordDecl const *, std::string &, const RConstructorTypes &, const cling::Interpreter &)
return true if we can find an constructor calleable without any arguments or with one the IOCtor spec...
Definition: TClingUtils.cxx:1185
TClassEdit::GetNameForIO
std::string GetNameForIO(const std::string &templateInstanceName, TClassEdit::EModType mode=TClassEdit::kNone, bool *hasChanged=nullptr)
Definition: TClassEdit.cxx:2075
Warning
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition: TError.cxx:231
ROOT::TMetaUtils::AnnotatedRecordDecl::fNormalizedName
std::string fNormalizedName
Definition: TClingUtils.h:198
ROOT::TMetaUtils::AnnotatedRecordDecl::RequestStreamerInfo
bool RequestStreamerInfo() const
Definition: TClingUtils.h:272
ROOT::TMetaUtils::ReplaceAll
void ReplaceAll(std::string &str, const std::string &from, const std::string &to, bool recurse=false)
Definition: TClingUtils.cxx:5038
dest
#define dest(otri, vertexptr)
Definition: triangle.c:1041
ROOT::TMetaUtils::GetLineNumber
long GetLineNumber(clang::Decl const *)
It looks like the template specialization decl actually contains less information on the location of ...
Definition: TClingUtils.cxx:1566
ROOT::TMetaUtils::AST2SourceTools::PrepareArgsForFwdDecl
int PrepareArgsForFwdDecl(std::string &templateArgs, const clang::TemplateParameterList &tmplParamList, const cling::Interpreter &interpreter)
Loop over the template parameters and build a string for template arguments using the fully qualified...
Definition: TClingUtils.cxx:5212
ROOT::TMetaUtils::Warning
void Warning(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:819
ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromRcdDecl
int FwdDeclFromRcdDecl(const clang::RecordDecl &recordDecl, const cling::Interpreter &interpreter, std::string &defString, bool acceptStl=false)
Convert a rcd decl to its fwd decl If this is a template specialisation, treat in the proper way.
Definition: TClingUtils.cxx:5405
ROOT::TMetaUtils::TClingLookupHelper::IsDeclaredScope
virtual bool IsDeclaredScope(const std::string &base, bool &isInlined)
Definition: TClingUtils.cxx:593
RStl.h
ROOT::TMetaUtils::AST2SourceTools::EncloseInScopes
const clang::RecordDecl * EncloseInScopes(const clang::Decl &decl, std::string &defString)
Take the scopes which enclose the decl and put them around the definition string.
Definition: TClingUtils.cxx:5173
ROOT::TMetaUtils::AnnotatedRecordDecl
Definition: TClingUtils.h:191
ROOT::TMetaUtils::GetNormalizedType
clang::QualType GetNormalizedType(const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t,...
Definition: TClingUtils.cxx:4022
ROOT::TMetaUtils::TNormalizedCtxtImpl::GetNargsToKeep
int GetNargsToKeep(const clang::ClassTemplateDecl *templ) const
Get from the map the number of arguments to keep.
Definition: TClingUtils.cxx:324
ROOT::TMetaUtils::AST2SourceTools
Definition: TClingUtils.h:853
ROOT::TMetaUtils::QualType2ClassTemplateDecl
clang::ClassTemplateDecl * QualType2ClassTemplateDecl(const clang::QualType &qt)
Extract from a qualtype the class template if this makes sense.
Definition: TClingUtils.cxx:3566
ROOT::TMetaUtils::TClingLookupHelper::fAutoParse
AutoParse_t fAutoParse
Definition: TClingUtils.h:169
ROOT::kSTLunorderedmultiset
@ kSTLunorderedmultiset
Definition: ESTLType.h:43
ROOT::kNotSTL
@ kNotSTL
Definition: ESTLType.h:29
TA
Definition: TStructViewer.cxx:24
ROOT::TMetaUtils::AnnotatedRecordDecl::fDemangledTypeInfo
std::string fDemangledTypeInfo
Definition: TClingUtils.h:199
ROOT::TMetaUtils::AnnotatedRecordDecl::GetRequestedName
const char * GetRequestedName() const
Definition: TClingUtils.h:268
ROOT::TMetaUtils::HasDirectoryAutoAdd
bool HasDirectoryAutoAdd(clang::CXXRecordDecl const *, const cling::Interpreter &)
Return true if the class has a method DirectoryAutoAdd(TDirectory *)
Definition: TClingUtils.cxx:1268
ROOT::WriteReadRawRuleFunc
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"...
Definition: RConversionRuleParser.cxx:694
TClassEdit::kLong64
@ kLong64
Definition: TClassEdit.h:84
ROOT::TMetaUtils::ShortTypeName
const char * ShortTypeName(const char *typeDesc)
Return the absolute type of typeDesc.
Definition: TClingUtils.cxx:2737
ROOT::kSTLend
@ kSTLend
Definition: ESTLType.h:47
TClassEdit::IsStdClass
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
Definition: TClassEdit.cxx:1401
ROOT::TMetaUtils::HasCustomOperatorNewArrayPlacement
bool HasCustomOperatorNewArrayPlacement(clang::RecordDecl const &, const cling::Interpreter &interp)
return true if we can find a custom operator new with placement
Definition: TClingUtils.cxx:2399
ROOT::TMetaUtils::NeedDestructor
bool NeedDestructor(clang::CXXRecordDecl const *, const cling::Interpreter &)
Definition: TClingUtils.cxx:1231
ROOT::gReadRawRules
R__EXTERN SchemaRuleClassMap_t gReadRawRules
Definition: RConversionRuleParser.h:25
ROOT::TMetaUtils::ReSubstTemplateArg
clang::QualType ReSubstTemplateArg(clang::QualType input, const clang::Type *instance)
Check if 'input' or any of its template parameter was substituted when instantiating the class templa...
Definition: TClingUtils.cxx:4559
ROOT::MembersTypeMap_t
std::map< std::string, ROOT::Internal::TSchemaType > MembersTypeMap_t
Definition: RConversionRuleParser.h:27
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:162
TClassEdit::GetLong64_Name
std::string GetLong64_Name(const char *original)
Replace 'long long' and 'unsigned long long' by 'Long64_t' and 'ULong64_t'.
Definition: TClassEdit.cxx:891
ROOT::TMetaUtils::TNormalizedCtxtImpl::fConfig
Config_t fConfig
Definition: TClingUtils.cxx:90
ROOT::TMetaUtils::AnnotatedRecordDecl::fRequestOnlyTClass
bool fRequestOnlyTClass
Definition: TClingUtils.h:203
ROOT::TMetaUtils::Error
void Error(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:789
N
#define N
ROOT::TMetaUtils::GetFullyQualifiedTypeName
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
Definition: TClingUtils.cxx:3504
ROOT::FoundationUtils::GetPathSeparator
const std::string & GetPathSeparator()
Definition: FoundationUtils.hxx:43
ROOT::TMetaUtils::TNormalizedCtxtImpl::fTemplatePtrArgsToKeepMap
static TemplPtrIntMap_t fTemplatePtrArgsToKeepMap
Definition: TClingUtils.cxx:92
ROOT::TMetaUtils::TNormalizedCtxt::GetTemplNargsToKeepMap
const TemplPtrIntMap_t GetTemplNargsToKeepMap() const
Definition: TClingUtils.cxx:359
ROOT::TMetaUtils::ExtractAttrIntPropertyFromName
bool ExtractAttrIntPropertyFromName(const clang::Decl &decl, const std::string &propName, int &propValue)
This routine counts on the "propName<separator>propValue" format.
Definition: TClingUtils.cxx:1728
ROOT::TMetaUtils::TNormalizedCtxtImpl::GetTemplNargsToKeepMap
const TemplPtrIntMap_t GetTemplNargsToKeepMap() const
Definition: TClingUtils.cxx:100
ROOT::TMetaUtils::propNames::nArgsToKeep
static const std::string nArgsToKeep("nArgsToKeep")
indent
static void indent(ostringstream &buf, int indent_level)
Definition: TClingCallFunc.cxx:87
RooFitShortHand::S
RooArgSet S(const RooAbsArg &v1)
Definition: RooGlobalFunc.cxx:390
ROOT::TMetaUtils::TClingLookupHelper::WantDiags
bool WantDiags() const
Definition: TClingUtils.h:172
ROOT::TMetaUtils::RConstructorType::RConstructorType
RConstructorType(const char *type_of_arg, const cling::Interpreter &)
Definition: TClingUtils.cxx:1167
ROOT::TMetaUtils::TrueName
std::string TrueName(const clang::FieldDecl &m)
TrueName strips the typedefs and array dimensions.
Definition: TClingUtils.cxx:2572
ROOT::TMetaUtils::TNormalizedCtxtImpl::TypesCont_t
TNormalizedCtxt::TypesCont_t TypesCont_t
Definition: TClingUtils.cxx:87
ROOT::TMetaUtils::extractPropertyNameVal
int extractPropertyNameVal(clang::Attr *attribute, std::string &attrName, std::string &attrValue)
Definition: TClingUtils.cxx:1694
RConfig.hxx
ROOT::TMetaUtils::IS_PRIVATE
@ IS_PRIVATE
Definition: TClingUtils.h:118
ROOT::Math::Cephes::A
static double A[]
Definition: SpecFuncCephes.cxx:170
ROOT::TMetaUtils::TClingLookupHelper::fInterpreterIsShuttingDownPtr
bool * fInterpreterIsShuttingDownPtr
Definition: TClingUtils.h:170
TClassEdit::TSplitType
Definition: TClassEdit.h:137
ROOT::TMetaUtils::GetUnderlyingRecordDecl
clang::RecordDecl * GetUnderlyingRecordDecl(clang::QualType type)
Definition: TClingUtils.cxx:2845
RecurseKeepNParams
static bool RecurseKeepNParams(clang::TemplateArgument &normTArg, const clang::TemplateArgument &tArg, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const clang::ASTContext &astCtxt)
Definition: TClingUtils.cxx:3749
ROOT::TMetaUtils::ExtractEnclosingScopes
const clang::RecordDecl * ExtractEnclosingScopes(const clang::Decl &decl, std::list< std::pair< std::string, unsigned int > > &enclosingSc)
Extract the names and types of containing scopes.
Definition: TClingUtils.cxx:4944
ROOT::TMetaUtils::AST2SourceTools::EncloseInNamespaces
int EncloseInNamespaces(const clang::Decl &decl, std::string &defString)
Take the namespaces which enclose the decl and put them around the definition string.
Definition: TClingUtils.cxx:5161
ROOT::kSTLlist
@ kSTLlist
Definition: ESTLType.h:31
ROOT::TMetaUtils::GetModuleFileName
std::string GetModuleFileName(const char *moduleName)
Return the dictionary file name for a module.
Definition: TClingUtils.cxx:4164
ROOT::TMetaUtils::TNormalizedCtxtImpl::TNormalizedCtxtImpl
TNormalizedCtxtImpl(const cling::LookupHelper &lh)
Initialize the list of typedef to keep (i.e.
Definition: TClingUtils.cxx:733
ROOT::TMetaUtils::AST2SourceTools::GetDefArg
int GetDefArg(const clang::ParmVarDecl &par, std::string &valAsString, const clang::PrintingPolicy &pp)
Get the default value as string.
Definition: TClingUtils.cxx:5556
ROOT::TMetaUtils::CheckPublicFuncWithProto
bool CheckPublicFuncWithProto(clang::CXXRecordDecl const *, char const *, char const *, const cling::Interpreter &, bool diagnose)
Return true, if the function (defined by the name and prototype) exists and is public.
Definition: TClingUtils.cxx:1252
ROOT::Math::IntegrationOneDim::Type
Type
enumeration specifying the integration types.
Definition: AllIntegrationTypes.h:32
getFinalSpellingLoc
static clang::SourceLocation getFinalSpellingLoc(clang::SourceManager &sourceManager, clang::SourceLocation sourceLoc)
Definition: TClingUtils.cxx:3329
ROOT::TMetaUtils::WritePointersSTL
void WritePointersSTL(const AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const TNormalizedCtxt &normCtxt)
Write interface function for STL members.
Definition: TClingUtils.cxx:2515
ROOT::TMetaUtils::GetNormalizedName
void GetNormalizedName(std::string &norm_name, const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type name normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t,...
Definition: TClingUtils.cxx:4048
ROOT::TMetaUtils::AST2SourceTools::FwdDeclIfTmplSpec
int FwdDeclIfTmplSpec(const clang::RecordDecl &recordDecl, const cling::Interpreter &interpreter, std::string &defString, const std::string &normalizedName)
Convert a tmplt decl to its fwd decl.
Definition: TClingUtils.cxx:5361
ROOT::TMetaUtils::WriteClassInit
void WriteClassInit(std::ostream &finalString, const AnnotatedRecordDecl &cl, const clang::CXXRecordDecl *decl, const cling::Interpreter &interp, const TNormalizedCtxt &normCtxt, const RConstructorTypes &ctorTypes, bool &needCollectionProxy)
FIXME: a function of 450+ lines!
Definition: TClingUtils.cxx:1750
ROOT::TMetaUtils::extractPropertyNameValFromString
int extractPropertyNameValFromString(const std::string attributeStr, std::string &attrName, std::string &attrValue)
Definition: TClingUtils.cxx:1677
ROOT::TMetaUtils::TNormalizedCtxt::keepTypedef
void keepTypedef(const cling::LookupHelper &lh, const char *name, bool replace=false)
Definition: TClingUtils.cxx:362
ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex
llvm::StringRef DataMemberInfo__ValidArrayIndex(const clang::DeclaratorDecl &m, int *errnum=0, llvm::StringRef *errstr=0)
ValidArrayIndex return a static string (so use it or copy it immediatly, do not call GrabIndex twice ...
Definition: TClingUtils.cxx:3132
ROOT::kSTLmap
@ kSTLmap
Definition: ESTLType.h:33
ROOT::TMetaUtils::TClingLookupHelper::TClingLookupHelper
TClingLookupHelper(cling::Interpreter &interpreter, TNormalizedCtxt &normCtxt, ExistingTypeCheck_t existingTypeCheck, AutoParse_t autoParse, bool *shuttingDownPtr, const int *pgDebug=0)
Definition: TClingUtils.cxx:532
ROOT::TMetaUtils::CheckDefaultConstructor
bool CheckDefaultConstructor(const clang::CXXRecordDecl *, const cling::Interpreter &interp)
Checks if default constructor exists and accessible.
Definition: TClingUtils.cxx:1049
ROOT::TMetaUtils::Fatal
void Fatal(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:829
ROOT::TMetaUtils::AnnotatedRecordDecl::GetNormalizedName
const char * GetNormalizedName() const
Definition: TClingUtils.h:269
ROOT::TMetaUtils::propNames::iotype
static const std::string iotype("iotype")
ROOT::TMetaUtils::TNormalizedCtxt::TemplPtrIntMap_t
std::map< const clang::ClassTemplateDecl *, int > TemplPtrIntMap_t
Definition: TClingUtils.h:144
ROOT::TMetaUtils::TNormalizedCtxt::AddTemplAndNargsToKeep
void AddTemplAndNargsToKeep(const clang::ClassTemplateDecl *templ, unsigned int i)
Definition: TClingUtils.cxx:351