Logo ROOT   6.07/09
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  finalString << " instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP << "< " << classname.c_str() << " >()));" << "\n";
1915 
1916  needCollectionProxy = true;
1917  }
1918 
1919  //---------------------------------------------------------------------------
1920  // Register Altenate spelling of the class name.
1921  /////////////////////////////////////////////////////////////////////////////
1922 
1923  if (cl.GetRequestedName()[0] && classname != cl.GetRequestedName()) {
1924  finalString << "\n" << " ::ROOT::AddClassAlternate(\""
1925  << classname << "\",\"" << cl.GetRequestedName() << "\");\n";
1926  }
1927 
1928  //---------------------------------------------------------------------------
1929  // Pass the schema evolution rules to TGenericClassInfo
1930  /////////////////////////////////////////////////////////////////////////////
1931 
1932  if( (rulesIt1 != ROOT::gReadRules.end() && rulesIt1->second.size()>0) || (rulesIt2 != ROOT::gReadRawRules.end() && rulesIt2->second.size()>0) ) {
1933  finalString << "\n" << " ROOT::Internal::TSchemaHelper* rule;" << "\n";
1934  }
1935 
1936  if( rulesIt1 != ROOT::gReadRules.end() ) {
1937  finalString << "\n" << " // the io read rules" << "\n" << " std::vector<ROOT::Internal::TSchemaHelper> readrules(" << rulesIt1->second.size() << ");" << "\n";
1938  ROOT::WriteSchemaList( rulesIt1->second, "readrules", finalString );
1939  finalString << " instance.SetReadRules( readrules );" << "\n";
1940  }
1941 
1942  if( rulesIt2 != ROOT::gReadRawRules.end() ) {
1943  finalString << "\n" << " // the io read raw rules" << "\n" << " std::vector<ROOT::Internal::TSchemaHelper> readrawrules(" << rulesIt2->second.size() << ");" << "\n";
1944  ROOT::WriteSchemaList( rulesIt2->second, "readrawrules", finalString );
1945  finalString << " instance.SetReadRawRules( readrawrules );" << "\n";
1946  }
1947 
1948  finalString << " return &instance;" << "\n" << " }" << "\n";
1949 
1950  if (!isStdNotString && !ROOT::TMetaUtils::hasOpaqueTypedef(cl, interp, normCtxt)) {
1951  // The GenerateInitInstance for STL are not unique and should not be externally accessible
1952  finalString << " TGenericClassInfo *GenerateInitInstance(const " << csymbol << "*)" << "\n" << " {\n return GenerateInitInstanceLocal((" << csymbol << "*)0);\n }" << "\n";
1953  }
1954 
1955  finalString << " // Static variable to force the class initialization" << "\n";
1956  // must be one long line otherwise UseDummy does not work
1957 
1958 
1959  finalString << " static ::ROOT::TGenericClassInfo *_R__UNIQUE_(Init) = GenerateInitInstanceLocal((const " << csymbol << "*)0x0); R__UseDummy(_R__UNIQUE_(Init));" << "\n";
1960 
1961  if (!ClassInfo__HasMethod(decl,"Dictionary",interp) || IsTemplate(*decl)) {
1962  finalString << "\n" << " // Dictionary for non-ClassDef classes" << "\n"
1963  << " static TClass *" << mappedname << "_Dictionary() {\n"
1964  << " TClass* theClass ="
1965  << "::ROOT::GenerateInitInstanceLocal((const " << csymbol << "*)0x0)->GetClass();\n"
1966  << " " << mappedname << "_TClassManip(theClass);\n";
1967  finalString << " return theClass;\n";
1968  finalString << " }\n\n";
1969 
1970  // Now manipulate tclass in order to percolate the properties expressed as
1971  // annotations of the decls.
1972  std::string manipString;
1973  std::string attribute_s;
1974  std::string attrName, attrValue;
1975  // Class properties
1976  bool attrMapExtracted = false;
1977  if (decl->hasAttrs()){
1978  // Loop on the attributes
1979  for (clang::Decl::attr_iterator attrIt = decl->attr_begin();
1980  attrIt!=decl->attr_end();++attrIt){
1981  if ( 0!=ROOT::TMetaUtils::extractAttrString(*attrIt,attribute_s)){
1982  continue;
1983  }
1984  if (0!=ROOT::TMetaUtils::extractPropertyNameValFromString(attribute_s, attrName, attrValue)){
1985  continue;
1986  }
1987  if (attrName == "name" ||
1988  attrName == "pattern" ||
1989  attrName == "rootmap") continue;
1990  // A general property
1991  // 1) We need to create the property map (in the gen code)
1992  // 2) we need to take out the map (in the gen code)
1993  // 3) We need to bookkep the fact that the map is created and out (in this source)
1994  // 4) We fill the map (in the gen code)
1995  if (!attrMapExtracted){
1996  manipString+=" theClass->CreateAttributeMap();\n";
1997  manipString+=" TDictAttributeMap* attrMap( theClass->GetAttributeMap() );\n";
1998  attrMapExtracted=true;
1999  }
2000  manipString+=" attrMap->AddProperty(\""+attrName +"\",\""+attrValue+"\");\n";
2001  }
2002  } // end of class has properties
2003 
2004  // Member properties
2005  // Loop on declarations inside the class, including data members
2006  for(clang::CXXRecordDecl::decl_iterator internalDeclIt = decl->decls_begin();
2007  internalDeclIt != decl->decls_end(); ++internalDeclIt){
2008  if (!(!(*internalDeclIt)->isImplicit()
2009  && (clang::isa<clang::FieldDecl>(*internalDeclIt) ||
2010  clang::isa<clang::VarDecl>(*internalDeclIt)))) continue; // Check if it's a var or a field
2011 
2012  // Now let's check the attributes of the var/field
2013  if (!internalDeclIt->hasAttrs()) continue;
2014 
2015  attrMapExtracted = false;
2016  bool memberPtrCreated = false;
2017 
2018  for (clang::Decl::attr_iterator attrIt = internalDeclIt->attr_begin();
2019  attrIt!=internalDeclIt->attr_end();++attrIt){
2020 
2021  // Get the attribute as string
2022  if ( 0!=ROOT::TMetaUtils::extractAttrString(*attrIt,attribute_s)){
2023  continue;
2024  }
2025 
2026  // Check the name of the decl
2027  clang::NamedDecl* namedInternalDecl = clang::dyn_cast<clang::NamedDecl> (*internalDeclIt);
2028  if (!namedInternalDecl) {
2029  TMetaUtils::Error(0,"Cannot convert field declaration to clang::NamedDecl");
2030  continue;
2031  };
2032  const std::string memberName(namedInternalDecl->getName());
2033  const std::string cppMemberName="theMember_"+memberName;
2034 
2035  // Prepare a string to get the data member, it can be used later.
2036  const std::string dataMemberCreation= " TDataMember* "+cppMemberName+" = theClass->GetDataMember(\""+memberName+"\");\n";
2037 
2038  // Let's now attack regular properties
2039 
2040  if (0!=ROOT::TMetaUtils::extractPropertyNameValFromString(attribute_s, attrName, attrValue)){
2041  continue;
2042  }
2043 
2044  // Skip these
2045  if (attrName == propNames::comment ||
2046  attrName == propNames::iotype ||
2047  attrName == propNames::ioname ) continue;
2048 
2049  if (!memberPtrCreated){
2050  manipString+=dataMemberCreation;
2051  memberPtrCreated=true;
2052  }
2053 
2054  if (!attrMapExtracted){
2055  manipString+=" "+cppMemberName+"->CreateAttributeMap();\n";
2056  manipString+=" TDictAttributeMap* memberAttrMap_"+memberName+"( theMember_"+memberName+"->GetAttributeMap() );\n";
2057  attrMapExtracted=true;
2058  }
2059 
2060  manipString+=" memberAttrMap_"+memberName+"->AddProperty(\""+attrName +"\",\""+attrValue+"\");\n";
2061 
2062 
2063  } // End loop on attributes
2064  } // End loop on internal declarations
2065 
2066 
2067  finalString << " static void " << mappedname << "_TClassManip(TClass* " << (manipString.empty() ? "":"theClass") << "){\n"
2068  << manipString
2069  << " }\n\n";
2070  } // End of !ClassInfo__HasMethod(decl,"Dictionary") || IsTemplate(*decl))
2071 
2072  finalString << "} // end of namespace ROOT" << "\n" << "\n";
2073 }
2074 
2075 ////////////////////////////////////////////////////////////////////////////////
2076 /// Return true if one of the class' enclosing scope is a namespace and
2077 /// set fullname to the fully qualified name,
2078 /// clsname to the name within a namespace
2079 /// and nsname to the namespace fully qualified name.
2080 
2081 bool ROOT::TMetaUtils::GetNameWithinNamespace(std::string &fullname,
2082  std::string &clsname,
2083  std::string &nsname,
2084  const clang::CXXRecordDecl *cl)
2085 {
2086  fullname.clear();
2087  nsname.clear();
2088 
2089  ROOT::TMetaUtils::GetQualifiedName(fullname,*cl);
2090  clsname = fullname;
2091 
2092  // Inline namespace are stripped from the normalized name, we need to
2093  // strip it from the prefix we want to remove.
2094  auto ctxt = cl->getEnclosingNamespaceContext();
2095  while(ctxt && ctxt!=cl && ctxt->isInlineNamespace()) {
2096  ctxt = ctxt->getParent();
2097  }
2098  if (ctxt) {
2099  const clang::NamedDecl *namedCtxt = llvm::dyn_cast<clang::NamedDecl>(ctxt);
2100  if (namedCtxt && namedCtxt!=cl) {
2101  const clang::NamespaceDecl *nsdecl = llvm::dyn_cast<clang::NamespaceDecl>(namedCtxt);
2102  if (nsdecl != 0 && !nsdecl->isAnonymousNamespace()) {
2103  ROOT::TMetaUtils::GetQualifiedName(nsname,*nsdecl);
2104  clsname.erase (0, nsname.size() + 2);
2105  return true;
2106  }
2107  }
2108  }
2109  return false;
2110 }
2111 
2112 ////////////////////////////////////////////////////////////////////////////////
2113 
2114 const clang::DeclContext *GetEnclosingSpace(const clang::RecordDecl &cl)
2115 {
2116  const clang::DeclContext *ctxt = cl.getDeclContext();
2117  while(ctxt && !ctxt->isNamespace()) {
2118  ctxt = ctxt->getParent();
2119  }
2120  return ctxt;
2121 }
2122 
2123 ////////////////////////////////////////////////////////////////////////////////
2124 /// Write all the necessary opening part of the namespace and
2125 /// return the number of closing brackets needed
2126 /// For example for Space1::Space2
2127 /// we write: namespace Space1 { namespace Space2 {
2128 /// and return 2.
2129 
2130 int ROOT::TMetaUtils::WriteNamespaceHeader(std::ostream &out, const clang::DeclContext *ctxt)
2131 {
2132  int closing_brackets = 0;
2133 
2134  //fprintf(stderr,"DEBUG: in WriteNamespaceHeader for %s with %s\n",
2135  // cl.Fullname(),namespace_obj.Fullname());
2136  if (ctxt && ctxt->isNamespace()) {
2137  closing_brackets = WriteNamespaceHeader(out,ctxt->getParent());
2138  for (int indent = 0; indent < closing_brackets; ++indent) {
2139  out << " ";
2140  }
2141  const clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(ctxt);
2142  if (ns->isInline())
2143  out << "inline ";
2144  out << "namespace " << ns->getNameAsString() << " {" << std::endl;
2145  closing_brackets++;
2146  }
2147 
2148  return closing_brackets;
2149 }
2150 
2151 ////////////////////////////////////////////////////////////////////////////////
2152 
2153 int ROOT::TMetaUtils::WriteNamespaceHeader(std::ostream &out, const clang::RecordDecl *cl)
2154 {
2155  return WriteNamespaceHeader(out, GetEnclosingSpace(*cl));
2156 }
2157 
2158 ////////////////////////////////////////////////////////////////////////////////
2159 
2160 bool ROOT::TMetaUtils::NeedTemplateKeyword(const clang::CXXRecordDecl *cl)
2161 {
2162  clang::TemplateSpecializationKind kind = cl->getTemplateSpecializationKind();
2163  if (kind == clang::TSK_Undeclared ) {
2164  // Note a template;
2165  return false;
2166  } else if (kind == clang::TSK_ExplicitSpecialization) {
2167  // This is a specialized templated class
2168  return false;
2169  } else {
2170  // This is an automatically or explicitly instantiated templated class.
2171  return true;
2172  }
2173 }
2174 
2175 ////////////////////////////////////////////////////////////////////////////////
2176 /// return true if we can find a custom operator new with placement
2177 
2178 bool ROOT::TMetaUtils::HasCustomOperatorNewPlacement(const char *which, const clang::RecordDecl &cl, const cling::Interpreter &interp)
2179 {
2180  const char *name = which;
2181  const char *proto = "size_t";
2182  const char *protoPlacement = "size_t,void*";
2183 
2184  // First search in the enclosing namespaces
2185  const clang::FunctionDecl *operatornew
2186  = ROOT::TMetaUtils::GetFuncWithProto(llvm::dyn_cast<clang::Decl>(cl.getDeclContext()),
2187  name, proto, interp,
2188  cling::LookupHelper::NoDiagnostics);
2189  const clang::FunctionDecl *operatornewPlacement
2190  = ROOT::TMetaUtils::GetFuncWithProto(llvm::dyn_cast<clang::Decl>(cl.getDeclContext()),
2191  name, protoPlacement, interp,
2192  cling::LookupHelper::NoDiagnostics);
2193 
2194  const clang::DeclContext *ctxtnew = 0;
2195  const clang::DeclContext *ctxtnewPlacement = 0;
2196 
2197  if (operatornew) {
2198  ctxtnew = operatornew->getParent();
2199  }
2200  if (operatornewPlacement) {
2201  ctxtnewPlacement = operatornewPlacement->getParent();
2202  }
2203 
2204  // Then in the class and base classes
2205  operatornew = ROOT::TMetaUtils::GetFuncWithProto(&cl, name, proto, interp,
2206  false /*diags*/);
2207  operatornewPlacement
2208  = ROOT::TMetaUtils::GetFuncWithProto(&cl, name, protoPlacement, interp,
2209  false /*diags*/);
2210 
2211  if (operatornew) {
2212  ctxtnew = operatornew->getParent();
2213  }
2214  if (operatornewPlacement) {
2215  ctxtnewPlacement = operatornewPlacement->getParent();
2216  }
2217 
2218  if (ctxtnewPlacement == 0) {
2219  return false;
2220  }
2221  if (ctxtnew == 0) {
2222  // Only a new with placement, no hiding
2223  return true;
2224  }
2225  // Both are non zero
2226  if (ctxtnew == ctxtnewPlacement) {
2227  // Same declaration ctxt, no hiding
2228  return true;
2229  }
2230  const clang::CXXRecordDecl* clnew = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnew);
2231  const clang::CXXRecordDecl* clnewPlacement = llvm::dyn_cast<clang::CXXRecordDecl>(ctxtnewPlacement);
2232  if (clnew == 0 && clnewPlacement == 0) {
2233  // They are both in different namespaces, I am not sure of the rules.
2234  // we probably ought to find which one is closest ... for now bail
2235  // (because rootcling was also bailing on that).
2236  return true;
2237  }
2238  if (clnew != 0 && clnewPlacement == 0) {
2239  // operator new is class method hiding the outer scope operator new with placement.
2240  return false;
2241  }
2242  if (clnew == 0 && clnewPlacement != 0) {
2243  // operator new is a not class method and can not hide new with placement which is a method
2244  return true;
2245  }
2246  // Both are class methods
2247  if (clnew->isDerivedFrom(clnewPlacement)) {
2248  // operator new is in a more derived part of the hierarchy, it is hiding operator new with placement.
2249  return false;
2250  }
2251  // operator new with placement is in a more derived part of the hierarchy, it can't be hidden by operator new.
2252  return true;
2253 }
2254 
2255 ////////////////////////////////////////////////////////////////////////////////
2256 /// return true if we can find a custom operator new with placement
2257 
2258 bool ROOT::TMetaUtils::HasCustomOperatorNewPlacement(const clang::RecordDecl &cl, const cling::Interpreter &interp)
2259 {
2260  return HasCustomOperatorNewPlacement("operator new",cl, interp);
2261 }
2262 
2263 ////////////////////////////////////////////////////////////////////////////////
2264 /// return true if we can find a custom operator new with placement
2265 
2266 bool ROOT::TMetaUtils::HasCustomOperatorNewArrayPlacement(const clang::RecordDecl &cl, const cling::Interpreter &interp)
2267 {
2268  return HasCustomOperatorNewPlacement("operator new[]",cl, interp);
2269 }
2270 
2271 ////////////////////////////////////////////////////////////////////////////////
2272 /// std::string NormalizedName;
2273 /// GetNormalizedName(NormalizedName, decl->getASTContext().getTypeDeclType(decl), interp, normCtxt);
2274 
2275 void ROOT::TMetaUtils::WriteAuxFunctions(std::ostream& finalString,
2276  const AnnotatedRecordDecl &cl,
2277  const clang::CXXRecordDecl *decl,
2278  const cling::Interpreter &interp,
2279  const RConstructorTypes& ctorTypes,
2280  const TNormalizedCtxt &normCtxt)
2281 {
2282  std::string classname = TClassEdit::GetLong64_Name(cl.GetNormalizedName());
2283 
2284  std::string mappedname;
2285  ROOT::TMetaUtils::GetCppName(mappedname,classname.c_str());
2286 
2287  // Write the functions that are need for the TGenericClassInfo.
2288  // This includes
2289  // IsA
2290  // operator new
2291  // operator new[]
2292  // operator delete
2293  // operator delete[]
2294 
2295  ROOT::TMetaUtils::GetCppName(mappedname,classname.c_str());
2296 
2297  if ( ! TClassEdit::IsStdClass( classname.c_str() ) ) {
2298 
2299  // Prefix the full class name with '::' except for the STL
2300  // containers and std::string. This is to request the
2301  // real class instead of the class in the namespace ROOT::Shadow
2302  classname.insert(0,"::");
2303  }
2304 
2305  finalString << "namespace ROOT {" << "\n";
2306 
2307  std::string args;
2308  if (HasIOConstructor(decl, args, ctorTypes, interp)) {
2309  // write the constructor wrapper only for concrete classes
2310  finalString << " // Wrappers around operator new" << "\n";
2311  finalString << " static void *new_" << mappedname.c_str() << "(void *p) {" << "\n" << " return p ? ";
2312  if (HasCustomOperatorNewPlacement(*decl, interp)) {
2313  finalString << "new(p) ";
2314  finalString << classname.c_str();
2315  finalString << args;
2316  finalString << " : ";
2317  } else {
2318  finalString << "::new((::ROOT::Internal::TOperatorNewHelper*)p) ";
2319  finalString << classname.c_str();
2320  finalString << args;
2321  finalString << " : ";
2322  }
2323  finalString << "new " << classname.c_str() << args << ";" << "\n";
2324  finalString << " }" << "\n";
2325 
2326  if (args.size()==0 && NeedDestructor(decl)) {
2327  // Can not can newArray if the destructor is not public.
2328  finalString << " static void *newArray_";
2329  finalString << mappedname.c_str();
2330  finalString << "(Long_t nElements, void *p) {";
2331  finalString << "\n";
2332  finalString << " return p ? ";
2333  if (HasCustomOperatorNewArrayPlacement(*decl, interp)) {
2334  finalString << "new(p) ";
2335  finalString << classname.c_str();
2336  finalString << "[nElements] : ";
2337  } else {
2338  finalString << "::new((::ROOT::Internal::TOperatorNewHelper*)p) ";
2339  finalString << classname.c_str();
2340  finalString << "[nElements] : ";
2341  }
2342  finalString << "new ";
2343  finalString << classname.c_str();
2344  finalString << "[nElements];";
2345  finalString << "\n";
2346  finalString << " }";
2347  finalString << "\n";
2348  }
2349  }
2350 
2351  if (NeedDestructor(decl)) {
2352  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";
2353  }
2354 
2355  if (HasDirectoryAutoAdd(decl, interp)) {
2356  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";
2357  }
2358 
2359  if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) {
2360  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";
2361  }
2362 
2363  if (HasCustomConvStreamerMemberFunction(cl, decl, interp, normCtxt)) {
2364  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";
2365  }
2366 
2367  if (HasNewMerge(decl, interp)) {
2368  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";
2369  } else if (HasOldMerge(decl, interp)) {
2370  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";
2371  }
2372 
2373  if (HasResetAfterMerge(decl, interp)) {
2374  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";
2375  }
2376  finalString << "} // end of namespace ROOT for class " << classname.c_str() << "\n" << "\n";
2377 }
2378 
2379 ////////////////////////////////////////////////////////////////////////////////
2380 /// Write interface function for STL members
2381 
2383  const cling::Interpreter &interp,
2384  const TNormalizedCtxt &normCtxt)
2385 {
2386  std::string a;
2387  std::string clName;
2388  TMetaUtils::GetCppName(clName, ROOT::TMetaUtils::GetFileName(*cl.GetRecordDecl(), interp).str().c_str());
2389  int version = ROOT::TMetaUtils::GetClassVersion(cl.GetRecordDecl(),interp);
2390  if (version == 0) return;
2391  if (version < 0 && !(cl.RequestStreamerInfo()) ) return;
2392 
2393 
2394  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
2395  if (clxx == 0) return;
2396 
2397  // We also need to look at the base classes.
2398  for(clang::CXXRecordDecl::base_class_const_iterator iter = clxx->bases_begin(), end = clxx->bases_end();
2399  iter != end;
2400  ++iter)
2401  {
2402  int k = ROOT::TMetaUtils::IsSTLContainer(*iter);
2403  if (k!=0) {
2404  Internal::RStl::Instance().GenerateTClassFor( iter->getType(), interp, normCtxt);
2405  }
2406  }
2407 
2408  // Loop over the non static data member.
2409  for(clang::RecordDecl::field_iterator field_iter = clxx->field_begin(), end = clxx->field_end();
2410  field_iter != end;
2411  ++field_iter)
2412  {
2413  std::string mTypename;
2414  ROOT::TMetaUtils::GetQualifiedName(mTypename, field_iter->getType(), *clxx);
2415 
2416  //member is a string
2417  {
2418  const char*shortTypeName = ROOT::TMetaUtils::ShortTypeName(mTypename.c_str());
2419  if (!strcmp(shortTypeName, "string")) {
2420  continue;
2421  }
2422  }
2423 
2424  if (!ROOT::TMetaUtils::IsStreamableObject(**field_iter, interp)) continue;
2425 
2426  int k = ROOT::TMetaUtils::IsSTLContainer( **field_iter );
2427  if (k!=0) {
2428  // fprintf(stderr,"Add %s which is also",m.Type()->Name());
2429  // fprintf(stderr," %s\n",R__TrueName(**field_iter) );
2430  clang::QualType utype(ROOT::TMetaUtils::GetUnderlyingType(field_iter->getType()),0);
2431  Internal::RStl::Instance().GenerateTClassFor(utype, interp, normCtxt);
2432  }
2433  }
2434 }
2435 
2436 ////////////////////////////////////////////////////////////////////////////////
2437 /// TrueName strips the typedefs and array dimensions.
2438 
2439 std::string ROOT::TMetaUtils::TrueName(const clang::FieldDecl &m)
2440 {
2441  const clang::Type *rawtype = m.getType()->getCanonicalTypeInternal().getTypePtr();
2442  if (rawtype->isArrayType()) {
2443  rawtype = rawtype->getBaseElementTypeUnsafe ();
2444  }
2445 
2446  std::string result;
2447  ROOT::TMetaUtils::GetQualifiedName(result, clang::QualType(rawtype,0), m);
2448  return result;
2449 }
2450 
2451 ////////////////////////////////////////////////////////////////////////////////
2452 /// Return the version number of the class or -1
2453 /// if the function Class_Version does not exist.
2454 
2455 int ROOT::TMetaUtils::GetClassVersion(const clang::RecordDecl *cl, const cling::Interpreter& interp)
2456 {
2457  const clang::CXXRecordDecl* CRD = llvm::dyn_cast<clang::CXXRecordDecl>(cl);
2458  if (!CRD) {
2459  // Must be an enum or namespace.
2460  // FIXME: Make it work for a namespace!
2461  return -1;
2462  }
2463  const clang::FunctionDecl* funcCV = ROOT::TMetaUtils::ClassInfo__HasMethod(CRD,"Class_Version",interp);
2464  // if we have no Class_Info() return -1.
2465  if (!funcCV) return -1;
2466  // if we have many Class_Info() (?!) return 1.
2467  if (funcCV == (clang::FunctionDecl*)-1) return 1;
2468 
2469  const clang::CompoundStmt* FuncBody
2470  = llvm::dyn_cast_or_null<clang::CompoundStmt>(funcCV->getBody());
2471  if (!FuncBody) return -1;
2472  if (FuncBody->size() != 1) {
2473  // This is a non-ClassDef(), complex function - it might depend on state
2474  // and thus we'll need the runtime and cannot determine the result
2475  // statically.
2476  return -1;
2477  }
2478  const clang::ReturnStmt* RetStmt
2479  = llvm::dyn_cast<clang::ReturnStmt>(FuncBody->body_back());
2480  if (!RetStmt) return -1;
2481  const clang::Expr* RetExpr = RetStmt->getRetValue();
2482  // ClassDef controls the content of Class_Version() but not the return
2483  // expression which is CPP expanded from what the user provided as second
2484  // ClassDef argument. It's usually just be an integer literal but it could
2485  // also be an enum or a variable template for all we know.
2486  // Go through ICE to be more general.
2487  llvm::APSInt RetRes;
2488  if (!RetExpr->isIntegerConstantExpr(RetRes, funcCV->getASTContext()))
2489  return -1;
2490  if (RetRes.isSigned()) {
2491  return (Version_t)RetRes.getSExtValue();
2492  }
2493  // else
2494  return (Version_t)RetRes.getZExtValue();
2495 }
2496 
2497 ////////////////////////////////////////////////////////////////////////////////
2498 /// Is this an STL container.
2499 
2501 {
2502  return TMetaUtils::IsSTLCont(*annotated.GetRecordDecl());
2503 }
2504 
2505 ////////////////////////////////////////////////////////////////////////////////
2506 /// Is this an STL container?
2507 
2509 {
2510  clang::QualType type = m.getType();
2511  clang::RecordDecl *decl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(type);
2512 
2513  if (decl) return TMetaUtils::IsSTLCont(*decl);
2514  else return ROOT::kNotSTL;
2515 }
2516 
2517 ////////////////////////////////////////////////////////////////////////////////
2518 /// Is this an STL container?
2519 
2520 int ROOT::TMetaUtils::IsSTLContainer(const clang::CXXBaseSpecifier &base)
2521 {
2522  clang::QualType type = base.getType();
2523  clang::RecordDecl *decl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(type);
2524 
2525  if (decl) return TMetaUtils::IsSTLCont(*decl);
2526  else return ROOT::kNotSTL;
2527 }
2528 
2529 ////////////////////////////////////////////////////////////////////////////////
2530 /// Return the absolute type of typeDesc.
2531 /// E.g.: typeDesc = "class TNamed**", returns "TNamed".
2532 /// we remove * and const keywords. (we do not want to remove & ).
2533 /// You need to use the result immediately before it is being overwritten.
2534 
2535 const char *ROOT::TMetaUtils::ShortTypeName(const char *typeDesc)
2536 {
2537  static char t[4096];
2538  static const char* constwd = "const ";
2539  static const char* constwdend = "const";
2540 
2541  const char *s;
2542  char *p=t;
2543  int lev=0;
2544  for (s=typeDesc;*s;s++) {
2545  if (*s=='<') lev++;
2546  if (*s=='>') lev--;
2547  if (lev==0 && *s=='*') continue;
2548  if (lev==0 && (strncmp(constwd,s,strlen(constwd))==0
2549  ||strcmp(constwdend,s)==0 ) ) {
2550  s+=strlen(constwd)-1; // -1 because the loop adds 1
2551  continue;
2552  }
2553  if (lev==0 && *s==' ' && *(s+1)!='*') { p = t; continue;}
2554  if (p - t > (long)sizeof(t)) {
2555  printf("ERROR (rootcling): type name too long for StortTypeName: %s\n",
2556  typeDesc);
2557  p[0] = 0;
2558  return t;
2559  }
2560  *p++ = *s;
2561  }
2562  p[0]=0;
2563 
2564  return t;
2565 }
2566 
2567 bool ROOT::TMetaUtils::IsStreamableObject(const clang::FieldDecl &m,
2568  const cling::Interpreter& interp)
2569 {
2570  const char *comment = ROOT::TMetaUtils::GetComment( m ).data();
2571 
2572  // Transient
2573  if (comment[0] == '!') return false;
2574 
2575  clang::QualType type = m.getType();
2576 
2577  if (type->isReferenceType()) {
2578  // Reference can not be streamed.
2579  return false;
2580  }
2581 
2582  std::string mTypeName = type.getAsString(m.getASTContext().getPrintingPolicy());
2583  if (!strcmp(mTypeName.c_str(), "string") || !strcmp(mTypeName.c_str(), "string*")) {
2584  return true;
2585  }
2586  if (!strcmp(mTypeName.c_str(), "std::string") || !strcmp(mTypeName.c_str(), "std::string*")) {
2587  return true;
2588  }
2589 
2591  return true;
2592  }
2593 
2594  const clang::Type *rawtype = type.getTypePtr()->getBaseElementTypeUnsafe ();
2595 
2596  if (rawtype->isPointerType()) {
2597  //Get to the 'raw' type.
2598  clang::QualType pointee;
2599  while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
2600  {
2601  rawtype = pointee.getTypePtr();
2602  }
2603  }
2604 
2605  if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2606  // not an ojbect.
2607  return false;
2608  }
2609 
2610  const clang::CXXRecordDecl *cxxdecl = rawtype->getAsCXXRecordDecl();
2611  if (cxxdecl && ROOT::TMetaUtils::ClassInfo__HasMethod(cxxdecl,"Streamer", interp)) {
2612  if (!(ROOT::TMetaUtils::ClassInfo__HasMethod(cxxdecl,"Class_Version", interp))) return true;
2613  int version = ROOT::TMetaUtils::GetClassVersion(cxxdecl,interp);
2614  if (version > 0) return true;
2615  }
2616  return false;
2617 }
2618 
2619 ////////////////////////////////////////////////////////////////////////////////
2620 /// Return the absolute type of typeDesc.
2621 /// E.g.: typeDesc = "class TNamed**", returns "TNamed".
2622 /// we remove * and const keywords. (we do not want to remove & ).
2623 /// You need to use the result immediately before it is being overwritten.
2624 
2625 std::string ROOT::TMetaUtils::ShortTypeName(const clang::FieldDecl &m)
2626 {
2627  const clang::Type *rawtype = m.getType().getTypePtr();
2628 
2629  //Get to the 'raw' type.
2630  clang::QualType pointee;
2631  while ( rawtype->isPointerType() && ((pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull()) && pointee.getTypePtr() != rawtype)
2632  {
2633  rawtype = pointee.getTypePtr();
2634  }
2635 
2636  std::string result;
2637  ROOT::TMetaUtils::GetQualifiedName(result, clang::QualType(rawtype,0), m);
2638  return result;
2639 }
2640 
2641 ////////////////////////////////////////////////////////////////////////////////
2642 
2643 clang::RecordDecl *ROOT::TMetaUtils::GetUnderlyingRecordDecl(clang::QualType type)
2644 {
2645  const clang::Type *rawtype = ROOT::TMetaUtils::GetUnderlyingType(type);
2646 
2647  if (rawtype->isFundamentalType() || rawtype->isEnumeralType()) {
2648  // not an object.
2649  return 0;
2650  }
2651  return rawtype->getAsCXXRecordDecl();
2652 }
2653 
2654 ////////////////////////////////////////////////////////////////////////////////
2655 /// Generate the code of the class
2656 /// If the requestor is genreflex, request the new streamer format
2657 
2659  const AnnotatedRecordDecl &cl,
2660  const cling::Interpreter &interp,
2661  const TNormalizedCtxt &normCtxt,
2662  std::ostream& dictStream,
2663  const RConstructorTypes& ctorTypes,
2664  bool isGenreflex=false)
2665 {
2666  const clang::CXXRecordDecl* decl = llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl());
2667 
2668  if (!decl || !decl->isCompleteDefinition()) {
2669  return;
2670  }
2671 
2672  std::string fullname;
2674  if (TClassEdit::IsSTLCont(fullname.c_str()) ) {
2675  Internal::RStl::Instance().GenerateTClassFor(cl.GetNormalizedName(), llvm::dyn_cast<clang::CXXRecordDecl>(cl.GetRecordDecl()), interp, normCtxt);
2676  return;
2677  }
2678 
2679  if (ROOT::TMetaUtils::ClassInfo__HasMethod(cl,"Streamer",interp)) {
2680  // The !genreflex is there to prevent genreflex to select collections which are data members
2681  // This is to maintain the behaviour of ROOT5 and ROOT6 up to 6.07 included.
2682  if (cl.RootFlag() && !isGenreflex) ROOT::TMetaUtils::WritePointersSTL(cl, interp, normCtxt); // In particular this detect if the class has a version number.
2683  if (!(cl.RequestNoStreamer())) {
2684  (*WriteStreamerFunc)(cl, interp, normCtxt, dictStream, isGenreflex || cl.RequestStreamerInfo());
2685  } else
2686  ROOT::TMetaUtils::Info(0, "Class %s: Do not generate Streamer() [*** custom streamer ***]\n",fullname.c_str());
2687  } else {
2688  ROOT::TMetaUtils::Info(0, "Class %s: Streamer() not declared\n", fullname.c_str());
2689 
2690  // See comment above about the !isGenreflex
2691  if (cl.RequestStreamerInfo() && !isGenreflex) ROOT::TMetaUtils::WritePointersSTL(cl, interp, normCtxt);
2692  }
2693  ROOT::TMetaUtils::WriteAuxFunctions(dictStream, cl, decl, interp, ctorTypes, normCtxt);
2694 }
2695 
2696 ////////////////////////////////////////////////////////////////////////////////
2697 /// Add any unspecified template parameters to the class template instance,
2698 /// mentioned anywhere in the type.
2699 ///
2700 /// Note: this does not strip any typedef but could be merged with cling::utils::Transform::GetPartiallyDesugaredType
2701 /// if we can safely replace TClassEdit::IsStd with a test on the declaring scope
2702 /// and if we can resolve the fact that the added parameter do not take into account possible use/dependences on Double32_t
2703 /// and if we decide that adding the default is the right long term solution or not.
2704 /// Whether it is or not depend on the I/O on whether the default template argument might change or not
2705 /// and whether they (should) affect the on disk layout (for STL containers, we do know they do not).
2706 
2707 clang::QualType ROOT::TMetaUtils::AddDefaultParameters(clang::QualType instanceType,
2708  const cling::Interpreter &interpreter,
2709  const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
2710 {
2711  const clang::ASTContext& Ctx = interpreter.getCI()->getASTContext();
2712 
2713  clang::QualType originalType = instanceType;
2714 
2715  // In case of name* we need to strip the pointer first, add the default and attach
2716  // the pointer once again.
2717  if (llvm::isa<clang::PointerType>(instanceType.getTypePtr())) {
2718  // Get the qualifiers.
2719  clang::Qualifiers quals = instanceType.getQualifiers();
2720  clang::QualType newPointee = AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2721  if (newPointee != instanceType->getPointeeType()) {
2722  instanceType = Ctx.getPointerType(newPointee);
2723  // Add back the qualifiers.
2724  instanceType = Ctx.getQualifiedType(instanceType, quals);
2725  }
2726  return instanceType;
2727  }
2728 
2729  // In case of Int_t& we need to strip the pointer first, desugar and attach
2730  // the pointer once again.
2731  if (llvm::isa<clang::ReferenceType>(instanceType.getTypePtr())) {
2732  // Get the qualifiers.
2733  bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(instanceType.getTypePtr());
2734  clang::Qualifiers quals = instanceType.getQualifiers();
2735  clang::QualType newPointee = AddDefaultParameters(instanceType->getPointeeType(), interpreter, normCtxt);
2736 
2737  if (newPointee != instanceType->getPointeeType()) {
2738  // Add the r- or l- value reference type back to the desugared one
2739  if (isLValueRefTy)
2740  instanceType = Ctx.getLValueReferenceType(newPointee);
2741  else
2742  instanceType = Ctx.getRValueReferenceType(newPointee);
2743  // Add back the qualifiers.
2744  instanceType = Ctx.getQualifiedType(instanceType, quals);
2745  }
2746  return instanceType;
2747  }
2748 
2749  // Treat the Scope.
2750  bool prefix_changed = false;
2751  clang::NestedNameSpecifier* prefix = 0;
2752  clang::Qualifiers prefix_qualifiers = instanceType.getLocalQualifiers();
2753  const clang::ElaboratedType* etype
2754  = llvm::dyn_cast<clang::ElaboratedType>(instanceType.getTypePtr());
2755  if (etype) {
2756  // We have to also handle the prefix.
2757  prefix = AddDefaultParametersNNS(Ctx, etype->getQualifier(), interpreter, normCtxt);
2758  prefix_changed = prefix != etype->getQualifier();
2759  instanceType = clang::QualType(etype->getNamedType().getTypePtr(),0);
2760  }
2761 
2762  // In case of template specializations iterate over the arguments and
2763  // add unspecified default parameter.
2764 
2765  const clang::TemplateSpecializationType* TST
2766  = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());
2767 
2768  const clang::ClassTemplateSpecializationDecl* TSTdecl
2769  = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instanceType.getTypePtr()->getAsCXXRecordDecl());
2770 
2771  // Don't add the default paramater onto std classes.
2772  // We really need this for __shared_ptr which add a enum constant value which
2773  // is spelled in its 'numeral' form and thus the resulting type name is
2774  // incorrect. We also can used this for any of the STL collections where we
2775  // know we don't want the default argument. For the other members of the
2776  // std namespace this is dubious (because TMetaUtils::GetNormalizedName would
2777  // not drop those defaults). [I.e. the real test ought to be is std and
2778  // name is __shared_ptr or vector or list or set or etc.]
2779  bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
2780 
2781  bool mightHaveChanged = false;
2782  if (TST && TSTdecl) {
2783 
2784  clang::Sema& S = interpreter.getCI()->getSema();
2785  clang::TemplateDecl *Template = TSTdecl->getSpecializedTemplate()->getMostRecentDecl();
2786  clang::TemplateParameterList *Params = Template->getTemplateParameters();
2787  clang::TemplateParameterList::iterator Param = Params->begin(); // , ParamEnd = Params->end();
2788  //llvm::SmallVectorImpl<TemplateArgument> Converted; // Need to contains the other arguments.
2789  // Converted seems to be the same as our 'desArgs'
2790 
2791  unsigned int dropDefault = normCtxt.GetConfig().DropDefaultArg(*Template);
2792 
2793  llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
2794  unsigned int Idecl = 0, Edecl = TSTdecl->getTemplateArgs().size();
2795  unsigned int maxAddArg = TSTdecl->getTemplateArgs().size() - dropDefault;
2796  for(clang::TemplateSpecializationType::iterator
2797  I = TST->begin(), E = TST->end();
2798  Idecl != Edecl;
2799  I!=E ? ++I : 0, ++Idecl, ++Param) {
2800 
2801  if (I != E) {
2802 
2803  if (I->getKind() == clang::TemplateArgument::Template) {
2804  clang::TemplateName templateName = I->getAsTemplate();
2805  clang::TemplateDecl* templateDecl = templateName.getAsTemplateDecl();
2806  if (templateDecl) {
2807  clang::DeclContext* declCtxt = templateDecl->getDeclContext();
2808 
2809  if (declCtxt && !templateName.getAsQualifiedTemplateName()){
2810  clang::NamespaceDecl* ns = clang::dyn_cast<clang::NamespaceDecl>(declCtxt);
2811  clang::NestedNameSpecifier* nns;
2812  if (ns) {
2813  nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx, ns);
2814  } else if (clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(declCtxt)) {
2815  nns = cling::utils::TypeName::CreateNestedNameSpecifier(Ctx,TD, false /*FullyQualified*/);
2816  } else {
2817  // TU scope
2818  desArgs.push_back(*I);
2819  continue;
2820  }
2821  clang::TemplateName templateNameWithNSS ( Ctx.getQualifiedTemplateName(nns, false, templateDecl) );
2822  desArgs.push_back(clang::TemplateArgument(templateNameWithNSS));
2823  mightHaveChanged = true;
2824  continue;
2825  }
2826  }
2827  }
2828 
2829  if (I->getKind() != clang::TemplateArgument::Type) {
2830  desArgs.push_back(*I);
2831  continue;
2832  }
2833 
2834  clang::QualType SubTy = I->getAsType();
2835 
2836  // Check if the type needs more desugaring and recurse.
2837  // (Originally this was limited to elaborated and templated type,
2838  // but we also need to do it for pointer and reference type
2839  // and who knows what, so do it always)
2840  clang::QualType newSubTy = AddDefaultParameters(SubTy,
2841  interpreter,
2842  normCtxt);
2843  if (SubTy != newSubTy) {
2844  mightHaveChanged = true;
2845  desArgs.push_back(clang::TemplateArgument(newSubTy));
2846  } else {
2847  desArgs.push_back(*I);
2848  }
2849  // Converted.push_back(TemplateArgument(ArgTypeForTemplate));
2850  } else if (!isStdDropDefault && Idecl < maxAddArg) {
2851 
2852  mightHaveChanged = true;
2853 
2854  const clang::TemplateArgument& templateArg
2855  = TSTdecl->getTemplateArgs().get(Idecl);
2856  if (templateArg.getKind() != clang::TemplateArgument::Type) {
2857  desArgs.push_back(templateArg);
2858  continue;
2859  }
2860  clang::QualType SubTy = templateArg.getAsType();
2861 
2862  clang::SourceLocation TemplateLoc = Template->getSourceRange ().getBegin(); //NOTE: not sure that this is the 'right' location.
2863  clang::SourceLocation RAngleLoc = TSTdecl->getSourceRange().getBegin(); // NOTE: most likely wrong, I think this is expecting the location of right angle
2864 
2865  clang::TemplateTypeParmDecl *TTP = llvm::dyn_cast<clang::TemplateTypeParmDecl>(*Param);
2866  {
2867  // We may induce template instantiation
2868  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interpreter));
2869  clang::sema::HackForDefaultTemplateArg raii;
2870  bool HasDefaultArgs;
2871  clang::TemplateArgumentLoc ArgType = S.SubstDefaultTemplateArgumentIfAvailable(
2872  Template,
2873  TemplateLoc,
2874  RAngleLoc,
2875  TTP,
2876  desArgs,
2877  HasDefaultArgs);
2878  // The substition can fail, in which case there would have been compilation
2879  // error printed on the screen.
2880  if (ArgType.getArgument().isNull()
2881  || ArgType.getArgument().getKind() != clang::TemplateArgument::Type) {
2882  ROOT::TMetaUtils::Error("ROOT::TMetaUtils::AddDefaultParameters",
2883  "Template parameter substitution failed for %s around %s",
2884  instanceType.getAsString().c_str(),
2885  SubTy.getAsString().c_str()
2886  );
2887  break;
2888  }
2889  clang::QualType BetterSubTy = ArgType.getArgument().getAsType();
2890  SubTy = cling::utils::Transform::GetPartiallyDesugaredType(Ctx,BetterSubTy,normCtxt.GetConfig(),/*fullyQualified=*/ true);
2891  }
2892  SubTy = AddDefaultParameters(SubTy,interpreter,normCtxt);
2893  desArgs.push_back(clang::TemplateArgument(SubTy));
2894  } else {
2895  // We are past the end of the list of specified arguements and we
2896  // do not want to add the default, no need to continue.
2897  break;
2898  }
2899  }
2900 
2901  // If we added default parameter, allocate new type in the AST.
2902  if (mightHaveChanged) {
2903  instanceType = Ctx.getTemplateSpecializationType(TST->getTemplateName(),
2904  desArgs.data(),
2905  desArgs.size(),
2906  TST->getCanonicalTypeInternal());
2907  }
2908  }
2909 
2910  if (!prefix_changed && !mightHaveChanged) return originalType;
2911  if (prefix) {
2912  instanceType = Ctx.getElaboratedType(clang::ETK_None,prefix,instanceType);
2913  instanceType = Ctx.getQualifiedType(instanceType,prefix_qualifiers);
2914  }
2915  return instanceType;
2916 }
2917 
2918 ////////////////////////////////////////////////////////////////////////////////
2919 /// ValidArrayIndex return a static string (so use it or copy it immediatly, do not
2920 /// call GrabIndex twice in the same expression) containing the size of the
2921 /// array data member.
2922 /// In case of error, or if the size is not specified, GrabIndex returns 0.
2923 /// If errnum is not null, *errnum updated with the error number:
2924 /// Cint::G__DataMemberInfo::G__VALID : valid array index
2925 /// Cint::G__DataMemberInfo::G__NOT_INT : array index is not an int
2926 /// Cint::G__DataMemberInfo::G__NOT_DEF : index not defined before array
2927 /// (this IS an error for streaming to disk)
2928 /// Cint::G__DataMemberInfo::G__IS_PRIVATE: index exist in a parent class but is private
2929 /// Cint::G__DataMemberInfo::G__UNKNOWN : index is not known
2930 /// If errstr is not null, *errstr is updated with the address of a static
2931 /// string containing the part of the index with is invalid.
2932 
2933 llvm::StringRef ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(const clang::DeclaratorDecl &m, int *errnum, llvm::StringRef *errstr)
2934 {
2935  llvm::StringRef title;
2936 
2937  // Try to get the comment either from the annotation or the header file if present
2938  if (clang::AnnotateAttr *A = m.getAttr<clang::AnnotateAttr>())
2939  title = A->getAnnotation();
2940  else
2941  // Try to get the comment from the header file if present
2942  title = ROOT::TMetaUtils::GetComment( m );
2943 
2944  // Let's see if the user provided us with some information
2945  // with the format: //[dimension] this is the dim of the array
2946  // dimension can be an arithmetical expression containing, literal integer,
2947  // the operator *,+ and - and data member of integral type. In addition the
2948  // data members used for the size of the array need to be defined prior to
2949  // the array.
2950 
2951  if (errnum) *errnum = VALID;
2952 
2953  if (title.size() == 0 || (title[0] != '[')) return llvm::StringRef();
2954  size_t rightbracket = title.find(']');
2955  if (rightbracket == llvm::StringRef::npos) return llvm::StringRef();
2956 
2957  std::string working;
2958  llvm::StringRef indexvar(title.data()+1,rightbracket-1);
2959 
2960  // now we should have indexvar=dimension
2961  // Let's see if this is legal.
2962  // which means a combination of data member and digit separated by '*','+','-'
2963  // First we remove white spaces.
2964  unsigned int i;
2965  size_t indexvarlen = indexvar.size();
2966  for ( i=0; i<indexvarlen; i++) {
2967  if (!isspace(indexvar[i])) {
2968  working += indexvar[i];
2969  }
2970  };
2971 
2972  // Now we go through all indentifiers
2973  const char *tokenlist = "*+-";
2974  char *current = const_cast<char*>(working.c_str());
2975  current = strtok(current,tokenlist);
2976 
2977  while (current!=0) {
2978  // Check the token
2979  if (isdigit(current[0])) {
2980  for(i=0;i<strlen(current);i++) {
2981  if (!isdigit(current[0])) {
2982  // Error we only access integer.
2983  //NOTE: *** Need to print an error;
2984  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not an interger\n",
2985  // member.MemberOf()->Name(), member.Name(), current);
2986  if (errstr) *errstr = current;
2987  if (errnum) *errnum = NOT_INT;
2988  return llvm::StringRef();
2989  }
2990  }
2991  } else { // current token is not a digit
2992  // first let's see if it is a data member:
2993  int found = 0;
2994  const clang::CXXRecordDecl *parent_clxx = llvm::dyn_cast<clang::CXXRecordDecl>(m.getDeclContext());
2995  const clang::FieldDecl *index1 = 0;
2996  if (parent_clxx)
2997  index1 = GetDataMemberFromAll(*parent_clxx, current );
2998  if ( index1 ) {
2999  if ( IsFieldDeclInt(index1) ) {
3000  found = 1;
3001  // Let's see if it has already been written down in the
3002  // Streamer.
3003  // Let's see if we already wrote it down in the
3004  // streamer.
3005  for(clang::RecordDecl::field_iterator field_iter = parent_clxx->field_begin(), end = parent_clxx->field_end();
3006  field_iter != end;
3007  ++field_iter)
3008  {
3009  if ( field_iter->getNameAsString() == m.getNameAsString() ) {
3010  // we reached the current data member before
3011  // reaching the index so we have not written it yet!
3012  //NOTE: *** Need to print an error;
3013  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) has not been defined before the array \n",
3014  // member.MemberOf()->Name(), member.Name(), current);
3015  if (errstr) *errstr = current;
3016  if (errnum) *errnum = NOT_DEF;
3017  return llvm::StringRef();
3018  }
3019  if ( field_iter->getNameAsString() == index1->getNameAsString() ) {
3020  break;
3021  }
3022  } // end of while (m_local.Next())
3023  } else {
3024  //NOTE: *** Need to print an error;
3025  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
3026  // member.MemberOf()->Name(), member.Name(), current);
3027  if (errstr) *errstr = current;
3028  if (errnum) *errnum = NOT_INT;
3029  return llvm::StringRef();
3030  }
3031  } else {
3032  // There is no variable by this name in this class, let see
3033  // the base classes!:
3034  index1 = GetDataMemberFromAllParents( *parent_clxx, current );
3035  if ( index1 ) {
3036  if ( IsFieldDeclInt(index1) ) {
3037  found = 1;
3038  } else {
3039  // We found a data member but it is the wrong type
3040  //NOTE: *** Need to print an error;
3041  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
3042  // member.MemberOf()->Name(), member.Name(), current);
3043  if (errnum) *errnum = NOT_INT;
3044  if (errstr) *errstr = current;
3045  //NOTE: *** Need to print an error;
3046  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not int \n",
3047  // member.MemberOf()->Name(), member.Name(), current);
3048  if (errnum) *errnum = NOT_INT;
3049  if (errstr) *errstr = current;
3050  return llvm::StringRef();
3051  }
3052  if ( found && (index1->getAccess() == clang::AS_private) ) {
3053  //NOTE: *** Need to print an error;
3054  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is a private member of %s \n",
3055  if (errstr) *errstr = current;
3056  if (errnum) *errnum = IS_PRIVATE;
3057  return llvm::StringRef();
3058  }
3059  }
3060  if (!found) {
3061  //NOTE: *** Need to print an error;
3062  //fprintf(stderr,"*** Datamember %s::%s: size of array (%s) is not known \n",
3063  // member.MemberOf()->Name(), member.Name(), indexvar);
3064  if (errstr) *errstr = indexvar;
3065  if (errnum) *errnum = UNKNOWN;
3066  return llvm::StringRef();
3067  } // end of if not found
3068  } // end of if is a data member of the class
3069  } // end of if isdigit
3070 
3071  current = strtok(0,tokenlist);
3072  } // end of while loop on tokens
3073 
3074  return indexvar;
3075 
3076 }
3077 
3078 ////////////////////////////////////////////////////////////////////////////////
3079 /// Return (in the argument 'output') a mangled version of the C++ symbol/type (pass as 'input')
3080 /// that can be used in C++ as a variable name.
3081 
3082 void ROOT::TMetaUtils::GetCppName(std::string &out, const char *in)
3083 {
3084  out.resize(strlen(in)*2);
3085  unsigned int i=0,j=0,c;
3086  while((c=in[i])) {
3087  if (out.capacity() < (j+3)) {
3088  out.resize(2*j+3);
3089  }
3090  switch(c) { // We resized the underlying buffer if needed
3091  case '+': strcpy(const_cast<char*>(out.data())+j,"pL"); j+=2; break;
3092  case '-': strcpy(const_cast<char*>(out.data())+j,"mI"); j+=2; break;
3093  case '*': strcpy(const_cast<char*>(out.data())+j,"mU"); j+=2; break;
3094  case '/': strcpy(const_cast<char*>(out.data())+j,"dI"); j+=2; break;
3095  case '&': strcpy(const_cast<char*>(out.data())+j,"aN"); j+=2; break;
3096  case '%': strcpy(const_cast<char*>(out.data())+j,"pE"); j+=2; break;
3097  case '|': strcpy(const_cast<char*>(out.data())+j,"oR"); j+=2; break;
3098  case '^': strcpy(const_cast<char*>(out.data())+j,"hA"); j+=2; break;
3099  case '>': strcpy(const_cast<char*>(out.data())+j,"gR"); j+=2; break;
3100  case '<': strcpy(const_cast<char*>(out.data())+j,"lE"); j+=2; break;
3101  case '=': strcpy(const_cast<char*>(out.data())+j,"eQ"); j+=2; break;
3102  case '~': strcpy(const_cast<char*>(out.data())+j,"wA"); j+=2; break;
3103  case '.': strcpy(const_cast<char*>(out.data())+j,"dO"); j+=2; break;
3104  case '(': strcpy(const_cast<char*>(out.data())+j,"oP"); j+=2; break;
3105  case ')': strcpy(const_cast<char*>(out.data())+j,"cP"); j+=2; break;
3106  case '[': strcpy(const_cast<char*>(out.data())+j,"oB"); j+=2; break;
3107  case ']': strcpy(const_cast<char*>(out.data())+j,"cB"); j+=2; break;
3108  case '!': strcpy(const_cast<char*>(out.data())+j,"nO"); j+=2; break;
3109  case ',': strcpy(const_cast<char*>(out.data())+j,"cO"); j+=2; break;
3110  case '$': strcpy(const_cast<char*>(out.data())+j,"dA"); j+=2; break;
3111  case ' ': strcpy(const_cast<char*>(out.data())+j,"sP"); j+=2; break;
3112  case ':': strcpy(const_cast<char*>(out.data())+j,"cL"); j+=2; break;
3113  case '"': strcpy(const_cast<char*>(out.data())+j,"dQ"); j+=2; break;
3114  case '@': strcpy(const_cast<char*>(out.data())+j,"aT"); j+=2; break;
3115  case '\'': strcpy(const_cast<char*>(out.data())+j,"sQ"); j+=2; break;
3116  case '\\': strcpy(const_cast<char*>(out.data())+j,"fI"); j+=2; break;
3117  default: out[j++]=c; break;
3118  }
3119  ++i;
3120  }
3121  out.resize(j);
3122 
3123  // Remove initial numbers if any
3124  std::size_t firstNonNumber = out.find_first_not_of("0123456789");
3125  out.replace(0,firstNonNumber,"");
3126 
3127  return;
3128 }
3129 
3130 static clang::SourceLocation
3131 getFinalSpellingLoc(clang::SourceManager& sourceManager,
3132  clang::SourceLocation sourceLoc) {
3133  // Follow macro expansion until we hit a source file.
3134  if (!sourceLoc.isFileID()) {
3135  return sourceManager.getExpansionRange(sourceLoc).second;
3136  }
3137  return sourceLoc;
3138 }
3139 
3140 ////////////////////////////////////////////////////////////////////////////////
3141 /// Return the header file to be included to declare the Decl.
3142 
3143 llvm::StringRef ROOT::TMetaUtils::GetFileName(const clang::Decl& decl,
3144  const cling::Interpreter& interp)
3145 {
3146  // It looks like the template specialization decl actually contains _less_ information
3147  // on the location of the code than the decl (in case where there is forward declaration,
3148  // that is what the specialization points to).
3149  //
3150  // const clang::CXXRecordDecl* clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
3151  // if (clxx) {
3152  // switch(clxx->getTemplateSpecializationKind()) {
3153  // case clang::TSK_Undeclared:
3154  // // We want the default behavior
3155  // break;
3156  // case clang::TSK_ExplicitInstantiationDeclaration:
3157  // case clang::TSK_ExplicitInstantiationDefinition:
3158  // case clang::TSK_ImplicitInstantiation: {
3159  // // We want the location of the template declaration:
3160  // const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (clxx);
3161  // if (tmplt_specialization) {
3162  // // return GetFileName(const_cast< clang::ClassTemplateSpecializationDecl *>(tmplt_specialization)->getSpecializedTemplate());
3163  // }
3164  // break;
3165  // }
3166  // case clang::TSK_ExplicitSpecialization:
3167  // // We want the default behavior
3168  // break;
3169  // default:
3170  // break;
3171  // }
3172  // }
3173 
3174  using namespace clang;
3175  SourceLocation headerLoc = decl.getLocation();
3176 
3177  static const char invalidFilename[] = "";
3178  if (!headerLoc.isValid()) return invalidFilename;
3179 
3180  HeaderSearch& HdrSearch = interp.getCI()->getPreprocessor().getHeaderSearchInfo();
3181 
3182  SourceManager& sourceManager = decl.getASTContext().getSourceManager();
3183  headerLoc = getFinalSpellingLoc(sourceManager, headerLoc);
3184  FileID headerFID = sourceManager.getFileID(headerLoc);
3185  SourceLocation includeLoc
3186  = getFinalSpellingLoc(sourceManager,
3187  sourceManager.getIncludeLoc(headerFID));
3188 
3189  const FileEntry *headerFE = sourceManager.getFileEntryForID(headerFID);
3190  while (includeLoc.isValid() && sourceManager.isInSystemHeader(includeLoc)) {
3191  const DirectoryLookup *foundDir = 0;
3192  // use HeaderSearch on the basename, to make sure it takes a header from
3193  // the include path (e.g. not from /usr/include/bits/)
3194  const FileEntry *FEhdr
3195  = HdrSearch.LookupFile(llvm::sys::path::filename(headerFE->getName()),
3196  SourceLocation(),
3197  true /*isAngled*/, 0/*FromDir*/, foundDir,
3198  ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3199  0/*Searchpath*/, 0/*RelPath*/,
3200  0/*RequestingModule*/, 0/*SuggestedModule*/,
3201  false /*SkipCache*/,
3202  false /*BuildSystemModule*/,
3203  false /*OpenFile*/, true /*CacheFailures*/);
3204  if (FEhdr) break;
3205  headerFID = sourceManager.getFileID(includeLoc);
3206  headerFE = sourceManager.getFileEntryForID(headerFID);
3207  includeLoc = getFinalSpellingLoc(sourceManager,
3208  sourceManager.getIncludeLoc(headerFID));
3209  }
3210 
3211  if (!headerFE) return invalidFilename;
3212  llvm::StringRef headerFileName = headerFE->getName();
3213 
3214  // Now headerFID references the last valid system header or the original
3215  // user file.
3216  // Find out how to include it by matching file name to include paths.
3217  // We assume that the file "/A/B/C/D.h" can at some level be included as
3218  // "C/D.h". Be we cannot know whether that happens to be a different file
3219  // with the same name. Thus we first find the longest stem that can be
3220  // reached, say B/C/D.h. Then we find the shortest one, say C/D.h, that
3221  // points to the same file as the long version. If such a short version
3222  // exists it will be returned. If it doesn't the long version is returned.
3223  bool isAbsolute = llvm::sys::path::is_absolute(headerFileName);
3224  const FileEntry* FELong = 0;
3225  // Find the longest available match.
3226  for (llvm::sys::path::const_iterator
3227  IDir = llvm::sys::path::begin(headerFileName),
3228  EDir = llvm::sys::path::end(headerFileName);
3229  !FELong && IDir != EDir; ++IDir) {
3230  if (isAbsolute) {
3231  // skip "/" part
3232  isAbsolute = false;
3233  continue;
3234  }
3235  size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3236  llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3237  assert(trailingPart.data() + trailingPart.size()
3238  == headerFileName.data() + headerFileName.size()
3239  && "Mismatched partitioning of file name!");
3240  const DirectoryLookup* FoundDir = 0;
3241  FELong = HdrSearch.LookupFile(trailingPart, SourceLocation(),
3242  true /*isAngled*/, 0/*FromDir*/, FoundDir,
3243  ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3244  0/*Searchpath*/, 0/*RelPath*/,
3245  0/*RequestingModule*/, 0/*SuggestedModule*/);
3246  }
3247 
3248  if (!FELong) {
3249  // We did not find any file part in any search path.
3250  return invalidFilename;
3251  }
3252 
3253  // Iterates through path *parts* "C"; we need trailing parts "C/D.h"
3254  for (llvm::sys::path::reverse_iterator
3255  IDir = llvm::sys::path::rbegin(headerFileName),
3256  EDir = llvm::sys::path::rend(headerFileName);
3257  IDir != EDir; ++IDir) {
3258  size_t lenTrailing = headerFileName.size() - (IDir->data() - headerFileName.data());
3259  llvm::StringRef trailingPart(IDir->data(), lenTrailing);
3260  assert(trailingPart.data() + trailingPart.size()
3261  == headerFileName.data() + headerFileName.size()
3262  && "Mismatched partitioning of file name!");
3263  const DirectoryLookup* FoundDir = 0;
3264  // Can we find it, and is it the same file as the long version?
3265  // (or are we back to the previously found spelling, which is fine, too)
3266  if (HdrSearch.LookupFile(trailingPart, SourceLocation(),
3267  true /*isAngled*/, 0/*FromDir*/, FoundDir,
3268  ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>>(),
3269  0/*Searchpath*/,
3270  0/*RelPath*/,
3271  0/*RequestingModule*/, 0 /*SuggestedModule*/) == FELong) {
3272  return trailingPart;
3273  }
3274  }
3275 
3276  return invalidFilename;
3277 }
3278 
3279 ////////////////////////////////////////////////////////////////////////////////
3280 
3281 void ROOT::TMetaUtils::GetFullyQualifiedTypeName(std::string &typenamestr,
3282  const clang::QualType &qtype,
3283  const clang::ASTContext &astContext)
3284 {
3285  std::string fqname = cling::utils::TypeName::GetFullyQualifiedName(qtype, astContext);
3286  TClassEdit::TSplitType splitname(fqname.c_str(),
3289 }
3290 
3291 ////////////////////////////////////////////////////////////////////////////////
3292 
3293 void ROOT::TMetaUtils::GetFullyQualifiedTypeName(std::string &typenamestr,
3294  const clang::QualType &qtype,
3295  const cling::Interpreter &interpreter)
3296 {
3297  GetFullyQualifiedTypeName(typenamestr,
3298  qtype,
3299  interpreter.getCI()->getASTContext());
3300 }
3301 
3302 ////////////////////////////////////////////////////////////////////////////////
3303 /// Return the -I needed to find RuntimeUniverse.h
3304 
3306 {
3307 #ifdef ROOTETCDIR
3308  if (rootbuild) {
3309  // Building ROOT, ignore ROOTETCDIR!
3310 #endif
3311  const char* rootsys = getenv("ROOTSYS");
3312  if (!rootsys) {
3313  Error(0, "Environment variable ROOTSYS not set!");
3314  return "-Ietc";
3315  }
3316  return std::string("-I") + rootsys + "/etc";
3317 #ifdef ROOTETCDIR
3318  }
3319  return std::string("-I") + ROOTETCDIR;
3320 #endif
3321 }
3322 
3323 ////////////////////////////////////////////////////////////////////////////////
3324 /// Return the LLVM / clang resource directory
3325 
3326 std::string ROOT::TMetaUtils::GetLLVMResourceDir(bool rootbuild)
3327 {
3328 #ifdef R__EXTERN_LLVMDIR
3329  return R__EXTERN_LLVMDIR;
3330 #else
3331  return GetInterpreterExtraIncludePath(rootbuild)
3332  .substr(2, std::string::npos) + "/cling";
3333 #endif
3334 }
3335 
3336 ////////////////////////////////////////////////////////////////////////////////
3337 /// Get the template specialisation decl and template decl behind the qualtype
3338 /// Returns true if successfully found, false otherwise
3339 
3340 bool ROOT::TMetaUtils::QualType2Template(const clang::QualType& qt,
3341  clang::ClassTemplateDecl*& ctd,
3342  clang::ClassTemplateSpecializationDecl*& ctsd)
3343 {
3344  using namespace clang;
3345  const Type* theType = qt.getTypePtr();
3346  if (!theType){
3347  ctd=nullptr;
3348  ctsd=nullptr;
3349  return false;
3350  }
3351 
3352  if (theType->isPointerType()) {
3353  return QualType2Template(theType->getPointeeType(), ctd, ctsd);
3354  }
3355 
3356  if (const RecordType* rType = llvm::dyn_cast<RecordType>(theType)) {
3357  ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(rType->getDecl());
3358  if (ctsd) {
3359  ctd = ctsd->getSpecializedTemplate();
3360  return true;
3361  }
3362  }
3363 
3364  if (const SubstTemplateTypeParmType* sttpType = llvm::dyn_cast<SubstTemplateTypeParmType>(theType)){
3365  return QualType2Template(sttpType->getReplacementType(), ctd, ctsd);
3366  }
3367 
3368 
3369  ctsd = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(qt->getAsCXXRecordDecl());
3370  if(ctsd){
3371  ctd = ctsd->getSpecializedTemplate();
3372  return true;
3373  }
3374 
3375  ctd=nullptr;
3376  ctsd=nullptr;
3377  return false;
3378 }
3379 
3380 ////////////////////////////////////////////////////////////////////////////////
3381 /// Extract from a qualtype the class template if this makes sense.
3382 /// Retuns the ClassTemplateDecl or nullptr otherwise.
3383 
3384 clang::ClassTemplateDecl* ROOT::TMetaUtils::QualType2ClassTemplateDecl(const clang::QualType& qt)
3385 {
3386  using namespace clang;
3387  ClassTemplateSpecializationDecl* ctsd;
3388  ClassTemplateDecl* ctd;
3389  QualType2Template(qt,ctd,ctsd);
3390  return ctd;
3391 }
3392 
3393 ////////////////////////////////////////////////////////////////////////////////
3394 /// These manipulations are necessary because a template specialisation type
3395 /// does not inherit from a record type (there is an asymmetry between
3396 /// the decls and the types in the clang interface).
3397 /// We may need therefore to step into the "Decl dimension" to then get back
3398 /// to the "type dimension".
3399 
3400 clang::TemplateName ROOT::TMetaUtils::ExtractTemplateNameFromQualType(const clang::QualType& qt)
3401 {
3402  using namespace clang;
3403  TemplateName theTemplateName;
3404 
3405  const Type* theType = qt.getTypePtr();
3406 
3407  if (const TemplateSpecializationType* tst = llvm::dyn_cast_or_null<const TemplateSpecializationType>(theType)) {
3408  theTemplateName = tst->getTemplateName();
3409  } // We step into the decl dimension
3410  else if (ClassTemplateDecl* ctd = QualType2ClassTemplateDecl(qt)) {
3411  theTemplateName = TemplateName(ctd);
3412  }
3413 
3414  return theTemplateName;
3415 }
3416 
3417 ////////////////////////////////////////////////////////////////////////////////
3418 
3419 static bool areEqualTypes(const clang::TemplateArgument& tArg,
3420  llvm::SmallVectorImpl<clang::TemplateArgument>& preceedingTArgs,
3421  const clang::NamedDecl& tPar,
3422  const cling::Interpreter& interp,
3423  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt)
3424 {
3425  using namespace ROOT::TMetaUtils;
3426  using namespace clang;
3427 
3428  // Check if this is a type for security
3429  TemplateTypeParmDecl* ttpdPtr = const_cast<TemplateTypeParmDecl*>(llvm::dyn_cast<TemplateTypeParmDecl>(&tPar));
3430  if (!ttpdPtr) return false;
3431  if (!ttpdPtr->hasDefaultArgument()) return false; // we should not be here in this case, but we protect us.
3432 
3433  // Try the fast solution
3434  QualType tParQualType = ttpdPtr->getDefaultArgument();
3435  const QualType tArgQualType = tArg.getAsType();
3436 
3437  // Now the equality tests for non template specialisations.
3438 
3439  // The easy cases:
3440  // template <class T=double> class A; or
3441  // template <class T=A<float>> class B;
3442  if (tParQualType.getTypePtr() == tArgQualType.getTypePtr()) return true;
3443 
3444  // Here the difficulty comes. We have to check if the argument is equal to its
3445  // default. We can do that bootstrapping an argument which has the default value
3446  // based on the preceeding arguments.
3447  // Basically we ask sema to give us the value of the argument given the template
3448  // of behind the parameter and the all the arguments.
3449  // So:
3450 
3451  // Take the template out of the parameter
3452 
3453  const clang::ElaboratedType* etype
3454  = llvm::dyn_cast<clang::ElaboratedType>(tParQualType.getTypePtr());
3455  while (etype) {
3456  tParQualType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3457  etype = llvm::dyn_cast<clang::ElaboratedType>(tParQualType.getTypePtr());
3458  }
3459 
3460  const TemplateSpecializationType* tst =
3461  llvm::dyn_cast<TemplateSpecializationType>(tParQualType.getTypePtr());
3462 
3463  if(!tst) // nothing more to be tried. They are different indeed.
3464  return false;
3465 
3466  ClassTemplateSpecializationDecl* TSTdecl
3467  = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(tArgQualType->getAsCXXRecordDecl());
3468 
3469  if(!TSTdecl) // nothing more to be tried. They are different indeed.
3470  return false;
3471 
3472  TemplateDecl *Template = tst->getTemplateName().getAsTemplateDecl();
3473 
3474  // Take the template location
3475  SourceLocation TemplateLoc = Template->getSourceRange ().getBegin();
3476 
3477  // Get the position of the "<" (LA) of the specializaion
3478  SourceLocation LAngleLoc = TSTdecl->getSourceRange().getBegin();
3479 
3480 
3481  // Enclose in a scope for the RAII
3482  bool isEqual=false;
3483  TemplateArgument newArg = tArg;
3484  {
3485  clang::Sema& S = interp.getCI()->getSema();
3486  cling::Interpreter::PushTransactionRAII clingRAII(const_cast<cling::Interpreter*>(&interp));
3487  clang::sema::HackForDefaultTemplateArg raii; // Hic sunt leones
3488  bool HasDefaultArgs;
3489  TemplateArgumentLoc defTArgLoc = S.SubstDefaultTemplateArgumentIfAvailable(Template,
3490  TemplateLoc,
3491  LAngleLoc,
3492  ttpdPtr,
3493  preceedingTArgs,
3494  HasDefaultArgs);
3495  // The substition can fail, in which case there would have been compilation
3496  // error printed on the screen.
3497  newArg = defTArgLoc.getArgument();
3498  if (newArg.isNull() ||
3499  newArg.getKind() != clang::TemplateArgument::Type) {
3500  ROOT::TMetaUtils::Error("areEqualTypes",
3501  "Template parameter substitution failed!");
3502  }
3503 
3504  ClassTemplateSpecializationDecl* nTSTdecl
3505  = llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(newArg.getAsType()->getAsCXXRecordDecl());
3506 // std::cout << "nSTdecl is " << nTSTdecl << std::endl;
3507 
3508  isEqual = nTSTdecl->getMostRecentDecl() == TSTdecl->getMostRecentDecl() ||
3509  tParQualType.getTypePtr() == newArg.getAsType().getTypePtr();
3510  }
3511 
3512 
3513  return isEqual;
3514 }
3515 
3516 
3517 ////////////////////////////////////////////////////////////////////////////////
3518 /// std::cout << "Are equal values?\n";
3519 
3520 static bool areEqualValues(const clang::TemplateArgument& tArg,
3521  const clang::NamedDecl& tPar)
3522 {
3523  using namespace clang;
3524  const NonTypeTemplateParmDecl* nttpdPtr = llvm::dyn_cast<NonTypeTemplateParmDecl>(&tPar);
3525  if (!nttpdPtr) return false;
3526  const NonTypeTemplateParmDecl& nttpd = *nttpdPtr;
3527 
3528  if (!nttpd.hasDefaultArgument())
3529  return false;
3530 
3531  // 64 bits wide and signed (non unsigned, that is why "false")
3532  llvm::APSInt defaultValueAPSInt(64, false);
3533  if (Expr* defArgExpr = nttpd.getDefaultArgument()) {
3534  const ASTContext& astCtxt = nttpdPtr->getASTContext();
3535  defArgExpr->isIntegerConstantExpr(defaultValueAPSInt, astCtxt);
3536  }
3537 
3538  const int value = tArg.getAsIntegral().getLimitedValue();
3539 
3540  // std::cout << (value == defaultValueAPSInt ? "yes!":"no") << std::endl;
3541  return value == defaultValueAPSInt;
3542 }
3543 
3544 ////////////////////////////////////////////////////////////////////////////////
3545 /// Check if this NamedDecl is a template parameter with a default argument.
3546 /// This is a single interface to treat both integral and type parameters.
3547 /// Returns true if this is the case, false otherwise
3548 
3549 static bool isTypeWithDefault(const clang::NamedDecl* nDecl)
3550 {
3551  using namespace clang;
3552  if (!nDecl) return false;
3553  if (const TemplateTypeParmDecl* ttpd = llvm::dyn_cast<TemplateTypeParmDecl>(nDecl))
3554  return ttpd->hasDefaultArgument();
3555  if (const NonTypeTemplateParmDecl* nttpd = llvm::dyn_cast<NonTypeTemplateParmDecl>(nDecl))
3556  return nttpd->hasDefaultArgument();
3557  return false;
3558 
3559 }
3560 
3561 static void KeepNParams(clang::QualType& normalizedType,
3562  const clang::QualType& vanillaType,
3563  const cling::Interpreter& interp,
3564  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt);
3565 
3566 // Returns true if normTArg might have changed.
3567 static bool RecurseKeepNParams(clang::TemplateArgument &normTArg,
3568  const clang::TemplateArgument &tArg,
3569  const cling::Interpreter& interp,
3570  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt,
3571  const clang::ASTContext& astCtxt)
3572 {
3573  using namespace ROOT::TMetaUtils;
3574  using namespace clang;
3575 
3576  // Once we know there is no more default parameter, we can run through to the end
3577  // and/or recurse in the template parameter packs.
3578 
3579  // If this is a type,
3580  // we need first of all to recurse: this argument may need to be manipulated
3581  if (tArg.getKind() == clang::TemplateArgument::Type) {
3582  QualType thisNormQualType = normTArg.getAsType();
3583  QualType thisArgQualType = tArg.getAsType();
3584  KeepNParams(thisNormQualType,
3585  thisArgQualType,
3586  interp,
3587  normCtxt);
3588  normTArg = TemplateArgument(thisNormQualType);
3589  return (thisNormQualType != thisArgQualType);
3590  } else if (normTArg.getKind() == clang::TemplateArgument::Pack) {
3591  assert( tArg.getKind() == clang::TemplateArgument::Pack );
3592 
3593  SmallVector<TemplateArgument, 2> desArgs;
3594  bool mightHaveChanged = true;
3595  for (auto I = normTArg.pack_begin(), E = normTArg.pack_end(),
3596  FI = tArg.pack_begin(), FE = tArg.pack_end();
3597  I != E && FI != FE; ++I, ++FI)
3598  {
3599  TemplateArgument pack_arg(*I);
3600  mightHaveChanged |= RecurseKeepNParams(pack_arg, *FI, interp, normCtxt, astCtxt);
3601  desArgs.push_back(pack_arg);
3602  }
3603  if (mightHaveChanged) {
3604  ASTContext &mutableCtx( const_cast<ASTContext&>(astCtxt) );
3605  normTArg = TemplateArgument::CreatePackCopy(mutableCtx, desArgs);
3606  }
3607  return mightHaveChanged;
3608  }
3609  return false;
3610 }
3611 
3612 
3613 ////////////////////////////////////////////////////////////////////////////////
3614 /// This function allows to manipulate the number of arguments in the type
3615 /// of a template specialisation.
3616 
3617 static void KeepNParams(clang::QualType& normalizedType,
3618  const clang::QualType& vanillaType,
3619  const cling::Interpreter& interp,
3620  const ROOT::TMetaUtils::TNormalizedCtxt& normCtxt)
3621 {
3622  using namespace ROOT::TMetaUtils;
3623  using namespace clang;
3624 
3625  // If this type has no template specialisation behind, we don't need to do
3626  // anything
3627  ClassTemplateSpecializationDecl* ctsd;
3628  ClassTemplateDecl* ctd;
3629  if (! QualType2Template(vanillaType, ctd, ctsd)) return ;
3630 
3631  // Even if this is a template, if we don't keep any argument, return
3632  const int nArgsToKeep = normCtxt.GetNargsToKeep(ctd);
3633 
3634  // Important in case of early return: we must restore the original qualtype
3635  QualType originalNormalizedType = normalizedType;
3636 
3637  const ASTContext& astCtxt = ctsd->getASTContext();
3638 
3639 
3640  // In case of name* we need to strip the pointer first, add the default and attach
3641  // the pointer once again.
3642  if (llvm::isa<clang::PointerType>(normalizedType.getTypePtr())) {
3643  // Get the qualifiers.
3644  clang::Qualifiers quals = normalizedType.getQualifiers();
3645  auto valNormalizedType = normalizedType->getPointeeType();
3646  KeepNParams(valNormalizedType,vanillaType, interp, normCtxt);
3647  normalizedType = astCtxt.getPointerType(valNormalizedType);
3648  // Add back the qualifiers.
3649  normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3650  return;
3651  }
3652 
3653  // In case of Int_t& we need to strip the pointer first, desugar and attach
3654  // the pointer once again.
3655  if (llvm::isa<clang::ReferenceType>(normalizedType.getTypePtr())) {
3656  // Get the qualifiers.
3657  bool isLValueRefTy = llvm::isa<clang::LValueReferenceType>(normalizedType.getTypePtr());
3658  clang::Qualifiers quals = normalizedType.getQualifiers();
3659  auto valNormType = normalizedType->getPointeeType();
3660  KeepNParams(valNormType, vanillaType, interp, normCtxt);
3661 
3662  // Add the r- or l- value reference type back to the desugared one
3663  if (isLValueRefTy)
3664  normalizedType = astCtxt.getLValueReferenceType(valNormType);
3665  else
3666  normalizedType = astCtxt.getRValueReferenceType(valNormType);
3667  // Add back the qualifiers.
3668  normalizedType = astCtxt.getQualifiedType(normalizedType, quals);
3669  return;
3670  }
3671 
3672  // Treat the Scope (factorise the code out to reuse it in AddDefaultParameters)
3673  bool prefix_changed = false;
3674  clang::NestedNameSpecifier* prefix = nullptr;
3675  clang::Qualifiers prefix_qualifiers = normalizedType.getLocalQualifiers();
3676  const clang::ElaboratedType* etype
3677  = llvm::dyn_cast<clang::ElaboratedType>(normalizedType.getTypePtr());
3678  if (etype) {
3679  // We have to also handle the prefix.
3680  // TODO: we ought to be running KeepNParams
3681  prefix = AddDefaultParametersNNS(astCtxt, etype->getQualifier(), interp, normCtxt);
3682  prefix_changed = prefix != etype->getQualifier();
3683  normalizedType = clang::QualType(etype->getNamedType().getTypePtr(),0);
3684  }
3685 
3686  // The canonical decl does not necessarily have the template default arguments.
3687  // Need to walk through the redecl chain to find it (we know there will be no
3688  // inconsistencies, at least)
3689  const clang::ClassTemplateDecl* ctdWithDefaultArgs = ctd;
3690  for (const RedeclarableTemplateDecl* rd: ctdWithDefaultArgs->redecls()) {
3691  clang::TemplateParameterList* tpl = rd->getTemplateParameters();
3692  if (tpl->getMinRequiredArguments () < tpl->size())
3693  ctdWithDefaultArgs = llvm::dyn_cast<clang::ClassTemplateDecl>(rd);
3694  }
3695  TemplateParameterList* tParsPtr = ctdWithDefaultArgs->getTemplateParameters();
3696  const TemplateParameterList& tPars = *tParsPtr;
3697  const TemplateArgumentList& tArgs = ctsd->getTemplateArgs();
3698 
3699  // We extract the template name from the type
3700  TemplateName theTemplateName = ExtractTemplateNameFromQualType(normalizedType);
3701  if (theTemplateName.isNull()) {
3702  normalizedType=originalNormalizedType;
3703  return;
3704  }
3705 
3706  const TemplateSpecializationType* normalizedTst =
3707  llvm::dyn_cast<TemplateSpecializationType>(normalizedType.getTypePtr());
3708  if (!normalizedTst) {
3709  normalizedType=originalNormalizedType;
3710  return;
3711  }
3712 
3713  const clang::ClassTemplateSpecializationDecl* TSTdecl
3714  = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(normalizedType.getTypePtr()->getAsCXXRecordDecl());
3715  bool isStdDropDefault = TSTdecl && IsStdDropDefaultClass(*TSTdecl);
3716 
3717  // Loop over the template parameters and arguments recursively.
3718  // We go down the two lanes: the one of template parameters (decls) and the
3719  // one of template arguments (QualTypes) in parallel. The former are a
3720  // property of the template, independent of its instantiations.
3721  // The latter are a property of the instance itself.
3722  llvm::SmallVector<TemplateArgument, 4> argsToKeep;
3723 
3724  const int nArgs = tArgs.size();
3725  const int nNormArgs = normalizedTst->getNumArgs();
3726 
3727  bool mightHaveChanged = false;
3728 
3729  // becomes true when a parameter has a value equal to its default
3730  for (int formal = 0, inst = 0; formal != nArgs; ++formal, ++inst) {
3731  const NamedDecl* tParPtr = tPars.getParam(formal);
3732  if (!tParPtr) {
3733  Error("KeepNParams", "The parameter number %s is null.\n", formal);
3734  continue;
3735  }
3736 
3737  // Stop if the normalized TemplateSpecializationType has less arguments than
3738  // the one index is pointing at.
3739  // We piggy back on the AddDefaultParameters routine basically.
3740  if (formal == nNormArgs || inst == nNormArgs) break;
3741 
3742  const TemplateArgument& tArg = tArgs.get(formal);
3743  TemplateArgument normTArg(normalizedTst->getArgs()[inst]);
3744 
3745  bool shouldKeepArg = nArgsToKeep < 0 || inst < nArgsToKeep;
3746  if (isStdDropDefault) shouldKeepArg = false;
3747 
3748  // Nothing to do here: either this parameter has no default, or we have to keep it.
3749  // FIXME: Temporary measure to get Atlas started with this.
3750  // We put a hard cut on the number of template arguments to keep, w/o checking if
3751  // they are non default. This makes this feature UNUSABLE for cases like std::vector,
3752  // where 2 different entities would have the same name if an allocator different from
3753  // the default one is by chance used.
3754  if (!isTypeWithDefault(tParPtr) || shouldKeepArg) {
3755  if ( tParPtr->isTemplateParameterPack() ) {
3756  // This is the last template parameter in the template declaration
3757  // but it is signaling that there can be an arbitrary number of arguments
3758  // in the template instance. So to avoid inadvertenly dropping those
3759  // arguments we just process all remaining argument and exit the main loop.
3760  for( ; inst != nNormArgs; ++inst) {
3761  normTArg = normalizedTst->getArgs()[inst];
3762  mightHaveChanged |= RecurseKeepNParams(normTArg, tArg, interp, normCtxt, astCtxt);
3763  argsToKeep.push_back(normTArg);
3764  }
3765  // Done.
3766  break;
3767  }
3768  mightHaveChanged |= RecurseKeepNParams(normTArg, tArg, interp, normCtxt, astCtxt);
3769  argsToKeep.push_back(normTArg);
3770  continue;
3771  } else {
3772  if (!isStdDropDefault) {
3773  // Here we should not break but rather check if the value is the default one.
3774  mightHaveChanged = true;
3775  break;
3776  }
3777  // For std, we want to check the default args values.
3778  }
3779 
3780  // Now, we keep it only if it not is equal to its default, expressed in the arg
3781  // Some gymnastic is needed to decide how to check for equality according to the
3782  // flavour of Type: templateType or Integer
3783  bool equal=false;
3784  auto argKind = tArg.getKind();
3785  if (argKind == clang::TemplateArgument::Type){
3786  // we need all the info
3787  equal = areEqualTypes(tArg, argsToKeep, *tParPtr, interp, normCtxt);
3788  } else if (argKind == clang::TemplateArgument::Integral){
3789  equal = areEqualValues(tArg, *tParPtr);
3790  }
3791  if (!equal) {
3792  mightHaveChanged |= RecurseKeepNParams(normTArg, tArg, interp, normCtxt, astCtxt);
3793  argsToKeep.push_back(normTArg);
3794  } else {
3795  mightHaveChanged = true;
3796  }
3797 
3798 
3799  } // of loop over parameters and arguments
3800 
3801  if (!prefix_changed && !mightHaveChanged) {
3802  normalizedType = originalNormalizedType;
3803  return;
3804  }
3805 
3806  // now, let's remanipulate our Qualtype
3807  if (mightHaveChanged) {
3808  Qualifiers qualifiers = normalizedType.getLocalQualifiers();
3809  normalizedType = astCtxt.getTemplateSpecializationType(theTemplateName,
3810  argsToKeep.data(),
3811  argsToKeep.size(),
3812  normalizedType.getTypePtr()->getCanonicalTypeInternal());
3813  normalizedType = astCtxt.getQualifiedType(normalizedType, qualifiers);
3814  }
3815 
3816  // Here we have (prefix_changed==true || mightHaveChanged), in both case
3817  // we need to reconstruct the type.
3818  if (prefix) {
3819  normalizedType = astCtxt.getElaboratedType(clang::ETK_None,prefix,normalizedType);
3820  normalizedType = astCtxt.getQualifiedType(normalizedType,prefix_qualifiers);
3821  }
3822 
3823 }
3824 
3825 ////////////////////////////////////////////////////////////////////////////////
3826 /// Return the type normalized for ROOT,
3827 /// keeping only the ROOT opaque typedef (Double32_t, etc.) and
3828 /// adding default template argument for all types except those explicitly
3829 /// requested to be drop by the user.
3830 /// Default template for STL collections are not yet removed by this routine.
3831 
3832 clang::QualType ROOT::TMetaUtils::GetNormalizedType(const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
3833 {
3834  clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
3835 
3836  clang::QualType normalizedType = cling::utils::Transform::GetPartiallyDesugaredType(ctxt, type, normCtxt.GetConfig(), true /* fully qualify */);
3837 
3838  // Readd missing default template parameters
3839  normalizedType = ROOT::TMetaUtils::AddDefaultParameters(normalizedType, interpreter, normCtxt);
3840 
3841  // Get the number of arguments to keep in case they are not default.
3842  KeepNParams(normalizedType,type,interpreter,normCtxt);
3843 
3844  return normalizedType;
3845 }
3846 
3847 ////////////////////////////////////////////////////////////////////////////////
3848 /// Return the type name normalized for ROOT,
3849 /// keeping only the ROOT opaque typedef (Double32_t, etc.) and
3850 /// adding default template argument for all types except the STL collections
3851 /// where we remove the default template argument if any.
3852 ///
3853 /// This routine might actually belong in the interpreter because
3854 /// cache the clang::Type might be intepreter specific.
3855 
3856 void ROOT::TMetaUtils::GetNormalizedName(std::string &norm_name, const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
3857 {
3858  if (type.isNull()) {
3859  norm_name = "";
3860  return;
3861  }
3862 
3863  clang::QualType normalizedType = GetNormalizedType(type,interpreter,normCtxt);
3864 
3865  clang::ASTContext &ctxt = interpreter.getCI()->getASTContext();
3866  clang::PrintingPolicy policy(ctxt.getPrintingPolicy());
3867  policy.SuppressTagKeyword = true; // Never get the class or struct keyword
3868  policy.SuppressScope = true; // Force the scope to be coming from a clang::ElaboratedType.
3869  policy.AnonymousTagLocations = false; // Do not extract file name + line number for anonymous types.
3870  // The scope suppression is required for getting rid of the anonymous part of the name of a class defined in an anonymous namespace.
3871  // This gives us more control vs not using the clang::ElaboratedType and relying on the Policy.SuppressUnwrittenScope which would
3872  // strip both the anonymous and the inline namespace names (and we probably do not want the later to be suppressed).
3873 
3874  std::string normalizedNameStep1;
3875  normalizedType.getAsStringInternal(normalizedNameStep1,policy);
3876 
3877  // Still remove the std:: and default template argument for STL container and
3878  // normalize the location and amount of white spaces.
3881 
3882  // The result of this routine is by definition a fully qualified name. There is an implicit starting '::' at the beginning of the name.
3883  // Depending on how the user typed their code, in particular typedef declarations, we may end up with an explicit '::' being
3884  // part of the result string. For consistency, we must remove it.
3885  if (norm_name.length()>2 && norm_name[0]==':' && norm_name[1]==':') {
3886  norm_name.erase(0,2);
3887  }
3888 
3889 }
3890 
3891 ////////////////////////////////////////////////////////////////////////////////
3892 
3893 void ROOT::TMetaUtils::GetNormalizedName(std::string &norm_name,
3894  const clang::TypeDecl* typeDecl,
3895  const cling::Interpreter &interpreter)
3896 {
3897  ROOT::TMetaUtils::TNormalizedCtxt tNormCtxt(interpreter.getLookupHelper());
3898  const clang::Sema &sema = interpreter.getSema();
3899  clang::ASTContext& astCtxt = sema.getASTContext();
3900  clang::QualType qualType = astCtxt.getTypeDeclType(typeDecl);
3901 
3903  qualType,
3904  interpreter,
3905  tNormCtxt);
3906 }
3907 
3908 ////////////////////////////////////////////////////////////////////////////////
3909 std::pair<std::string,clang::QualType>
3910 ROOT::TMetaUtils::GetNameTypeForIO(const clang::QualType& thisType,
3911  const cling::Interpreter &interpreter,
3912  const TNormalizedCtxt &normCtxt,
3913  TClassEdit::EModType mode)
3914 {
3915  std::string thisTypeName;
3916  GetNormalizedName(thisTypeName, thisType, interpreter, normCtxt );
3917  bool hasChanged;
3918  auto thisTypeNameForIO = TClassEdit::GetNameForIO(thisTypeName, mode, &hasChanged);
3919  if (!hasChanged) return std::make_pair(thisTypeName,thisType);
3920 
3922  ROOT::TMetaUtils::Info("ROOT::TMetaUtils::GetTypeForIO",
3923  "Name changed from %s to %s\n", thisTypeName.c_str(), thisTypeNameForIO.c_str());
3924  }
3925 
3926  auto& lookupHelper = interpreter.getLookupHelper();
3927 
3928  const clang::Type* typePtrForIO;
3929  lookupHelper.findScope(thisTypeNameForIO,
3930  cling::LookupHelper::DiagSetting::NoDiagnostics,
3931  &typePtrForIO);
3932 
3933  // This should never happen
3934  if (!typePtrForIO) {
3935  ROOT::TMetaUtils::Fatal("ROOT::TMetaUtils::GetTypeForIO",
3936  "Type not found: %s.",thisTypeNameForIO.c_str());
3937  }
3938 
3939  clang::QualType typeForIO(typePtrForIO,0);
3940 
3941  // Check if this is a class. Indeed it could well be a POD
3942  if (!typeForIO->isRecordType()) {
3943  return std::make_pair(thisTypeNameForIO,typeForIO);
3944  }
3945 
3946  auto thisDeclForIO = typeForIO->getAsCXXRecordDecl();
3947  if (!thisDeclForIO) {
3948  ROOT::TMetaUtils::Error("ROOT::TMetaUtils::GetTypeForIO",
3949  "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());
3950  return std::make_pair(thisTypeName,thisType);
3951  }
3952 
3953  return std::make_pair(thisTypeNameForIO,typeForIO);
3954 }
3955 
3956 ////////////////////////////////////////////////////////////////////////////////
3957 
3958 clang::QualType ROOT::TMetaUtils::GetTypeForIO(const clang::QualType& thisType,
3959  const cling::Interpreter &interpreter,
3960  const TNormalizedCtxt &normCtxt,
3961  TClassEdit::EModType mode)
3962 {
3963  return GetNameTypeForIO(thisType, interpreter, normCtxt, mode).second;
3964 }
3965 
3966 ////////////////////////////////////////////////////////////////////////////////
3967 
3968 std::string ROOT::TMetaUtils::GetROOTIncludeDir(bool rootbuild)
3969 {
3970  const std::string defaultInclude ("include");
3971  if (!rootbuild) {
3972 #ifndef ROOTINCDIR
3973  const char* rootSysContent = getenv("ROOTSYS");
3974  if (rootSysContent) {
3975  std::string incl_rootsys (rootSysContent);
3976  return incl_rootsys + "/" + defaultInclude;
3977  } else {
3978  Error(0,"Environment variable ROOTSYS not set");
3979  return defaultInclude;
3980  }
3981 #else
3982  return ROOTINCDIR;
3983 #endif
3984  }
3985 
3986  return defaultInclude;
3987 }
3988 
3989 ////////////////////////////////////////////////////////////////////////////////
3990 /// Return the dictionary file name for a module
3991 
3992 std::string ROOT::TMetaUtils::GetModuleFileName(const char* moduleName)
3993 {
3994  std::string dictFileName(moduleName);
3995  dictFileName += "_rdict.pcm";
3996  return dictFileName;
3997 }
3998 
3999 ////////////////////////////////////////////////////////////////////////////////
4000 /// Declare a virtual module.map to clang. Returns Module on success.
4001 
4002 clang::Module* ROOT::TMetaUtils::declareModuleMap(clang::CompilerInstance* CI,
4003  const char* moduleFileName,
4004  const char* headers[])
4005 {
4006  clang::Preprocessor& PP = CI->getPreprocessor();
4007  clang::ModuleMap& ModuleMap = PP.getHeaderSearchInfo().getModuleMap();
4008 
4009  // Set the patch for searching for modules
4010  clang::HeaderSearch& HS = CI->getPreprocessor().getHeaderSearchInfo();
4011  HS.setModuleCachePath(llvm::sys::path::parent_path(moduleFileName));
4012 
4013  llvm::StringRef moduleName = llvm::sys::path::filename(moduleFileName);
4014  moduleName = llvm::sys::path::stem(moduleName);
4015 
4016  std::pair<clang::Module*, bool> modCreation;
4017 
4018  modCreation
4019  = ModuleMap.findOrCreateModule(moduleName.str(),
4020  0 /*Parent*/,
4021  false /*Framework*/, false /*Explicit*/);
4022  if (!modCreation.second && !strstr(moduleFileName, "/allDict_rdict.pcm")) {
4023  std::cerr << "TMetaUtils::declareModuleMap: "
4024  "Duplicate definition of dictionary module "
4025  << moduleFileName << std::endl;
4026  /*"\nOriginal module was found in %s.", - if only we could...*/
4027  // Go on, add new headers nonetheless.
4028  }
4029 
4030  clang::HeaderSearch& HdrSearch = PP.getHeaderSearchInfo();
4031  for (const char** hdr = headers; hdr && *hdr; ++hdr) {
4032  const clang::DirectoryLookup* CurDir;
4033  const clang::FileEntry* hdrFileEntry
4034  = HdrSearch.LookupFile(*hdr, clang::SourceLocation(),
4035  false /*isAngled*/, 0 /*FromDir*/, CurDir,
4036  llvm::ArrayRef<std::pair<const clang::FileEntry *,
4037  const clang::DirectoryEntry *>>(),
4038  0 /*SearchPath*/, 0 /*RelativePath*/,
4039  0 /*RequestingModule*/, 0 /*SuggestedModule*/,
4040  false /*SkipCache*/, false /*BuildSystemModule*/,
4041  false /*OpenFile*/, true /*CacheFailures*/);
4042  if (!hdrFileEntry) {
4043  std::cerr << "TMetaUtils::declareModuleMap: "
4044  "Cannot find header file " << *hdr
4045  << " included in dictionary module "
4046  << moduleName.str()
4047  << " in include search path!";
4048  hdrFileEntry = PP.getFileManager().getFile(*hdr, /*OpenFile=*/false,
4049  /*CacheFailure=*/false);
4050  } else if (getenv("ROOT_MODULES")) {
4051  // Tell HeaderSearch that the header's directory has a module.map
4052  llvm::StringRef srHdrDir(hdrFileEntry->getName());
4053  srHdrDir = llvm::sys::path::parent_path(srHdrDir);
4054  const clang::DirectoryEntry* Dir
4055  = PP.getFileManager().getDirectory(srHdrDir);
4056  if (Dir) {
4057  HdrSearch.setDirectoryHasModuleMap(Dir);
4058  }
4059  }
4060 
4061  ModuleMap.addHeader(modCreation.first,
4062  clang::Module::Header{*hdr,hdrFileEntry},
4063  clang::ModuleMap::NormalHeader);
4064  } // for headers
4065  return modCreation.first;
4066 }
4067 
4068 int dumpDeclForAssert(const clang::Decl& D, const char* commentStart) {
4069  llvm::errs() << llvm::StringRef(commentStart, 80) << '\n';
4070  D.dump();
4071  return 0;
4072 }
4073 
4074 ////////////////////////////////////////////////////////////////////////////////
4075 /// Returns the comment (// striped away), annotating declaration in a meaningful
4076 /// for ROOT IO way.
4077 /// Takes optional out parameter clang::SourceLocation returning the source
4078 /// location of the comment.
4079 ///
4080 /// CXXMethodDecls, FieldDecls and TagDecls are annotated.
4081 /// CXXMethodDecls declarations and FieldDecls are annotated as follows:
4082 /// Eg. void f(); // comment1
4083 /// int member; // comment2
4084 /// Inline definitions of CXXMethodDecls after the closing } \n. Eg:
4085 /// void f()
4086 /// {...} // comment3
4087 /// TagDecls are annotated in the end of the ClassDef macro. Eg.
4088 /// class MyClass {
4089 /// ...
4090 /// ClassDef(MyClass, 1) // comment4
4091 ///
4092 
4093 llvm::StringRef ROOT::TMetaUtils::GetComment(const clang::Decl &decl, clang::SourceLocation *loc)
4094 {
4095  clang::SourceManager& sourceManager = decl.getASTContext().getSourceManager();
4096  clang::SourceLocation sourceLocation = decl.getLocEnd();
4097 
4098  // If the location is a macro get the expansion location.
4099  sourceLocation = sourceManager.getExpansionRange(sourceLocation).second;
4100  if (sourceManager.isLoadedSourceLocation(sourceLocation)) {
4101  // Do not touch disk for nodes coming from the PCH.
4102  return "";
4103  }
4104 
4105  bool invalid;
4106  const char *commentStart = sourceManager.getCharacterData(sourceLocation, &invalid);
4107  if (invalid)
4108  return "";
4109 
4110  bool skipToSemi = true;
4111  if (const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(&decl)) {
4112  if (FD->isImplicit()) {
4113  // Compiler generated function.
4114  return "";
4115  }
4116  if (FD->isExplicitlyDefaulted() || FD->isDeletedAsWritten()) {
4117  // ctorOrFunc() = xyz; with commentStart pointing somewhere into
4118  // ctorOrFunc.
4119  // We have to skipToSemi
4120  } else if (FD->doesThisDeclarationHaveABody()) {
4121  // commentStart is at body's '}'
4122  // But we might end up e.g. at the ')' of a CPP macro
4123  assert((decl.getLocEnd() != sourceLocation || *commentStart == '}'
4124  || dumpDeclForAssert(*FD, commentStart))
4125  && "Expected macro or end of body at '}'");
4126  if (*commentStart) ++commentStart;
4127 
4128  // We might still have a ';'; skip the spaces and check.
4129  while (*commentStart && isspace(*commentStart)
4130  && *commentStart != '\n' && *commentStart != '\r') {
4131  ++commentStart;
4132  }
4133  if (*commentStart == ';') ++commentStart;
4134 
4135  skipToSemi = false;
4136  }
4137  } else if (const clang::EnumConstantDecl* ECD
4138  = clang::dyn_cast<clang::EnumConstantDecl>(&decl)) {
4139  // either "konstant = 12, //COMMENT" or "lastkonstant // COMMENT"
4140  if (ECD->getNextDeclInContext())
4141  while (*commentStart && *commentStart != ',' && *commentStart != '\r' && *commentStart != '\n')
4142  ++commentStart;
4143  // else commentStart already points to the end.
4144 
4145  skipToSemi = false;
4146  }
4147 
4148  if (skipToSemi) {
4149  while (*commentStart && *commentStart != ';' && *commentStart != '\r' && *commentStart != '\n')
4150  ++commentStart;
4151  if (*commentStart == ';') ++commentStart;
4152  }
4153 
4154  // Now skip the spaces until beginning of comments or EOL.
4155  while ( *commentStart && isspace(*commentStart)
4156  && *commentStart != '\n' && *commentStart != '\r') {
4157  ++commentStart;
4158  }
4159 
4160  if (commentStart[0] != '/' ||
4161  (commentStart[1] != '/' && commentStart[1] != '*')) {
4162  // not a comment
4163  return "";
4164  }
4165 
4166  // Treat by default c++ comments (+2) but also Doxygen comments (+4)
4167  // Int_t fPx; ///< Some doxygen comment for persistent data.
4168  // Int_t fPy; //!< Some doxygen comment for persistent data.
4169  // Int_t fPz; /*!< Some doxygen comment for persistent data. */
4170  // Int_t fPa; /**< Some doxygen comment for persistent data. */
4171  unsigned int skipChars = 2;
4172  if (commentStart[0] == '/' &&
4173  commentStart[1] == '/' &&
4174  (commentStart[2] == '/' || commentStart[2] == '!') &&
4175  commentStart[3] == '<') {
4176  skipChars = 4;
4177  } else if (commentStart[0] == '/' &&
4178  commentStart[1] == '*' &&
4179  (commentStart[2] == '*' || commentStart[2] == '!') &&
4180  commentStart[3] == '<') {
4181  skipChars = 4;
4182  }
4183 
4184  commentStart += skipChars;
4185 
4186  // Now skip the spaces after comment start until EOL.
4187  while ( *commentStart && isspace(*commentStart)
4188  && *commentStart != '\n' && *commentStart != '\r') {
4189  ++commentStart;
4190  }
4191  const char* commentEnd = commentStart;
4192  // Even for /* comments we only take the first line into account.
4193  while (*commentEnd && *commentEnd != '\n' && *commentEnd != '\r') {
4194  ++commentEnd;
4195  }
4196 
4197  // "Skip" (don't include) trailing space.
4198  // *commentEnd points behind comment end thus check commentEnd[-1]
4199  while (commentEnd > commentStart && isspace(commentEnd[-1])) {
4200  --commentEnd;
4201  }
4202 
4203  if (loc) {
4204  // Find the true beginning of a comment.
4205  unsigned offset = commentStart - sourceManager.getCharacterData(sourceLocation);
4206  *loc = sourceLocation.getLocWithOffset(offset - 1);
4207  }
4208 
4209  return llvm::StringRef(commentStart, commentEnd - commentStart);
4210 }
4211 
4212 ////////////////////////////////////////////////////////////////////////////////
4213 /// Return the class comment after the ClassDef:
4214 /// class MyClass {
4215 /// ...
4216 /// ClassDef(MyClass, 1) // class comment
4217 ///
4218 
4219 llvm::StringRef ROOT::TMetaUtils::GetClassComment(const clang::CXXRecordDecl &decl,
4220  clang::SourceLocation *loc,
4221  const cling::Interpreter &interpreter)
4222 {
4223  using namespace clang;
4224  SourceLocation commentSLoc;
4225  llvm::StringRef comment;
4226 
4227  Sema& sema = interpreter.getCI()->getSema();
4228 
4229  const Decl* DeclFileLineDecl
4230  = interpreter.getLookupHelper().findFunctionProto(&decl, "DeclFileLine", "",
4231  cling::LookupHelper::NoDiagnostics);
4232  if (!DeclFileLineDecl) return llvm::StringRef();
4233 
4234  // For now we allow only a special macro (ClassDef) to have meaningful comments
4235  SourceLocation maybeMacroLoc = DeclFileLineDecl->getLocation();
4236  bool isClassDefMacro = maybeMacroLoc.isMacroID() && sema.findMacroSpelling(maybeMacroLoc, "ClassDef");
4237  if (isClassDefMacro) {
4238  comment = ROOT::TMetaUtils::GetComment(*DeclFileLineDecl, &commentSLoc);
4239  if (comment.size()) {
4240  if (loc){
4241  *loc = commentSLoc;
4242  }
4243  return comment;
4244  }
4245  }
4246  return llvm::StringRef();
4247 }
4248 
4249 ////////////////////////////////////////////////////////////////////////////////
4250 /// Return the base/underlying type of a chain of array or pointers type.
4251 /// Does not yet support the array and pointer part being intermixed.
4252 
4254 {
4255  const clang::Type *rawtype = type.getTypePtr();
4256 
4257  // NOTE: We probably meant isa<clang::ElaboratedType>
4258  if (rawtype->isElaboratedTypeSpecifier() ) {
4259  rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4260  }
4261  if (rawtype->isArrayType()) {
4262  rawtype = type.getTypePtr()->getBaseElementTypeUnsafe ();
4263  }
4264  if (rawtype->isPointerType() || rawtype->isReferenceType() ) {
4265  //Get to the 'raw' type.
4266  clang::QualType pointee;
4267  while ( (pointee = rawtype->getPointeeType()) , pointee.getTypePtrOrNull() && pointee.getTypePtr() != rawtype)
4268  {
4269  rawtype = pointee.getTypePtr();
4270 
4271  if (rawtype->isElaboratedTypeSpecifier() ) {
4272  rawtype = rawtype->getCanonicalTypeInternal().getTypePtr();
4273  }
4274  if (rawtype->isArrayType()) {
4275  rawtype = rawtype->getBaseElementTypeUnsafe ();
4276  }
4277  }
4278  }
4279  if (rawtype->isArrayType()) {
4280  rawtype = rawtype->getBaseElementTypeUnsafe ();
4281  }
4282  return rawtype;
4283 }
4284 
4285 ////////////////////////////////////////////////////////////////////////////////
4286 /// Return true, if the decl is part of the std namespace.
4287 
4288 bool ROOT::TMetaUtils::IsStdClass(const clang::RecordDecl &cl)
4289 {
4291 }
4292 
4293 ////////////////////////////////////////////////////////////////////////////////
4294 /// Return true, if the decl is part of the std namespace and we want
4295 /// its default parameter dropped.
4296 
4297 bool ROOT::TMetaUtils::IsStdDropDefaultClass(const clang::RecordDecl &cl)
4298 {
4299  // Might need to reduce it to shared_ptr and STL collection.s
4301  static const char *names[] =
4302  { "shared_ptr", "__shared_ptr",
4303  "vector", "list", "deque", "map", "multimap", "set", "multiset", "bitset"};
4304  llvm::StringRef clname(cl.getName());
4305  for(auto &&name : names) {
4306  if (clname == name) return true;
4307  }
4308  }
4309  return false;
4310 }
4311 
4312 ////////////////////////////////////////////////////////////////////////////////
4313 /// This is a recursive function
4314 
4315 bool ROOT::TMetaUtils::MatchWithDeclOrAnyOfPrevious(const clang::CXXRecordDecl &cl,
4316  const clang::CXXRecordDecl &currentCl)
4317 {
4318  // We found it: let's return true
4319  if (&cl == &currentCl) return true;
4320 
4321  const clang::CXXRecordDecl* previous = currentCl.getPreviousDecl();
4322 
4323  // There is no previous decl, so we cannot possibly find it
4324  if (NULL == previous){
4325  return false;
4326  }
4327 
4328  // We try to find it in the previous
4329  return ROOT::TMetaUtils::MatchWithDeclOrAnyOfPrevious(cl, *previous);
4330 
4331 }
4332 
4333 //______________________________________________________________________________
4334 
4335 bool ROOT::TMetaUtils::IsOfType(const clang::CXXRecordDecl &cl, const std::string& typ, const cling::LookupHelper& lh)
4336 {
4337  // Return true if the decl is of type.
4338  // A proper hashtable for caching results would be the ideal solution
4339  // 1) Only one lookup per type
4340  // 2) No string comparison
4341  // We may use a map which becomes an unordered map if c++11 is enabled?
4342 
4343  const clang::CXXRecordDecl *thisDecl =
4344  llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(typ, cling::LookupHelper::WithDiagnostics));
4345 
4346  // this would be probably an assert given that this state is not reachable unless a mistake is somewhere
4347  if (! thisDecl){
4348  Error("IsOfType","Record decl of type %s not found in the AST.", typ.c_str());
4349  return false;
4350  }
4351 
4352  // Now loop on all previous decls to seek a match
4353  const clang::CXXRecordDecl *mostRecentDecl = thisDecl->getMostRecentDecl();
4354  bool matchFound = MatchWithDeclOrAnyOfPrevious (cl,*mostRecentDecl);
4355 
4356  return matchFound;
4357 }
4358 
4359 ////////////////////////////////////////////////////////////////////////////////
4360 /// type : type name: vector<list<classA,allocator>,allocator>
4361 /// result: 0 : not stl container
4362 /// abs(result): code of container 1=vector,2=list,3=deque,4=map
4363 /// 5=multimap,6=set,7=multiset
4364 
4365 ROOT::ESTLType ROOT::TMetaUtils::IsSTLCont(const clang::RecordDecl &cl)
4366 {
4367  // This routine could be enhanced to also support:
4368  //
4369  // testAlloc: if true, we test allocator, if it is not default result is negative
4370  // result: 0 : not stl container
4371  // abs(result): code of container 1=vector,2=list,3=deque,4=map
4372  // 5=multimap,6=set,7=multiset
4373  // positive val: we have a vector or list with default allocator to any depth
4374  // like vector<list<vector<int>>>
4375  // negative val: STL container other than vector or list, or non default allocator
4376  // For example: vector<deque<int>> has answer -1
4377 
4378  if (!IsStdClass(cl)) {
4379  return ROOT::kNotSTL;
4380  }
4381 
4382  return STLKind(cl.getName());
4383 }
4384 
4386  using namespace clang;
4387  struct SearchTypedef: public TypeVisitor<SearchTypedef, bool> {
4388  bool VisitTypedefType(const TypedefType* TD) {
4389  return true;
4390  }
4391  bool VisitArrayType(const ArrayType* AT) {
4392  return Visit(AT->getElementType().getTypePtr());
4393  }
4394  bool VisitDecltypeType(const DecltypeType* DT) {
4395  return Visit(DT->getUnderlyingType().getTypePtr());
4396  }
4397  bool VisitPointerType(const PointerType* PT) {
4398  return Visit(PT->getPointeeType().getTypePtr());
4399  }
4400  bool VisitReferenceType(const ReferenceType* RT) {
4401  return Visit(RT->getPointeeType().getTypePtr());
4402  }
4403  bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType* STST) {
4404  return Visit(STST->getReplacementType().getTypePtr());
4405  }
4406  bool VisitTemplateSpecializationType(const TemplateSpecializationType* TST) {
4407  for (int I = 0, N = TST->getNumArgs(); I < N; ++I) {
4408  const TemplateArgument& TA = TST->getArg(I);
4409  if (TA.getKind() == TemplateArgument::Type
4410  && Visit(TA.getAsType().getTypePtr()))
4411  return true;
4412  }
4413  return false;
4414  }
4415  bool VisitTemplateTypeParmType(const TemplateTypeParmType* TTPT) {
4416  return false; // shrug...
4417  }
4418  bool VisitTypeOfType(const TypeOfType* TOT) {
4419  return TOT->getUnderlyingType().getTypePtr();
4420  }
4421  bool VisitElaboratedType(const ElaboratedType* ET) {
4422  NestedNameSpecifier* NNS = ET->getQualifier();
4423  while (NNS) {
4424  if (NNS->getKind() == NestedNameSpecifier::TypeSpec) {
4425  if (Visit(NNS->getAsType()))
4426  return true;
4427  }
4428  NNS = NNS->getPrefix();
4429  }
4430  return Visit(ET->getNamedType().getTypePtr());
4431  }
4432  };
4433 
4434  SearchTypedef ST;
4435  return ST.Visit(T);
4436 }
4437 
4438 ////////////////////////////////////////////////////////////////////////////////
4439 /// Check if 'input' or any of its template parameter was substituted when
4440 /// instantiating the class template instance and replace it with the
4441 /// partially sugared types we have from 'instance'.
4442 
4443 clang::QualType ROOT::TMetaUtils::ReSubstTemplateArg(clang::QualType input, const clang::Type *instance)
4444 {
4445  if (!instance) return input;
4446  // if there is no typedef in instance then there is nothing guiding any
4447  // template parameter typedef replacement.
4448  if (!hasSomeTypedefSomewhere(instance))
4449  return input;
4450 
4451  using namespace llvm;
4452  using namespace clang;
4453  const clang::ASTContext &Ctxt = instance->getAsCXXRecordDecl()->getASTContext();
4454 
4455  // Treat scope (clang::ElaboratedType) if any.
4456  const clang::ElaboratedType* etype
4457  = llvm::dyn_cast<clang::ElaboratedType>(input.getTypePtr());
4458  if (etype) {
4459  // We have to also handle the prefix.
4460 
4461  clang::Qualifiers scope_qualifiers = input.getLocalQualifiers();
4462  assert(instance->getAsCXXRecordDecl()!=0 && "ReSubstTemplateArg only makes sense with a type representing a class.");
4463 
4464  clang::NestedNameSpecifier *scope = ReSubstTemplateArgNNS(Ctxt,etype->getQualifier(),instance);
4465  clang::QualType subTy = ReSubstTemplateArg(clang::QualType(etype->getNamedType().getTypePtr(),0),instance);
4466 
4467  if (scope) subTy = Ctxt.getElaboratedType(clang::ETK_None,scope,subTy);
4468  subTy = Ctxt.getQualifiedType(subTy,scope_qualifiers);
4469  return subTy;
4470  }
4471 
4472  QualType QT = input;
4473 
4474  // In case of Int_t* we need to strip the pointer first, ReSubst and attach
4475  // the pointer once again.
4476  if (isa<clang::PointerType>(QT.getTypePtr())) {
4477  // Get the qualifiers.
4478  Qualifiers quals = QT.getQualifiers();
4479  QualType nQT;
4480  nQT = ReSubstTemplateArg(QT->getPointeeType(),instance);
4481  if (nQT == QT->getPointeeType()) return QT;
4482 
4483  QT = Ctxt.getPointerType(nQT);
4484  // Add back the qualifiers.
4485  QT = Ctxt.getQualifiedType(QT, quals);
4486  return QT;
4487  }
4488 
4489  // In case of Int_t& we need to strip the pointer first, ReSubst and attach
4490  // the reference once again.
4491  if (isa<ReferenceType>(QT.getTypePtr())) {
4492  // Get the qualifiers.
4493  bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
4494  Qualifiers quals = QT.getQualifiers();
4495  QualType nQT;
4496  nQT = ReSubstTemplateArg(QT->getPointeeType(),instance);
4497  if (nQT == QT->getPointeeType()) return QT;
4498 
4499  // Add the r- or l-value reference type back to the desugared one.
4500  if (isLValueRefTy)
4501  QT = Ctxt.getLValueReferenceType(nQT);
4502  else
4503  QT = Ctxt.getRValueReferenceType(nQT);
4504  // Add back the qualifiers.
4505  QT = Ctxt.getQualifiedType(QT, quals);
4506  return QT;
4507  }
4508 
4509  // In case of Int_t[2] we need to strip the array first, ReSubst and attach
4510  // the array once again.
4511  if (isa<clang::ArrayType>(QT.getTypePtr())) {
4512  // Get the qualifiers.
4513  Qualifiers quals = QT.getQualifiers();
4514 
4515  if (isa<ConstantArrayType>(QT.getTypePtr())) {
4516  const ConstantArrayType *arr = dyn_cast<ConstantArrayType>(QT.getTypePtr());
4517 
4518  QualType newQT= ReSubstTemplateArg(arr->getElementType(),instance);
4519 
4520  if (newQT == arr->getElementType()) return QT;
4521  QT = Ctxt.getConstantArrayType (newQT,
4522  arr->getSize(),
4523  arr->getSizeModifier(),
4524  arr->getIndexTypeCVRQualifiers());
4525 
4526  } else if (isa<DependentSizedArrayType>(QT.getTypePtr())) {
4527  const DependentSizedArrayType *arr = dyn_cast<DependentSizedArrayType>(QT.getTypePtr());
4528 
4529  QualType newQT = ReSubstTemplateArg(arr->getElementType(),instance);
4530 
4531  if (newQT == QT) return QT;
4532  QT = Ctxt.getDependentSizedArrayType (newQT,
4533  arr->getSizeExpr(),
4534  arr->getSizeModifier(),
4535  arr->getIndexTypeCVRQualifiers(),
4536  arr->getBracketsRange());
4537 
4538  } else if (isa<IncompleteArrayType>(QT.getTypePtr())) {
4539  const IncompleteArrayType *arr
4540  = dyn_cast<IncompleteArrayType>(QT.getTypePtr());
4541 
4542  QualType newQT = ReSubstTemplateArg(arr->getElementType(),instance);
4543 
4544  if (newQT == arr->getElementType()) return QT;
4545  QT = Ctxt.getIncompleteArrayType (newQT,
4546  arr->getSizeModifier(),
4547  arr->getIndexTypeCVRQualifiers());
4548 
4549  } else if (isa<VariableArrayType>(QT.getTypePtr())) {
4550  const VariableArrayType *arr
4551  = dyn_cast<VariableArrayType>(QT.getTypePtr());
4552 
4553  QualType newQT = ReSubstTemplateArg(arr->getElementType(),instance);
4554 
4555  if (newQT == arr->getElementType()) return QT;
4556  QT = Ctxt.getVariableArrayType (newQT,
4557  arr->getSizeExpr(),
4558  arr->getSizeModifier(),
4559  arr->getIndexTypeCVRQualifiers(),
4560  arr->getBracketsRange());
4561  }
4562 
4563  // Add back the qualifiers.
4564  QT = Ctxt.getQualifiedType(QT, quals);
4565  return QT;
4566  }
4567 
4568  // If the instance is also an elaborated type, we need to skip
4569  etype = llvm::dyn_cast<clang::ElaboratedType>(instance);
4570  if (etype) {
4571  instance = etype->getNamedType().getTypePtr();
4572  if (!instance) return input;
4573  }
4574 
4575  const clang::TemplateSpecializationType* TST
4576  = llvm::dyn_cast<const clang::TemplateSpecializationType>(instance);
4577 
4578  if (!TST) return input;
4579 
4580  const clang::ClassTemplateSpecializationDecl* TSTdecl
4581  = llvm::dyn_cast_or_null<const clang::ClassTemplateSpecializationDecl>(instance->getAsCXXRecordDecl());
4582 
4583  const clang::SubstTemplateTypeParmType *substType
4584  = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(input.getTypePtr());
4585 
4586  if (substType) {
4587  // Make sure it got replaced from this template
4588  const clang::ClassTemplateDecl *replacedCtxt = 0;
4589 
4590  const clang::DeclContext *replacedDeclCtxt = substType->getReplacedParameter()->getDecl()->getDeclContext();
4591  const clang::CXXRecordDecl *decl = llvm::dyn_cast<clang::CXXRecordDecl>(replacedDeclCtxt);
4592  unsigned int index = substType->getReplacedParameter()->getIndex();
4593  if (decl) {
4594 
4595  if (decl->getKind() == clang::Decl::ClassTemplatePartialSpecialization) {
4596  const clang::ClassTemplatePartialSpecializationDecl *spec = llvm::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(decl);
4597 
4598  unsigned int depth = substType->getReplacedParameter()->getDepth();
4599 
4600  const TemplateArgument *instanceArgs = spec->getTemplateArgs().data();
4601  unsigned int instanceNArgs = spec->getTemplateArgs().size();
4602 
4603  // Search for the 'right' replacement.
4604 
4605  for(unsigned int A = 0; A < instanceNArgs; ++A) {
4606  if (instanceArgs[A].getKind() == clang::TemplateArgument::Type) {
4607  clang::QualType argQualType = instanceArgs[A].getAsType();
4608 
4609  const clang::TemplateTypeParmType *replacementType;
4610 
4611  replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(argQualType);
4612 
4613  if (!replacementType) {
4614  const clang::SubstTemplateTypeParmType *argType
4615  = llvm::dyn_cast<clang::SubstTemplateTypeParmType>(argQualType);
4616  if (argType) {
4617  clang::QualType replacementQT = argType->getReplacementType();
4618  replacementType = llvm::dyn_cast<clang::TemplateTypeParmType>(replacementQT);
4619  }
4620  }
4621  if (replacementType &&
4622  depth == replacementType->getDepth() &&
4623  index == replacementType->getIndex() )
4624  {
4625  index = A;
4626  break;
4627  }
4628  }
4629  }
4630  replacedCtxt = spec->getSpecializedTemplate();
4631  } else {
4632  replacedCtxt = decl->getDescribedClassTemplate();
4633  }
4634  } else {
4635  replacedCtxt = llvm::dyn_cast<clang::ClassTemplateDecl>(replacedDeclCtxt);
4636  }
4637 
4638  if (replacedCtxt->getCanonicalDecl() == TSTdecl->getSpecializedTemplate()->getCanonicalDecl()
4639  || /* the following is likely just redundant */
4640  substType->getReplacedParameter()->getDecl()
4641  == TSTdecl->getSpecializedTemplate ()->getTemplateParameters()->getParam(index))
4642  {
4643  if ( index >= TST->getNumArgs() ) {
4644  // The argument replaced was a default template argument that is
4645  // being listed as part of the instance ...
4646  // so we probably don't really know how to spell it ... we would need to recreate it
4647  // (See AddDefaultParameters).
4648  return input;
4649  } else {
4650  return TST->getArg(index).getAsType();
4651  }
4652  }
4653  }
4654  // Maybe a class template instance, recurse and rebuild
4655  const clang::TemplateSpecializationType* inputTST
4656  = llvm::dyn_cast<const clang::TemplateSpecializationType>(input.getTypePtr());
4657  const clang::ASTContext& astCtxt = TSTdecl->getASTContext();
4658 
4659  if (inputTST) {
4660  bool mightHaveChanged = false;
4661  llvm::SmallVector<clang::TemplateArgument, 4> desArgs;
4662  for(clang::TemplateSpecializationType::iterator I = inputTST->begin(), E = inputTST->end();
4663  I != E; ++I) {
4664  if (I->getKind() != clang::TemplateArgument::Type) {
4665  desArgs.push_back(*I);
4666  continue;
4667  }
4668 
4669  clang::QualType SubTy = I->getAsType();
4670  // Check if the type needs more desugaring and recurse.
4671  if (llvm::isa<clang::SubstTemplateTypeParmType>(SubTy)
4672  || llvm::isa<clang::TemplateSpecializationType>(SubTy)) {
4673  clang::QualType newSubTy = ReSubstTemplateArg(SubTy,instance);
4674  mightHaveChanged = SubTy != newSubTy;
4675  if (!newSubTy.isNull()) {
4676  desArgs.push_back(clang::TemplateArgument(newSubTy));
4677  }
4678  } else
4679  desArgs.push_back(*I);
4680  }
4681 
4682  // If desugaring happened allocate new type in the AST.
4683  if (mightHaveChanged) {
4684  clang::Qualifiers qualifiers = input.getLocalQualifiers();
4685  input = astCtxt.getTemplateSpecializationType(inputTST->getTemplateName(),
4686  desArgs.data(),
4687  desArgs.size(),
4688  inputTST->getCanonicalTypeInternal());
4689  input = astCtxt.getQualifiedType(input, qualifiers);
4690  }
4691  }
4692 
4693  return input;
4694 }
4695 
4696 ////////////////////////////////////////////////////////////////////////////////
4697 /// Remove the last n template arguments from the name
4698 
4699 int ROOT::TMetaUtils::RemoveTemplateArgsFromName(std::string& name, unsigned int nArgsToRemove)
4700 {
4701  if ( nArgsToRemove == 0 || name == "")
4702  return 0;
4703 
4704  // We proceed from the right to the left, counting commas which are not
4705  // enclosed by < >.
4706  const unsigned int length = name.length();
4707  unsigned int cur=0; // let's start beyond the first > from the right
4708  unsigned int nArgsRemoved=0;
4709  unsigned int nBraces=0;
4710  char c='@';
4711  while (nArgsRemoved!=nArgsToRemove && cur<length){
4712  c = name[cur];
4713  if (c == '<') nBraces++;
4714  if (c == '>') nBraces--;
4715  if (c == ',' && nBraces==1 /*So we are not in a sub-template*/) nArgsRemoved++;
4716  cur++;
4717  }
4718  cur--;
4719  name = name.substr(0,cur)+">";
4720  return 0;
4721 
4722 }
4723 
4724 ////////////////////////////////////////////////////////////////////////////////
4725 /// Converts STL container name to number. vector -> 1, etc..
4726 
4727 ROOT::ESTLType ROOT::TMetaUtils::STLKind(const llvm::StringRef type)
4728 {
4729  static const char *stls[] = //container names
4730  {"any","vector","list", "deque","map","multimap","set","multiset","bitset",
4731  "forward_list","unordered_set","unordered_multiset","unordered_map","unordered_multimap",0};
4732  static const ROOT::ESTLType values[] =
4742  };
4743  // kind of stl container
4744  for(int k=1;stls[k];k++) {if (type.equals(stls[k])) return values[k];}
4745  return ROOT::kNotSTL;
4746 }
4747 
4748 ////////////////////////////////////////////////////////////////////////////////
4749 
4750 const clang::TypedefNameDecl* ROOT::TMetaUtils::GetAnnotatedRedeclarable(const clang::TypedefNameDecl* TND)
4751 {
4752  if (!TND)
4753  return 0;
4754 
4755  TND = TND->getMostRecentDecl();
4756  while (TND && !(TND->hasAttrs()))
4757  TND = TND->getPreviousDecl();
4758 
4759  return TND;
4760 }
4761 
4762 ////////////////////////////////////////////////////////////////////////////////
4763 
4764 const clang::TagDecl* ROOT::TMetaUtils::GetAnnotatedRedeclarable(const clang::TagDecl* TD)
4765 {
4766  if (!TD)
4767  return 0;
4768 
4769  TD = TD->getMostRecentDecl();
4770  while (TD && !(TD->hasAttrs() && TD->isThisDeclarationADefinition()))
4771  TD = TD->getPreviousDecl();
4772 
4773  return TD;
4774 }
4775 
4776 ////////////////////////////////////////////////////////////////////////////////
4777 /// Extract the immediately outer namespace and then launch the recursion
4778 
4780  std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4781 {
4782  const clang::DeclContext* enclosingNamespaceDeclCtxt = decl.getDeclContext();
4783  if (!enclosingNamespaceDeclCtxt) return;
4784 
4785  const clang::NamespaceDecl* enclosingNamespace =
4786  clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4787  if (!enclosingNamespace) return;
4788 
4789  enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4790  enclosingNamespace->isInline()));
4791 
4792  ExtractCtxtEnclosingNameSpaces(*enclosingNamespace, enclosingNamespaces);
4793 
4794 }
4795 
4796 ////////////////////////////////////////////////////////////////////////////////
4797 /// Extract enclosing namespaces recusrively
4798 
4799 void ROOT::TMetaUtils::ExtractCtxtEnclosingNameSpaces(const clang::DeclContext& ctxt,
4800  std::list<std::pair<std::string,bool> >& enclosingNamespaces)
4801 {
4802  const clang::DeclContext* enclosingNamespaceDeclCtxt = ctxt.getParent ();
4803 
4804  // If no parent is found, nothing more to be done
4805  if (!enclosingNamespaceDeclCtxt) {
4806  return;
4807  }
4808 
4809  // Check if the parent is a namespace (it could be a class for example)
4810  // if not, nothing to be done here
4811  const clang::NamespaceDecl* enclosingNamespace = clang::dyn_cast<clang::NamespaceDecl>(enclosingNamespaceDeclCtxt);
4812  if (!enclosingNamespace) return;
4813 
4814  // Add to the list of parent namespaces
4815  enclosingNamespaces.push_back(std::make_pair(enclosingNamespace->getNameAsString(),
4816  enclosingNamespace->isInline()));
4817 
4818  // here the recursion
4819  ExtractEnclosingNameSpaces(*enclosingNamespace, enclosingNamespaces);
4820 }
4821 
4822 ////////////////////////////////////////////////////////////////////////////////
4823 /// Extract the names and types of containing scopes.
4824 /// Stop if a class is met and return its pointer.
4825 
4826 const clang::RecordDecl* ROOT::TMetaUtils::ExtractEnclosingScopes(const clang::Decl& decl,
4827  std::list<std::pair<std::string,unsigned int> >& enclosingSc)
4828 {
4829  const clang::DeclContext* enclosingDeclCtxt = decl.getDeclContext();
4830  if (!enclosingDeclCtxt) return 0;
4831 
4832  unsigned int scopeType;
4833 
4834  if (auto enclosingNamespacePtr =
4835  clang::dyn_cast<clang::NamespaceDecl>(enclosingDeclCtxt)){
4836  scopeType= enclosingNamespacePtr->isInline() ? 1 : 0; // inline or simple namespace
4837  enclosingSc.push_back(std::make_pair(enclosingNamespacePtr->getNameAsString(),scopeType));
4838  return ExtractEnclosingScopes(*enclosingNamespacePtr, enclosingSc);
4839  }
4840 
4841  if (auto enclosingClassPtr =
4842  clang::dyn_cast<clang::RecordDecl>(enclosingDeclCtxt)){
4843  return enclosingClassPtr;
4844  }
4845 
4846  return nullptr;
4847 
4848 }
4849 
4850 ////////////////////////////////////////////////////////////////////////////////
4851 /// Reimplementation of TSystem::ExpandPathName() that cannot be
4852 /// used from TMetaUtils.
4853 
4854 static void replaceEnvVars(const char* varname, std::string& txt)
4855 {
4856  std::string::size_type beginVar = 0;
4857  std::string::size_type endVar = 0;
4858  while ((beginVar = txt.find('$', beginVar)) != std::string::npos
4859  && beginVar + 1 < txt.length()) {
4860  std::string::size_type beginVarName = beginVar + 1;
4861  std::string::size_type endVarName = std::string::npos;
4862  if (txt[beginVarName] == '(') {
4863  // "$(VARNAME)" style.
4864  endVarName = txt.find(')', beginVarName);
4865  ++beginVarName;
4866  if (endVarName == std::string::npos) {
4867  ROOT::TMetaUtils::Error(0, "Missing ')' for '$(' in $%s at %s\n",
4868  varname, txt.c_str() + beginVar);
4869  return;
4870  }
4871  endVar = endVarName + 1;
4872  } else {
4873  // "$VARNAME/..." style.
4874  beginVarName = beginVar + 1;
4875  endVarName = beginVarName;
4876  while (isalnum(txt[endVarName]) || txt[endVarName] == '_')
4877  ++endVarName;
4878  endVar = endVarName;
4879  }
4880 
4881  const char* val = getenv(txt.substr(beginVarName,
4882  endVarName - beginVarName).c_str());
4883  if (!val) val = "";
4884 
4885  txt.replace(beginVar, endVar - beginVar, val);
4886  int lenval = strlen(val);
4887  int delta = lenval - (endVar - beginVar); // these many extra chars,
4888  endVar += delta; // advance the end marker accordingly.
4889 
4890  // Look for the next one
4891  beginVar = endVar + 1;
4892  }
4893 }
4894 
4895 ////////////////////////////////////////////////////////////////////////////////
4896 /// Organise the parameters for cling in order to guarantee relocatability
4897 /// It treats the gcc toolchain and the root include path
4898 /// FIXME: enables relocatability for experiments' framework headers until PCMs
4899 /// are available.
4900 
4901 void ROOT::TMetaUtils::SetPathsForRelocatability(std::vector<std::string>& clingArgs )
4902 {
4903  const char* envInclPath = getenv("ROOT_INCLUDE_PATH");
4904 
4905  if (!envInclPath)
4906  return;
4907  std::istringstream envInclPathsStream(envInclPath);
4908  std::string inclPath;
4909  while (std::getline(envInclPathsStream, inclPath, ':')) {
4910  // Can't use TSystem in here; re-implement TSystem::ExpandPathName().
4911  replaceEnvVars("ROOT_INCLUDE_PATH", inclPath);
4912  if (!inclPath.empty()) {
4913  clingArgs.push_back("-I");
4914  clingArgs.push_back(inclPath);
4915  }
4916  }
4917 }
4918 
4919 ////////////////////////////////////////////////////////////////////////////////
4920 
4921 void ROOT::TMetaUtils::ReplaceAll(std::string& str, const std::string& from, const std::string& to,bool recurse)
4922 {
4923  if(from.empty())
4924  return;
4925  size_t start_pos = 0;
4926  bool changed=true;
4927  while (changed){
4928  changed=false;
4929  start_pos = 0;
4930  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
4931  str.replace(start_pos, from.length(), to);
4932  start_pos += to.length();
4933  if (recurse) changed = true;
4934  }
4935  }
4936 }
4937 
4938 ////////////////////////////////////////////////////////////////////////////////
4939 /// Return the separator suitable for this platform.
4940 /// To be replaced at the next llvm upgrade by
4941 /// const StringRef llvm::sys::path::get_separator()
4942 
4944 {
4945 #ifdef WIN32
4946  static const std::string gPathSeparator ("\\");
4947 #else
4948  static const std::string gPathSeparator ("/");
4949 #endif
4950  return gPathSeparator;
4951 }
4952 
4953 ////////////////////////////////////////////////////////////////////////////////
4954 
4955 bool ROOT::TMetaUtils::EndsWith(const std::string &theString, const std::string &theSubstring)
4956 {
4957  if (theString.size() < theSubstring.size()) return false;
4958  const unsigned int theSubstringSize = theSubstring.size();
4959  return 0 == theString.compare(theString.size() - theSubstringSize,
4960  theSubstringSize,
4961  theSubstring);
4962 }
4963 
4964 ////////////////////////////////////////////////////////////////////////////////
4965 
4966 bool ROOT::TMetaUtils::BeginsWith(const std::string &theString, const std::string &theSubstring)
4967 {
4968  if (theString.size() < theSubstring.size()) return false;
4969  const unsigned int theSubstringSize = theSubstring.size();
4970  return 0 == theString.compare(0,
4971  theSubstringSize,
4972  theSubstring);
4973 }
4974 
4975 
4976 ////////////////////////////////////////////////////////////////////////////////
4977 
4978 const std::string ROOT::TMetaUtils::AST2SourceTools::Decls2FwdDecls(const std::vector<const clang::Decl *> &decls, cling::Interpreter::IgnoreFilesFunc_t ignoreFiles, const cling::Interpreter &interp)
4979 {
4980  clang::Sema &sema = interp.getSema();
4981  cling::Transaction theTransaction(sema);
4982  std::set<clang::Decl *> addedDecls;
4983  for (auto decl : decls) {
4984  // again waiting for cling
4985  clang::Decl *ncDecl = const_cast<clang::Decl *>(decl);
4986  theTransaction.append(ncDecl);
4987  }
4988  std::string newFwdDecl;
4989  llvm::raw_string_ostream llvmOstr(newFwdDecl);
4990  interp.forwardDeclare(theTransaction, sema, llvmOstr, true, nullptr, ignoreFiles);
4991  llvmOstr.flush();
4992  return newFwdDecl;
4993 }
4994 
4995 ////////////////////////////////////////////////////////////////////////////////
4996 /// Take the namespaces which enclose the decl and put them around the
4997 /// definition string.
4998 /// For example, if the definition string is "myClass" which is enclosed by
4999 /// the namespaces ns1 and ns2, one would get:
5000 /// namespace ns2{ namespace ns1 { class myClass; } }
5001 
5003  std::string& defString)
5004 {
5005  auto rcd = EncloseInScopes(decl, defString);
5006  return rcd ? 1:0;
5007 }
5008 
5009 ////////////////////////////////////////////////////////////////////////////////
5010 /// Take the scopes which enclose the decl and put them around the
5011 /// definition string.
5012 /// If a class is encountered, bail out.
5013 
5014 const clang::RecordDecl* ROOT::TMetaUtils::AST2SourceTools::EncloseInScopes(const clang::Decl& decl,
5015  std::string& defString)
5016 {
5017  std::list<std::pair<std::string,unsigned int> > enclosingNamespaces;
5018  auto rcdPtr = ROOT::TMetaUtils::ExtractEnclosingScopes(decl,enclosingNamespaces);
5019 
5020  if (rcdPtr) return rcdPtr;
5021 
5022  // Check if we have enclosing namespaces
5023  static const std::string scopeType [] = {"namespace ", "inline namespace ", "class "};
5024 
5025  std::string scopeName;
5026  std::string scopeContent;
5027  unsigned int scopeIndex;
5028  for (auto const & encScope : enclosingNamespaces){
5029  scopeIndex = encScope.second;
5030  scopeName = encScope.first;
5031  scopeContent = " { " + defString + " }";
5032  defString = scopeType[scopeIndex] +
5033  scopeName +
5034  scopeContent;
5035  }
5036  return nullptr;
5037 }
5038 
5039 ////////////////////////////////////////////////////////////////////////////////
5040 /// Loop over the template parameters and build a string for template arguments
5041 /// using the fully qualified name
5042 /// There are different cases:
5043 /// Case 1: a simple template parameter
5044 /// E.g. template<typename T> class A;
5045 /// Case 2: a non-type: either an integer or an enum
5046 /// E.g. template<int I, Foo > class A; where Foo is enum Foo {red, blue};
5047 /// 2 sub cases here:
5048 /// SubCase 2.a: the parameter is an enum: bail out, cannot be treated.
5049 /// SubCase 2.b: use the fully qualified name
5050 /// Case 3: a TemplateTemplate argument
5051 /// E.g. template <template <typename> class T> class container { };
5052 
5054  const clang::TemplateParameterList& tmplParamList,
5055  const cling::Interpreter& interpreter)
5056 {
5057  static const char* paramPackWarning="Template parameter pack found: autoload of variadic templates is not supported yet.\n";
5058 
5059  templateArgs="<";
5060  for (auto prmIt = tmplParamList.begin();
5061  prmIt != tmplParamList.end(); prmIt++){
5062 
5063  if (prmIt != tmplParamList.begin())
5064  templateArgs += ", ";
5065 
5066  auto nDecl = *prmIt;
5067  std::string typeName;
5068 
5069  if(nDecl->isParameterPack ()){
5070  ROOT::TMetaUtils::Warning(0,paramPackWarning);
5071  return 1;
5072  }
5073 
5074  // Case 1
5075  if (llvm::isa<clang::TemplateTypeParmDecl>(nDecl)){
5076  typeName = "typename " + (*prmIt)->getNameAsString();
5077  }
5078  // Case 2
5079  else if (auto nttpd = llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(nDecl)){
5080  auto theType = nttpd->getType();
5081  // If this is an enum, use int as it is impossible to fwd declare and
5082  // this makes sense since it is not a type...
5083  if (theType.getAsString().find("enum") != std::string::npos){
5084  std::string astDump;
5085  llvm::raw_string_ostream ostream(astDump);
5086  nttpd->dump(ostream);
5087  ostream.flush();
5088  ROOT::TMetaUtils::Warning(0,"Forward declarations of templates with enums as template parameters. The responsible class is: %s\n", astDump.c_str());
5089  return 1;
5090  } else {
5092  theType,
5093  interpreter);
5094  }
5095  }
5096  // Case 3: TemplateTemplate argument
5097  else if (auto ttpd = llvm::dyn_cast<clang::TemplateTemplateParmDecl>(nDecl)){
5098  int retCode = FwdDeclFromTmplDecl(*ttpd,interpreter,typeName);
5099  if (retCode!=0){
5100  std::string astDump;
5101  llvm::raw_string_ostream ostream(astDump);
5102  ttpd->dump(ostream);
5103  ostream.flush();
5104  ROOT::TMetaUtils::Error(0,"Cannot reconstruct template template parameter forward declaration for %s\n", astDump.c_str());
5105  return 1;
5106  }
5107  }
5108 
5109  templateArgs += typeName;
5110  }
5111 
5112  templateArgs+=">";
5113  return 0;
5114 }
5115 
5116 ////////////////////////////////////////////////////////////////////////////////
5117 /// Convert a tmplt decl to its fwd decl
5118 
5119 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromTmplDecl(const clang::TemplateDecl& templDecl,
5120  const cling::Interpreter& interpreter,
5121  std::string& defString)
5122 {
5123  std::string templatePrefixString;
5124  auto tmplParamList= templDecl.getTemplateParameters();
5125  if (!tmplParamList){ // Should never happen
5126  Error(0,
5127  "Cannot extract template parameter list for %s",
5128  templDecl.getNameAsString().c_str());
5129  return 1;
5130  }
5131 
5132  int retCode = PrepareArgsForFwdDecl(templatePrefixString,*tmplParamList,interpreter);
5133  if (retCode!=0){
5134  Warning(0,
5135  "Problems with arguments for forward declaration of class %s\n",
5136  templDecl.getNameAsString().c_str());
5137  return retCode;
5138  }
5139  templatePrefixString = "template " + templatePrefixString + " ";
5140 
5141  defString = templatePrefixString + "class " + templDecl.getNameAsString();
5142  if (llvm::isa<clang::TemplateTemplateParmDecl>(&templDecl)) {
5143  // When fwd delcaring the template template arg of
5144  // namespace N { template <template <class T> class C> class X; }
5145  // we don't need to put it into any namespace, and we want no trailing
5146  // ';'
5147  return 0;
5148  }
5149  defString += ';';
5150  return EncloseInNamespaces(templDecl, defString);
5151 }
5152 
5153 ////////////////////////////////////////////////////////////////////////////////
5154 
5155 static int TreatSingleTemplateArg(const clang::TemplateArgument& arg,
5156  std::string& argFwdDecl,
5157  const cling::Interpreter& interpreter,
5158  bool acceptStl=false)
5159 {
5160  using namespace ROOT::TMetaUtils::AST2SourceTools;
5161 
5162  // We do nothing in presence of ints, bools, templates.
5163  // We should probably in presence of templates though...
5164  if (clang::TemplateArgument::Type != arg.getKind()) return 0;
5165 
5166  auto argQualType = arg.getAsType();
5167 
5168  // Recursively remove all *
5169  while (llvm::isa<clang::PointerType>(argQualType.getTypePtr())) argQualType = argQualType->getPointeeType();
5170 
5171  auto argTypePtr = argQualType.getTypePtr();
5172 
5173  // Bail out on enums
5174  if (llvm::isa<clang::EnumType>(argTypePtr)){
5175  return 1;
5176  }
5177 
5178  // If this is a built-in, just return: fwd decl not necessary.
5179  if (llvm::isa<clang::BuiltinType>(argTypePtr)){
5180  return 0;
5181  }
5182 
5183  // Treat typedefs which are arguments
5184  if (llvm::isa<clang::TypedefType>(argTypePtr)){
5185  auto tdTypePtr = llvm::dyn_cast<clang::TypedefType>(argTypePtr);
5186  FwdDeclFromTypeDefNameDecl(*tdTypePtr->getDecl(), interpreter, argFwdDecl);
5187  return 0;
5188  }
5189 
5190  if (llvm::isa<clang::RecordType>(argQualType)){
5191  // Now we cannot but have a RecordType
5192  auto argRecTypePtr = llvm::cast<clang::RecordType>(argTypePtr);
5193  if (auto argRecDeclPtr = argRecTypePtr->getDecl()){
5194  FwdDeclFromRcdDecl(*argRecDeclPtr,interpreter,argFwdDecl,acceptStl);
5195  }
5196  return 0;
5197  }
5198 
5199  return 1;
5200 }
5201 
5202 ////////////////////////////////////////////////////////////////////////////////
5203 /// Convert a rcd decl to its fwd decl
5204 /// If this is a template specialisation, treat in the proper way.
5205 /// If it is contained in a class, just fwd declare the class.
5206 
5207 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromRcdDecl(const clang::RecordDecl& recordDecl,
5208  const cling::Interpreter& interpreter,
5209  std::string& defString,
5210  bool acceptStl)
5211 {
5212  // Do not fwd declare the templates in the stl.
5213  if (ROOT::TMetaUtils::IsStdClass(recordDecl) && !acceptStl)
5214  return 0;
5215 
5216  // Do not fwd declare unnamed decls.
5217  if (!recordDecl.getIdentifier())
5218  return 0;
5219 
5220  // We may need to fwd declare the arguments of the template
5221  std::string argsFwdDecl;
5222 
5223  if (auto tmplSpecDeclPtr = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)){
5224  std::string argFwdDecl;
5226  std::cout << "Class " << recordDecl.getNameAsString()
5227  << " is a template specialisation. Treating its arguments.\n";
5228  for(auto arg : tmplSpecDeclPtr->getTemplateArgs().asArray()){
5229  int retCode = TreatSingleTemplateArg(arg, argFwdDecl, interpreter, acceptStl);
5231  std::cout << " o Template argument ";
5232  if (retCode==0){
5233  std::cout << "successfully treated. Arg fwd decl: " << argFwdDecl << std::endl;
5234  } else {
5235  std::cout << "could not be treated. Abort fwd declaration generation.\n";
5236  }
5237  }
5238 
5239  if (retCode!=0){ // A sign we must bail out
5240  return retCode;
5241  }
5242  argsFwdDecl+=argFwdDecl;
5243  }
5244 
5245  if (acceptStl){
5246  defString=argsFwdDecl;
5247  return 0;
5248  }
5249 
5250  int retCode=0;
5251  if (auto tmplDeclPtr = tmplSpecDeclPtr->getSpecializedTemplate()){
5252  retCode = FwdDeclFromTmplDecl(*tmplDeclPtr,interpreter,defString);
5253  }
5254  defString = argsFwdDecl + "\n" + defString;
5255  return retCode;
5256 
5257  }
5258 
5259  defString = "class " + recordDecl.getNameAsString() + ";";
5260  const clang::RecordDecl* rcd = EncloseInScopes(recordDecl, defString);
5261 
5262  if (rcd){
5263  FwdDeclFromRcdDecl(*rcd, interpreter,defString);
5264  }
5265  // Add a \n here to avoid long lines which contain duplications, for example (from MathCore):
5266  // namespace ROOT { namespace Math { class IBaseFunctionMultiDim; } }namespace ROOT { namespace Fit { template <typename FunType> class Chi2FCN; } }
5267  // namespace ROOT { namespace Math { class IGradientFunctionMultiDim; } }namespace ROOT { namespace Fit { template <typename FunType> class Chi2FCN; } }
5268  defString = argsFwdDecl + "\n" + defString;
5269 
5270  return 0;
5271 }
5272 
5273 ////////////////////////////////////////////////////////////////////////////////
5274 /// Extract "forward declaration" of a typedef.
5275 /// If the typedef is contained in a class, just fwd declare the class.
5276 /// If not, fwd declare the typedef and all the dependent typedefs and types if necessary.
5277 
5278 int ROOT::TMetaUtils::AST2SourceTools::FwdDeclFromTypeDefNameDecl(const clang::TypedefNameDecl& tdnDecl,
5279  const cling::Interpreter& interpreter,
5280  std::string& fwdDeclString,
5281  std::unordered_set<std::string>* fwdDeclSetPtr)
5282 {
5283  std::string buffer = tdnDecl.getNameAsString();
5284  std::string underlyingName;
5285  auto underlyingType = tdnDecl.getUnderlyingType().getCanonicalType();
5286  if (const clang::TagType* TT
5287  = llvm::dyn_cast<clang::TagType>(underlyingType.getTypePtr())) {
5288  if (clang::NamedDecl* ND = TT->getDecl()) {
5289  if (!ND->getIdentifier()) {
5290  // No fwd decl for unnamed underlying entities.
5291  return 0;
5292  }
5293  }
5294  }
5295 
5296  TNormalizedCtxt nCtxt(interpreter.getLookupHelper());
5297  ROOT::TMetaUtils::GetNormalizedName(underlyingName,
5298  underlyingType,
5299  interpreter,
5300  nCtxt);
5301 
5302  // Heuristic: avoid entities like myclass<myType1, myType2::xyz>
5303  if (underlyingName.find(">::") != std::string::npos)
5304  return 0;
5305 
5306  buffer="typedef "+underlyingName+" "+buffer+";";
5307  const clang::RecordDecl* rcd=EncloseInScopes(tdnDecl,buffer);
5308  if (rcd) {
5309  // We do not need the whole series of scopes, just the class.
5310  // It is enough to trigger an uncomplete type autoload/parse callback
5311  // for example: MyClass::blabla::otherNs::myTypedef
5312  return FwdDeclFromRcdDecl(*rcd, interpreter,fwdDeclString,fwdDeclSetPtr);
5313  }
5314 
5315  // Start Recursion if the underlying type is a TypedefNameDecl
5316  // Note: the simple cast w/o the getSingleStepDesugaredType call
5317  // does not work in case the typedef is in a namespace.
5318  auto& ctxt = tdnDecl.getASTContext();
5319  auto immediatelyUnderlyingType = underlyingType.getSingleStepDesugaredType(ctxt);
5320 
5321  if (auto underlyingTdnTypePtr = llvm::dyn_cast<clang::TypedefType>(immediatelyUnderlyingType.getTypePtr())){
5322  std::string tdnFwdDecl;
5323  auto underlyingTdnDeclPtr = underlyingTdnTypePtr->getDecl();
5324  FwdDeclFromTypeDefNameDecl(*underlyingTdnDeclPtr,
5325  interpreter,
5326  tdnFwdDecl,
5327  fwdDeclSetPtr);
5328  if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(tdnFwdDecl).second)
5329  fwdDeclString+=tdnFwdDecl;
5330  } else if (auto CXXRcdDeclPtr = immediatelyUnderlyingType->getAsCXXRecordDecl()){
5331  std::string classFwdDecl;
5333  std::cout << "Typedef " << tdnDecl.getNameAsString() << " hides a class: "
5334  << CXXRcdDeclPtr->getNameAsString() << std::endl;
5335  int retCode = FwdDeclFromRcdDecl(*CXXRcdDeclPtr,
5336  interpreter,
5337  classFwdDecl,
5338  true /* acceptStl*/);
5339  if (retCode!=0){ // bail out
5340  return 0;
5341  }
5342 
5343  if (!fwdDeclSetPtr || fwdDeclSetPtr->insert(classFwdDecl).second)
5344  fwdDeclString+=classFwdDecl;
5345  }
5346 
5347  fwdDeclString+=buffer;
5348 
5349  return 0;
5350 }
5351 
5352 ////////////////////////////////////////////////////////////////////////////////
5353 /// Get the default value as string.
5354 /// Limited at the moment to:
5355 /// - Integers
5356 /// - Booleans
5357 
5359  std::string& valAsString,
5360  const clang::PrintingPolicy& ppolicy)
5361 {
5362  auto defArgExprPtr = par.getDefaultArg();
5363  auto& ctxt = par.getASTContext();
5364  if(!defArgExprPtr->isEvaluatable(ctxt)){
5365  return -1;
5366  }
5367 
5368  auto defArgType = par.getType();
5369 
5370  // The value is a boolean
5371  if (defArgType->isBooleanType()){
5372  bool result;
5373  defArgExprPtr->EvaluateAsBooleanCondition (result,ctxt);
5374  valAsString=std::to_string(result);
5375  return 0;
5376  }
5377 
5378  // The value is an integer
5379  if (defArgType->isIntegerType()){
5380  llvm::APSInt result;
5381  defArgExprPtr->EvaluateAsInt(result,ctxt);
5382  auto uintVal = *result.getRawData();
5383  if (result.isNegative()){
5384  long long int intVal=uintVal*-1;
5385  valAsString=std::to_string(intVal);
5386  } else {
5387  valAsString=std::to_string(uintVal);
5388  }
5389 
5390  return 0;
5391  }
5392 
5393  // The value is something else. We go for the generalised printer
5394  llvm::raw_string_ostream rso(valAsString);
5395  defArgExprPtr->printPretty(rso,nullptr,ppolicy);
5396  valAsString = rso.str();
5397  // We can be in presence of a string. Let's escape the characters properly.
5398  ROOT::TMetaUtils::ReplaceAll(valAsString,"\\\"","__TEMP__VAL__");
5399  ROOT::TMetaUtils::ReplaceAll(valAsString,"\"","\\\"");
5400  ROOT::TMetaUtils::ReplaceAll(valAsString,"__TEMP__VAL__","\\\"");
5401 
5402  return 0;
5403 }
5404 
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 *)
bool CheckPublicFuncWithProto(clang::CXXRecordDecl const *, char const *, char const *, const cling::Interpreter &, bool diagnose)
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
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...
int GetNargsToKeep(const clang::ClassTemplateDecl *templ) const
Definition: TMetaUtils.cxx:337
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 &)
bool HasValidDataMembers(SchemaRuleMap_t &rule, MembersTypeMap_t &members)
Check if given rule contains references to valid data members.
const TypesCont_t & GetTypeWithAlternative() const
Definition: TMetaUtils.cxx:330
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
const Config_t & GetConfig() const
Definition: TMetaUtils.cxx:327
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
const TemplPtrIntMap_t GetTemplNargsToKeepMap() const
Definition: TMetaUtils.cxx:341
bool HasNewMerge(clang::CXXRecordDecl const *, const cling::Interpreter &)
bool IsStdClass(const clang::RecordDecl &cl)
Return true, if the decl is part of the std namespace.
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 &)
static bool isTypeWithDefault(const clang::NamedDecl *nDecl)
Check if this NamedDecl is a template parameter with a default argument.
const clang::RecordDecl * GetRecordDecl() const
Definition: TMetaUtils.h:268
void(* CallWriteStreamer_t)(const AnnotatedRecordDecl &cl, const cling::Interpreter &interp, const TNormalizedCtxt &normCtxt, std::ostream &dictStream, bool isAutoStreamer)
Definition: TMetaUtils.h:104
const clang::FunctionDecl * ClassInfo__HasMethod(const clang::DeclContext *cl, char const *, const cling::Interpreter &interp)
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...
std::string TrueName(const clang::FieldDecl &m)
TrueName strips the typedefs and array dimensions.
#define dest(otri, vertexptr)
Definition: triangle.c:1040
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
const clang::CXXRecordDecl * GetType() const
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):...
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
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.
Definition: TCling.h:48
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
const std::string Decls2FwdDecls(const std::vector< const clang::Decl * > &decls, bool(*ignoreFiles)(const clang::PresumedLoc &), const cling::Interpreter &interp)
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 *)
int & GetErrorIgnoreLevel()
Definition: TMetaUtils.h:721
bool EndsWith(const std::string &theString, const std::string &theSubstring)
const char * GetNormalizedName() const
Definition: TMetaUtils.h:248
const char * GetRequestedName() const
Definition: TMetaUtils.h:247
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)
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::DeclContext * GetEnclosingSpace(const clang::RecordDecl &cl)
bool HasCustomOperatorNewArrayPlacement(clang::RecordDecl const &, const cling::Interpreter &interp)
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 &)
bool HasCustomOperatorNewPlacement(char const *, clang::RecordDecl const &, const cling::Interpreter &)
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 &)
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...