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