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