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