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