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