Logo ROOT  
Reference Guide
Scanner.cxx
Go to the documentation of this file.
1 // @(#)root/utils/src:$Id$
2 // Author: Philippe Canal November 2011 ; originated from Zdenek Culik 16/04/2010 and Velislava Spasova.
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/rootcint. *
10  *************************************************************************/
11 
12 #include "Scanner.h"
13 #include "clang/AST/ASTConsumer.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "clang/Basic/SourceManager.h"
16 #include "llvm/ADT/SmallSet.h"
17 #include "clang/Sema/Sema.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 
20 #include "cling/Interpreter/Interpreter.h"
21 #include "llvm/Support/Path.h"
22 
23 #include "TClassEdit.h"
24 
25 #include <iostream>
26 #include <sstream> // class ostringstream
27 
28 #include "SelectionRules.h"
29 
30 namespace {
31 
32  class RPredicateIsSameNamespace
33  {
34  private:
35  clang::NamespaceDecl *fTarget;
36  public:
37  RPredicateIsSameNamespace(clang::NamespaceDecl *target) : fTarget(target) {}
38 
39  bool operator()(const RScanner::AnnotatedNamespaceDecl& element)
40  {
41  return (fTarget == element);
42  }
43  };
44 
45 template<class T>
46 inline static bool IsElementPresent(const std::vector<T> &v, const T &el){
47  return std::find(v.begin(),v.end(),el) != v.end();
48 }
49 
50 template<class T>
51 inline static bool IsElementPresent(const std::vector<const T*> &v, T *el){
52  return std::find(v.begin(),v.end(),el) != v.end();
53 }
54 
55 }
56 
57 using namespace ROOT;
58 using namespace clang;
59 
60 extern cling::Interpreter *gInterp;
61 
62 const char* RScanner::fgClangDeclKey = "ClangDecl"; // property key used for connection with Clang objects
63 const char* RScanner::fgClangFuncKey = "ClangFunc"; // property key for demangled names
64 
68 
69 std::map <clang::Decl*, std::string> RScanner::fgAnonymousClassMap;
70 std::map <clang::Decl*, std::string> RScanner::fgAnonymousEnumMap;
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 /// Regular constructor setting up the scanner to search for entities
74 /// matching the 'rules'.
75 
77  EScanType stype,
78  const cling::Interpreter &interpret,
80  unsigned int verbose /* = 0 */) :
81  fVerboseLevel(verbose),
82  fSourceManager(nullptr),
83  fInterpreter(interpret),
84  fRecordDeclCallback(nullptr),
85  fNormCtxt(normCtxt),
86  fSelectionRules(rules),
87  fScanType(stype),
88  fFirstPass(true)
89 {
90  // Build the cache for all selection rules
92 
93  for (int i = 0; i <= fgDeclLast; i ++)
94  fDeclTable [i] = false;
95 
96  for (int i = 0; i <= fgTypeLast; i ++)
97  fTypeTable [i] = false;
98 
99  fLastDecl = nullptr;
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 
105 {
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 /// Whether we can actually visit this declaration, i.e. if it is reachable
110 /// via name lookup.
111 ///
112 /// RScanner shouldn't touch decls for which this method returns false as we
113 /// call Sema methods on those declarations. Those will fail in strange way as
114 /// they assume those decls are already visible.
115 ///
116 /// The main problem this is supposed to prevent is when we use C++ modules and
117 /// have hidden declarations in our AST. Usually they can't be found as they are
118 /// hidden from name lookup until their module is actually imported, but as the
119 /// RecursiveASTVisitor is not supposed to be restricted by lookup limitations,
120 /// it still reaches those hidden declarations.
121 bool RScanner::shouldVisitDecl(clang::NamedDecl *D)
122 {
123  if (auto M = D->getOwningModule()) {
124  return fInterpreter.getSema().isModuleVisible(M);
125  }
126  return true;
127 }
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 
131 inline void* ToDeclProp(clang::Decl* item)
132 {
133  /* conversion and type check used by AddProperty */
134  return item;
135 }
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 
139 inline size_t APIntToSize(const llvm::APInt& num)
140 {
141  return *num.getRawData();
142 }
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 
146 inline long APIntToLong(const llvm::APInt& num)
147 {
148  return *num.getRawData();
149 }
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 
153 inline std::string APIntToStr(const llvm::APInt& num)
154 {
155  return num.toString(10, true);
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 
160 inline std::string IntToStr(int num)
161 {
162  std::string txt = "";
163  txt += num;
164  return txt;
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 
169 inline std::string IntToStd(int num)
170 {
171  std::ostringstream stream;
172  stream << num;
173  return stream.str();
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 
178 inline std::string Message(const std::string &msg, const std::string &location)
179 {
180  std::string loc = location;
181 
182  if (loc == "")
183  return msg;
184  else
185  return loc + " " + msg;
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 
190 void RScanner::ShowInfo(const std::string &msg, const std::string &location) const
191 {
192  const std::string message = Message(msg, location);
193  std::cout << message << std::endl;
194 }
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 
198 void RScanner::ShowWarning(const std::string &msg, const std::string &location) const
199 {
200  const std::string message = Message(msg, location);
201  std::cout << message << std::endl;
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 
206 void RScanner::ShowError(const std::string &msg, const std::string &location) const
207 {
208  const std::string message = Message(msg, location);
209  std::cout << message << std::endl;
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 
214 void RScanner::ShowTemplateInfo(const std::string &msg, const std::string &location) const
215 {
216  std::string loc = location;
217  if (loc == "")
218  loc = GetLocation (fLastDecl);
219  ShowWarning(msg, loc);
220 }
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 
224 std::string RScanner::GetSrcLocation(clang::SourceLocation L) const
225 {
226  std::string location = "";
227  llvm::raw_string_ostream stream(location);
228  L.print(stream, *fSourceManager);
229  return stream.str();
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 
234 std::string RScanner::GetLocation(clang::Decl* D) const
235 {
236  if (D == nullptr)
237  {
238  return "";
239  }
240  else
241  {
242  std::string location = "";
243  llvm::raw_string_ostream stream(location);
244  D->getLocation().print(stream, *fSourceManager);
245  return stream.str();
246  }
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 
251 std::string RScanner::GetName(clang::Decl* D) const
252 {
253  std::string name = "";
254  // std::string kind = D->getDeclKindName();
255 
256  if (clang::NamedDecl* ND = dyn_cast <clang::NamedDecl> (D)) {
257  name = ND->getQualifiedNameAsString();
258  }
259 
260  return name;
261 }
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 
265 inline std::string AddSpace(const std::string &txt)
266 {
267  if (txt == "")
268  return "";
269  else
270  return txt + " ";
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 
275 void RScanner::DeclInfo(clang::Decl* D) const
276 {
277  std::string location = GetLocation(D);
278  std::string kind = D->getDeclKindName();
279  std::string name = GetName(D);
280  ShowInfo("Scan: " + kind + " declaration " + name, location);
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// unknown - this kind of declaration was not known to programmer
285 
286 void RScanner::UnknownDecl(clang::Decl* D, const std::string &txt) const
287 {
288  std::string location = GetLocation(D);
289  std::string kind = D->getDeclKindName();
290  std::string name = GetName(D);
291  ShowWarning("Unknown " + AddSpace(txt) + kind + " declaration " + name, location);
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// unexpected - this kind of declaration is unexpected (in concrete place)
296 
297 void RScanner::UnexpectedDecl(clang::Decl* D, const std::string &txt) const
298 {
299  std::string location = GetLocation(D);
300  std::string kind = D->getDeclKindName();
301  std::string name = GetName(D);
302  ShowWarning("Unexpected " + kind + " declaration " + name, location);
303 }
304 
305 ////////////////////////////////////////////////////////////////////////////////
306 /// unsupported - this kind of declaration is probably not used (in current version of C++)
307 
308 void RScanner::UnsupportedDecl(clang::Decl* D, const std::string &txt) const
309 {
310  std::string location = GetLocation(D);
311  std::string kind = D->getDeclKindName();
312  std::string name = GetName(D);
313  ShowWarning("Unsupported " + AddSpace(txt) + kind + " declaration " + name, location);
314 }
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// unimportant - this kind of declaration is not stored into reflex
318 
319 void RScanner::UnimportantDecl(clang::Decl* D, const std::string &txt) const
320 {
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// information about item, that should be implemented
325 
326 void RScanner::UnimplementedDecl(clang::Decl* D, const std::string &txt)
327 {
328  clang::Decl::Kind k = D->getKind();
329 
330  bool show = true;
331  if (k <= fgDeclLast) {
332  if (fDeclTable [k])
333  show = false; // already displayed
334  else
335  fDeclTable [k] = true;
336  }
337 
338  if (show)
339  {
340  std::string location = GetLocation(D);
341  std::string kind = D->getDeclKindName();
342  std::string name = GetName(D);
343  std::string msg = "Unimplemented ";
344  if (txt == "") {
345  msg += "declaration";
346  } else {
347  msg += txt;
348  }
349  msg += ": ";
350  msg += kind;
351  msg += " ";
352  msg += name;
353  ShowWarning(msg,location);
354  }
355 }
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 
359 void RScanner::UnknownType(clang::QualType qual_type) const
360 {
361  std::string location = GetLocation(fLastDecl);
362  std::string kind = qual_type.getTypePtr()->getTypeClassName();
363  ShowWarning("Unknown " + kind + " type " + qual_type.getAsString(), location);
364 }
365 
366 ////////////////////////////////////////////////////////////////////////////////
367 
368 void RScanner::UnsupportedType(clang::QualType qual_type) const
369 {
370  std::string location = GetLocation(fLastDecl);
371  std::string kind = qual_type.getTypePtr()->getTypeClassName();
372  ShowWarning("Unsupported " + kind + " type " + qual_type.getAsString(), location);
373 }
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 
377 std::string RScanner::GetEnumName(clang::EnumDecl* D) const
378 {
379  std::string enum_name = D->getQualifiedNameAsString();
380 
381  if (! D->getDeclName ()) {
382  if (fgAnonymousEnumMap.find (D) != fgAnonymousEnumMap.end())
383  {
384  // already encountered anonymous enumeration type
385  enum_name = fgAnonymousEnumMap [D];
386  }
387  else
388  {
390  enum_name = "_ANONYMOUS_ENUM_" + IntToStd(fgAnonymousEnumCounter) + "_"; // !?
391  fgAnonymousEnumMap [D] = enum_name;
392  // ShowInfo ("anonymous enum " + enum_name, GetLocation (D));
393  }
394  }
395 
396  return enum_name;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////////
400 
401 std::string RScanner::ExprToStr(clang::Expr* expr) const
402 {
403  clang::LangOptions lang_opts;
404  clang::PrintingPolicy print_opts(lang_opts); // !?
405 
406  std::string text = "";
407  llvm::raw_string_ostream stream(text);
408 
409  expr->printPretty(stream, nullptr, print_opts);
410 
411  return stream.str();
412 }
413 
414 ////////////////////////////////////////////////////////////////////////////////
415 
416 std::string RScanner::ConvTemplateName(clang::TemplateName& N) const
417 {
418  clang::LangOptions lang_opts;
419  clang::PrintingPolicy print_opts(lang_opts); // !?
420 
421  std::string text = "";
422  llvm::raw_string_ostream stream(text);
423 
424  N.print(stream, print_opts);
425 
426  return stream.str();
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 
431 std::string RScanner::FuncParameters(clang::FunctionDecl* D) const
432 {
433  std::string result = "";
434 
435  for (clang::FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) {
436  clang::ParmVarDecl* P = *I;
437 
438  if (result != "")
439  result += ";"; // semicolon, not comma, important
440 
441  std::string type = P->getType().getAsString();
442  std::string name = P->getNameAsString();
443 
444  result += type + " " + name;
445 
446  // NO if (P->hasDefaultArg ()) // check hasUnparsedDefaultArg () and hasUninstantiatedDefaultArg ()
447  if (P->getInit()) {
448  std::string init_value = ExprToStr(P->getDefaultArg());
449  result += "=" + init_value;
450  }
451  }
452 
453  return result;
454 }
455 
456 ////////////////////////////////////////////////////////////////////////////////
457 
458 std::string RScanner::FuncParameterList(clang::FunctionDecl* D) const
459 {
460  std::string result = "";
461 
462  for (clang::FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) {
463  clang::ParmVarDecl* P = *I;
464 
465  if (result != "")
466  result += ",";
467 
468  std::string type = P->getType().getAsString();
469  result += type;
470  }
471 
472  return "(" + result + ")";
473 }
474 
475 ////////////////////////////////////////////////////////////////////////////////
476 /// This method visits a namespace node
477 
478 bool RScanner::VisitNamespaceDecl(clang::NamespaceDecl* N)
479 {
480  // We don't need to visit this while creating the big PCM
482  return true;
483 
484  if (!shouldVisitDecl(N))
485  return true;
486 
487  // in case it is implicit we don't create a builder
488  // [Note: Can N be nullptr?, is so 'ShouldVisitDecl' should test or we should test sooner]
489  if((N && N->isImplicit()) || !N){
490  return true;
491  }
492 
493  bool ret = true;
494 
496  if (selected) {
497 
498  clang::DeclContext* primary_ctxt = N->getPrimaryContext();
499  clang::NamespaceDecl* primary = llvm::dyn_cast<clang::NamespaceDecl>(primary_ctxt);
500 
501  RPredicateIsSameNamespace pred(primary);
502  if ( find_if(fSelectedNamespaces.begin(),fSelectedNamespaces.end(),pred) == fSelectedNamespaces.end() ) {
503  // The namespace is not already registered.
504 
505  if (fVerboseLevel > 0) {
506  std::string qual_name;
507  GetDeclQualName(N,qual_name);
508  // std::cout<<"\tSelected namespace -> " << qual_name << " ptr " << (void*)N << " decl ctxt " << (void*)N->getPrimaryContext() << " classname " <<primary->getNameAsString() << "\n";
509  std::cout<<"\tSelected namespace -> " << qual_name << "\n";
510  }
511  fSelectedNamespaces.push_back(AnnotatedNamespaceDecl(primary,selected->GetIndex(),selected->RequestOnlyTClass()));
512  }
513  ret = true;
514  }
515 
516  return ret;
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 
521 bool RScanner::VisitRecordDecl(clang::RecordDecl* D)
522 {
523  if (!shouldVisitDecl(D))
524  return true;
525 
526  // This method visits a class node
528 
529 
530 }
531 
532 ////////////////////////////////////////////////////////////////////////////////
533 
535  const clang::Type* req_type,
536  const clang::RecordDecl* recordDecl,
537  const std::string& attr_name,
538  const clang::TypedefNameDecl* typedefNameDecl,
539  unsigned int indexOffset)
540 {
541 
542  bool has_attr_name = selected->HasAttributeName();
543 
544  if (recordDecl->isUnion() &&
546  std::string normName;
548  recordDecl->getASTContext().getTypeDeclType(recordDecl),
549  fInterpreter,
550  fNormCtxt);
551  ROOT::TMetaUtils::Error(nullptr,"Union %s has been selected for I/O. This is not supported. Interactive usage of unions is supported, as all C++ entities, without the need of dictionaries.\n",normName.c_str());
552  return 1;
553  }
554 
555  if (has_attr_name) {
556  fSelectedClasses.emplace_back(selected->GetIndex() + indexOffset,
557  req_type,
558  recordDecl,
559  attr_name.c_str(),
560  selected->RequestStreamerInfo(),
561  selected->RequestNoStreamer(),
562  selected->RequestNoInputOperator(),
563  selected->RequestOnlyTClass(),
564  selected->RequestedVersionNumber(),
565  fInterpreter,
566  fNormCtxt);
567  } else {
568  fSelectedClasses.emplace_back(selected->GetIndex() + indexOffset,
569  recordDecl,
570  selected->RequestStreamerInfo(),
571  selected->RequestNoStreamer(),
572  selected->RequestNoInputOperator(),
573  selected->RequestOnlyTClass(),
574  selected->RequestedVersionNumber(),
575  fInterpreter,
576  fNormCtxt);
577  }
578 
579  if (fVerboseLevel > 0) {
580  std::string qual_name;
581  GetDeclQualName(recordDecl,qual_name);
582  std::string normName;
584  recordDecl->getASTContext().getTypeDeclType(recordDecl),
585  fInterpreter,
586  fNormCtxt);
587  std::string typedef_qual_name;
588  std::string typedefMsg;
589  if (typedefNameDecl){
590  GetDeclQualName(typedefNameDecl,typedef_qual_name);
591  typedefMsg = "(through typedef/alias " + typedef_qual_name + ") ";
592  }
593 
594  std::cout << "Selected class "
595  << typedefMsg
596  << "-> "
597  << qual_name
598  << " for ROOT: "
599  << normName
600  << "\n";
601  }
602  return 0;
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 
607 bool RScanner::TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl* typeDecl)
608 {
609  // For every class is created a new class buider irrespectful of weather the
610  // class is internal for another class declaration or not.
611  // RecordDecls and TypedefDecls (or RecordDecls!) are treated.
612  // We follow two different codepaths if the typeDecl is a RecordDecl or
613  // a TypedefDecl. If typeDecl is a TypedefDecl, recordDecl becomes the
614  // underlying RecordDecl.
615  // This is done to leverage the selections rule matching in SelectionRules
616  // which works basically with names.
617  // At the end of the method, if the typedef name is matched, an AnnotatedRecordDecl
618  // with the underlying RecordDecl is fed to the machinery.
619 
620  const clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(typeDecl);
621  const clang::TypedefNameDecl* typedefNameDecl = clang::dyn_cast<clang::TypedefNameDecl>(typeDecl);
622 
623  // If typeDecl is not a RecordDecl, try to fetch the RecordDecl behind the TypedefDecl
624  if (!recordDecl && typedefNameDecl) {
625  recordDecl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(typedefNameDecl->getUnderlyingType());
626  }
627 
628  // If at this point recordDecl is still NULL, we have a problem
629  if (!recordDecl) {
630  ROOT::TMetaUtils::Warning("RScanner::TreatRecordDeclOrTypeNameDecl",
631  "Could not cast typeDecl either to RecordDecl or could not get RecordDecl underneath typedef.\n");
632  return true;
633  }
634 
635  // Do not select unnamed records.
636  if (!recordDecl->getIdentifier())
637  return true;
638 
639  // Do not select dependent types.
640  if (recordDecl->isDependentType())
641  return true;
642 
644  return true;
645 
646 
647  // At this point, recordDecl must be a RecordDecl pointer.
648 
649  if (fRecordDeclCallback) {
650  // Pass on any declaration. This is usually used to record dependency.
651  // Since rootcint see C++ compliant header files, we can assume that
652  // if a forward declaration or declaration has been inserted, the
653  // classes for which we are creating a dictionary will be using
654  // them either directly or indirectly. Any false positive can be
655  // resolved by removing the spurrious dependency in the (user) header
656  // files.
657  fRecordDeclCallback(recordDecl);
658  }
659 
660  // in case it is implicit or a forward declaration, we are not interested.
661  if(recordDecl->isImplicit() || !recordDecl->isCompleteDefinition()) {
662  return true;
663  }
664 
665  // Never select the class templates themselves.
666  const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(recordDecl);
667  if (cxxdecl && cxxdecl->getDescribedClassTemplate ()) {
668  return true;
669  }
670 
671  const ClassSelectionRule *selectedFromTypedef = typedefNameDecl ? fSelectionRules.IsDeclSelected(typedefNameDecl) : nullptr;
672 
673  const ClassSelectionRule *selectedFromRecDecl = fSelectionRules.IsDeclSelected(recordDecl, false /* exclude typedef rules*/);
674 
675  const ClassSelectionRule *selected = typedefNameDecl ? selectedFromTypedef : selectedFromRecDecl;
676 
677  if (! selected) return true; // early exit. Nothing more to be done.
678 
679  // Selected through typedef but excluded with concrete classname
680  bool excludedFromRecDecl = false;
681  if ( selectedFromRecDecl )
682  excludedFromRecDecl = selectedFromRecDecl->GetSelected() == BaseSelectionRule::kNo;
683 
684  if (selected->GetSelected() != BaseSelectionRule::kYes || excludedFromRecDecl)
685  return true;
686 
687  // Save the typedef
688  if (selectedFromTypedef) {
689  if (!IsElementPresent(fSelectedTypedefs, typedefNameDecl))
690  fSelectedTypedefs.push_back(typedefNameDecl);
691  // Don't generate a dictionary for the class underlying a typedef found
692  // for a file name match (eg. "defined_in")
693  if (!selectedFromRecDecl && selectedFromTypedef->HasAttributeFileName())
694  return true;
695  }
696 
697  if (selected->IsFromTypedef()) {
698  if (typedefNameDecl && !IsElementPresent(fSelectedTypedefs, typedefNameDecl))
699  fSelectedTypedefs.push_back(typedefNameDecl);
700  return true;
701  }
702 
703  if (typedefNameDecl)
704  ROOT::TMetaUtils::Info("RScanner::TreatRecordDeclOrTypedefNameDecl",
705  "Typedef is selected %s.\n", typedefNameDecl->getNameAsString().c_str());
706 
707  // For the case kNo, we could (but don't) remove the node from the pcm
708  // For the case kDontCare, the rule is just a place holder and we are actually trying to exclude some of its children
709  // (this is used only in the selection xml case).
710 
711  // Reject the selection of std::pair on the ground that it is trivial
712  // and can easily be recreated from the AST information.
713  if (recordDecl->getName() == "pair") {
714  const clang::NamespaceDecl *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(recordDecl->getDeclContext());
715  if (!nsDecl){
716  ROOT::TMetaUtils::Error("RScanner::TreatRecordDeclOrTypedefNameDecl",
717  "Cannot convert context of RecordDecl called pair into a namespace.\n");
718  return true;
719  }
720  const clang::NamespaceDecl *nsCanonical = nsDecl->getCanonicalDecl();
721  if (nsCanonical && nsCanonical == fInterpreter.getCI()->getSema().getStdNamespace()) {
722  if (selected->HasAttributeFileName() || selected->HasAttributeFilePattern()) {
723  return true;
724  }
725  }
726  }
727 
728  // Insert in the selected classes if not already there
729  // We need this check since the same class can be selected through its name or typedef
730  bool rcrdDeclNotAlreadySelected = fselectedRecordDecls.insert((RecordDecl*)recordDecl->getCanonicalDecl()).second;
731  if (!fFirstPass && !rcrdDeclNotAlreadySelected) {
732  // Diagnose conflicting selection rules:
733  auto declSelRuleMapIt = fDeclSelRuleMap.find(recordDecl->getCanonicalDecl());
734  if (declSelRuleMapIt != fDeclSelRuleMap.end() &&
735  declSelRuleMapIt->second != selected) {
736  std::string normName;
738  recordDecl->getASTContext().getTypeDeclType(recordDecl),
739  fInterpreter,
740  fNormCtxt);
741 
742  auto previouslyMatchingRule = (const ClassSelectionRule*)declSelRuleMapIt->second;
743  int previouslineno = previouslyMatchingRule->GetLineNumber();
744 
745  std::string cleanFileName = llvm::sys::path::filename(selected->GetSelFileName());
746  auto lineno = selected->GetLineNumber();
747  auto rulesAreCompatible = SelectionRulesUtils::areEqual<ClassSelectionRule>(selected, previouslyMatchingRule, true /*moduloNameOrPattern*/);
748  if (!rulesAreCompatible){
749  std::stringstream message;
750  if (lineno > 1) message << "Selection file " << cleanFileName << ", lines "
751  << lineno << " and " << previouslineno << ". ";
752  message << "Attempt to select a class "<< normName << " with two rules which have incompatible attributes. "
753  << "The attributes such as transiency might not be correctly propagated to the typesystem of ROOT.\n";
754  selected->Print(message);
755  message << "Conflicting rule already matched:\n";
756  previouslyMatchingRule->Print(message);
757  ROOT::TMetaUtils::Warning(nullptr,"%s\n", message.str().c_str());
758  }
759  }
760  }
761 
762  fDeclSelRuleMap[recordDecl->getCanonicalDecl()] = selected;
763 
764  if (!rcrdDeclNotAlreadySelected || fFirstPass)
765  return true;
766 
767  // Before adding the decl to the selected ones, check its access.
768  // We do not yet support I/O of private or protected classes.
769  // See ROOT-7450.
770  // Additionally, private declarations lead to uncompilable code, so just ignore (ROOT-9112).
771  if (recordDecl->getAccess() == AS_private || recordDecl->getAccess() == AS_protected) {
772  // Don't warn about types selected by "everything in that file".
773  auto isFileSelection = selected->HasAttributeFileName() &&
774  selected->HasAttributePattern() &&
775  "*" == selected->GetAttributePattern();
776  if (!isFileSelection) {
777  std::string normName;
779  recordDecl->getASTContext().getTypeDeclType(recordDecl),
780  fInterpreter,
781  fNormCtxt);
782  auto msg = "Class or struct %s was selected but its dictionary cannot be generated: "
783  "this is a private or protected class and this is not supported. No direct "
784  "I/O operation of %s instances will be possible.\n";
785  ROOT::TMetaUtils::Warning(nullptr,msg,normName.c_str(),normName.c_str());
786  }
787  return true;
788  }
789 
790  // Replace on the fly the type if the type for IO is different for example
791  // in presence of unique_ptr<T> or collections thereof.
792  // The following lines are very delicate: we need to preserve the special
793  // ROOT opaque typedefs.
794  auto req_type = selected->GetRequestedType();
795  clang::QualType thisType(req_type, 0);
796  std::string attr_name = selected->GetAttributeName().c_str();
797 
798  auto sc = AddAnnotatedRecordDecl(selected, req_type, recordDecl, attr_name, typedefNameDecl);
799  if (sc != 0) {
800  return false;
801  }
802 
803  if (auto CTSD = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(recordDecl)) {
804  fDelayedAnnotatedRecordDecls.emplace_back(DelayedAnnotatedRecordDeclInfo{selected, CTSD, typedefNameDecl});
805  }
806 
807  return true;
808 }
809 
811 {
812  for (auto &&info: fDelayedAnnotatedRecordDecls) {
813  const clang::Type *thisType = info.fSelected->GetRequestedType();
814  if (!thisType)
815  thisType = info.fDecl->getTypeForDecl();
816  const clang::CXXRecordDecl *recordDecl = info.fDecl;
817  auto nameTypeForIO = ROOT::TMetaUtils::GetNameTypeForIO(clang::QualType(thisType, 0), fInterpreter, fNormCtxt);
818  auto typeForIO = nameTypeForIO.second;
819  // It could be that we have in hands a type which is not a class, e.g.
820  // in presence of unique_ptr<T> we got a T with T=double.
821  if (typeForIO.getTypePtr() == thisType)
822  continue;
823  if (auto recordDeclForIO = typeForIO->getAsCXXRecordDecl()) {
824  const auto canRecordDeclForIO = recordDeclForIO->getCanonicalDecl();
825  if (!fselectedRecordDecls.insert(canRecordDeclForIO).second)
826  continue;
827  recordDecl = canRecordDeclForIO;
828  fDeclSelRuleMap[recordDecl] = info.fSelected;
829  thisType = typeForIO.getTypePtr();
830  }
831 
832  AddAnnotatedRecordDecl(info.fSelected, thisType, recordDecl,
833  nameTypeForIO.first, info.fTypedefNameDecl, 1000);
834  }
835 }
836 
837 ////////////////////////////////////////////////////////////////////////////////
838 /// Visitor for every TypedefNameDecl, i.e. aliases and typedefs
839 /// We check three conditions before trying to match the name:
840 /// 1) If we are creating a big PCM
841 /// 2) If the underlying decl is a RecordDecl
842 /// 3) If the typedef is eventually contained in the std namespace
843 
844 bool RScanner::VisitTypedefNameDecl(clang::TypedefNameDecl* D)
845 {
847  return true;
848 
849  if (!shouldVisitDecl(D))
850  return true;
851 
852  const clang::DeclContext *ctx = D->getDeclContext();
853 
854  bool isInStd=false;
855  if (ctx) {
856  const clang::NamedDecl *parent = llvm::dyn_cast<clang::NamedDecl> (ctx);
857  isInStd = parent && 0 == parent->getQualifiedNameAsString().compare(0,5,"std::");
858  }
859 
860  if (ROOT::TMetaUtils::GetUnderlyingRecordDecl(D->getUnderlyingType()) &&
861  !isInStd){
863  }
864 
865  return true;
866 }
867 
868 ////////////////////////////////////////////////////////////////////////////////
869 
870 bool RScanner::VisitEnumDecl(clang::EnumDecl* D)
871 {
873  return true;
874 
875  if (!shouldVisitDecl(D))
876  return true;
877 
879  !IsElementPresent(fSelectedEnums, D)){ // Removal of duplicates.
880  fSelectedEnums.push_back(D);
881  }
882 
883  return true;
884 }
885 
886 ////////////////////////////////////////////////////////////////////////////////
887 
888 bool RScanner::VisitVarDecl(clang::VarDecl* D)
889 {
890  if (!D->hasGlobalStorage() ||
892  return true;
893 
894  if (!shouldVisitDecl(D))
895  return true;
896 
898  fSelectedVariables.push_back(D);
899  }
900 
901  return true;
902 }
903 
904 ////////////////////////////////////////////////////////////////////////////////
905 /// Nothing to be done here
906 
907 bool RScanner::VisitFieldDecl(clang::FieldDecl* D)
908 {
909  return true;
910 
911 // bool ret = true;
912 //
913 // if(fSelectionRules.IsDeclSelected(D)){
914 //
915 // // if (fVerboseLevel > 0) {
916 // // std::string qual_name;
917 // // GetDeclQualName(D,qual_name);
918 // // std::cout<<"\tSelected field -> " << qual_name << "\n";
919 // // }
920 // }
921 // else {
922 // }
923 //
924 // return ret;
925 }
926 
927 ////////////////////////////////////////////////////////////////////////////////
928 
929 bool RScanner::VisitFunctionDecl(clang::FunctionDecl* D)
930 {
932  return true;
933 
934  if (!shouldVisitDecl(D))
935  return true;
936 
937  if(clang::FunctionDecl::TemplatedKind::TK_FunctionTemplate == D->getTemplatedKind())
938  return true;
939 
941  fSelectedFunctions.push_back(D);
942  }
943 
944  return true;
945 }
946 
947 ////////////////////////////////////////////////////////////////////////////////
948 
950 {
951  bool ret = true;
952 
953  if (!DC)
954  return true;
955 
956  clang::Decl* D = dyn_cast<clang::Decl>(DC);
957  // skip implicit decls
958  if (D && D->isImplicit()){
959  return true;
960  }
961 
963  const clang::NamespaceDecl *parent = llvm::dyn_cast<clang::NamespaceDecl> (DC);
964  if (parent && 0 == parent->getQualifiedNameAsString().compare(0,5,"std::"))
965  return true;
966  }
967 
968  for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end();
969  ret && (Child != ChildEnd); ++Child) {
970  ret=TraverseDecl(*Child);
971  }
972 
973  return ret;
974 
975 }
976 
977 ////////////////////////////////////////////////////////////////////////////////
978 
979 bool RScanner::GetDeclName(clang::Decl* D, std::string& name) const
980 {
981  clang::NamedDecl* N = dyn_cast<clang::NamedDecl> (D);
982 
983  if (N) {
984  name = N->getNameAsString();
985  return true;
986  }
987  else {
988  name = "UNNAMED";
989  return false;
990  }
991 }
992 
993 ////////////////////////////////////////////////////////////////////////////////
994 
995 bool RScanner::GetDeclQualName(const clang::Decl* D, std::string& qual_name)
996 {
997  auto N = dyn_cast<const clang::NamedDecl> (D);
998 
999  if (N) {
1000  llvm::raw_string_ostream stream(qual_name);
1001  N->getNameForDiagnostic(stream,D->getASTContext().getPrintingPolicy(),true); // qual_name = N->getQualifiedNameAsString();
1002  return true;
1003  }
1004  else {
1005  return false;
1006  }
1007 }
1008 
1009 ////////////////////////////////////////////////////////////////////////////////
1010 
1011 bool RScanner::GetFunctionPrototype(clang::Decl* D, std::string& prototype) const {
1012  if (!D) {
1013  return false;
1014  }
1015 
1016  clang::FunctionDecl* F = dyn_cast<clang::FunctionDecl> (D);
1017 
1018  if (F) {
1019 
1020  prototype = "";
1021  for (clang::FunctionDecl::param_iterator I = F->param_begin(), E = F->param_end(); I != E; ++I) {
1022  clang::ParmVarDecl* P = *I;
1023 
1024  if (prototype != "")
1025  prototype += ",";
1026 
1027  //std::string type = P->getType().getAsString();
1028  std::string type = P->getType().getAsString();
1029  if (type.at(type.length()-1) == '*') {
1030  type.at(type.length()-2) = '*';
1031  type.erase(type.length()-1);
1032  }
1033  prototype += type;
1034  }
1035 
1036  prototype = "(" + prototype + ")";
1037  return true;
1038  }
1039  else {
1040  ShowWarning("can't convert Decl to FunctionDecl","");
1041  return false;
1042  }
1043 }
1044 
1045 ////////////////////////////////////////////////////////////////////////////////
1046 
1047 void RScanner::Scan(const clang::ASTContext &C)
1048 {
1049  fSourceManager = &C.getSourceManager();
1050 
1051 // if (fVerboseLevel >= 3) fSelectionRules.PrintSelectionRules();
1052 
1054  std::cout<<"File name detected"<<std::endl;
1055  }
1056 
1058  TraverseDecl(C.getTranslationUnitDecl());
1059 
1060  fFirstPass=false;
1061  fselectedRecordDecls.clear();
1062  fSelectedEnums.clear();
1063  fSelectedTypedefs.clear();
1064  fSelectedVariables.clear();
1065  fSelectedFunctions.clear();
1066  TraverseDecl(C.getTranslationUnitDecl());
1067 
1068  // The RecursiveASTVisitor uses range-based for; we must not modify the AST
1069  // during iteration / visitation. Instead, buffer the lookups that could
1070  // potentially create new template specializations, and handle them here:
1072 }
1073 
1074 
1075 ////////////////////////////////////////////////////////////////////////////////
1076 /// Set the callback to the RecordDecl and return the previous one.
1077 
1079 {
1081  fRecordDeclCallback = callback;
1082  return old;
1083 }
RScanner::fFirstPass
bool fFirstPass
Definition: Scanner.h:200
RScanner::fSelectedEnums
EnumColl_t fSelectedEnums
Definition: Scanner.h:133
SelectionRules::IsDeclSelected
const ClassSelectionRule * IsDeclSelected(const clang::RecordDecl *D, bool includeTypedefRule) const
Definition: SelectionRules.cxx:273
TClassEdit::GetNormalizedName
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:837
RScanner::TraverseDeclContextHelper
bool TraverseDeclContextHelper(clang::DeclContext *DC)
Definition: Scanner.cxx:949
RScanner::ExprToStr
std::string ExprToStr(clang::Expr *expr) const
Definition: Scanner.cxx:401
ToDeclProp
void * ToDeclProp(clang::Decl *item)
Definition: Scanner.cxx:131
ROOT::TMetaUtils::Warning
void Warning(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:819
RScanner::DeclInfo
void DeclInfo(clang::Decl *D) const
Definition: Scanner.cxx:275
RScanner::fgTypeLast
static const int fgTypeLast
Definition: Scanner.h:188
RScanner::UnexpectedDecl
void UnexpectedDecl(clang::Decl *D, const std::string &txt="") const
unexpected - this kind of declaration is unexpected (in concrete place)
Definition: Scanner.cxx:297
RScanner::fSelectionRules
SelectionRules & fSelectionRules
Definition: Scanner.h:197
IntToStr
std::string IntToStr(int num)
Definition: Scanner.cxx:160
RScanner::fgClangFuncKey
static const char * fgClangFuncKey
Definition: Scanner.h:123
RScanner::UnknownDecl
void UnknownDecl(clang::Decl *D, const std::string &txt="") const
unknown - this kind of declaration was not known to programmer
Definition: Scanner.cxx:286
F
#define F(x, y, z)
ROOT::Math::Cephes::P
static double P[]
Definition: SpecFuncCephes.cxx:285
RScanner::fLastDecl
clang::Decl * fLastDecl
Definition: Scanner.h:190
RScanner::~RScanner
virtual ~RScanner()
Definition: Scanner.cxx:104
RScanner::fgClangDeclKey
static const char * fgClangDeclKey
Definition: Scanner.h:122
RScanner::GetEnumName
std::string GetEnumName(clang::EnumDecl *D) const
Definition: Scanner.cxx:377
BaseSelectionRule::GetSelected
ESelect GetSelected() const
Definition: BaseSelectionRule.cxx:103
RScanner::EScanType::kTwoPasses
@ kTwoPasses
SelectionRules.h
RScanner::VisitFieldDecl
bool VisitFieldDecl(clang::FieldDecl *D)
Nothing to be done here.
Definition: Scanner.cxx:907
BaseSelectionRule::kNo
@ kNo
Definition: BaseSelectionRule.h:45
RScanner::fSourceManager
const clang::SourceManager * fSourceManager
Definition: Scanner.h:185
gInterp
cling::Interpreter * gInterp
RScanner::DelayedAnnotatedRecordDeclInfo
Definition: Scanner.h:135
RScanner::ShowWarning
void ShowWarning(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:198
ROOT::TMetaUtils::Error
void Error(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:789
N
#define N
RScanner::fgAnonymousClassMap
static std::map< clang::Decl *, std::string > fgAnonymousClassMap
Definition: Scanner.h:175
ClassSelectionRule::RequestOnlyTClass
bool RequestOnlyTClass() const
Definition: ClassSelectionRule.cxx:160
operator()
TRObject operator()(const T1 &t1) const
Definition: TRFunctionImport__oprtr.h:14
RScanner::FuncParameters
std::string FuncParameters(clang::FunctionDecl *D) const
Definition: Scanner.cxx:431
SelectionRules::FillCache
void FillCache()
Definition: SelectionRules.cxx:1537
RScanner::fNormCtxt
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
Definition: Scanner.h:196
RScanner::UnsupportedDecl
void UnsupportedDecl(clang::Decl *D, const std::string &txt="") const
unsupported - this kind of declaration is probably not used (in current version of C++)
Definition: Scanner.cxx:308
RScanner::EScanType
EScanType
Definition: Scanner.h:80
RScanner::UnimplementedDecl
void UnimplementedDecl(clang::Decl *D, const std::string &txt="")
information about item, that should be implemented
Definition: Scanner.cxx:326
ClassSelectionRule::RequestNoInputOperator
bool RequestNoInputOperator() const
Definition: ClassSelectionRule.cxx:130
RScanner::VisitTypedefNameDecl
bool VisitTypedefNameDecl(clang::TypedefNameDecl *D)
Visitor for every TypedefNameDecl, i.e.
Definition: Scanner.cxx:844
ROOT::TMetaUtils::GetUnderlyingRecordDecl
clang::RecordDecl * GetUnderlyingRecordDecl(clang::QualType type)
Definition: TClingUtils.cxx:2845
ROOT::Math::IntegrationOneDim::Type
Type
enumeration specifying the integration types.
Definition: AllIntegrationTypes.h:32
v
@ v
Definition: rootcling_impl.cxx:3664
text
TText * text
Definition: entrylist_figure1.C:10
RScanner::UnimportantDecl
void UnimportantDecl(clang::Decl *D, const std::string &txt="") const
unimportant - this kind of declaration is not stored into reflex
Definition: Scanner.cxx:319
BaseSelectionRule::HasAttributePattern
bool HasAttributePattern() const
Definition: BaseSelectionRule.h:117
RScanner::ShowTemplateInfo
void ShowTemplateInfo(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:214
AddSpace
std::string AddSpace(const std::string &txt)
Definition: Scanner.cxx:265
APIntToSize
size_t APIntToSize(const llvm::APInt &num)
Definition: Scanner.cxx:139
ClassSelectionRule::Print
void Print(std::ostream &out) const
Definition: ClassSelectionRule.cxx:47
BaseSelectionRule::HasAttributeFilePattern
bool HasAttributeFilePattern() const
Definition: BaseSelectionRule.h:126
RScanner::fgDeclLast
static const int fgDeclLast
Definition: Scanner.h:187
Scanner.h
ROOT::Math::Cephes::C
static double C[]
Definition: SpecFuncCephes.cxx:187
ROOT::TMetaUtils::Info
void Info(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:809
TGeant4Unit::L
static constexpr double L
Definition: TGeant4SystemOfUnits.h:117
RScanner::ShowInfo
void ShowInfo(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:190
ROOT::TMetaUtils::IsStdClass
bool IsStdClass(const clang::RecordDecl &cl)
Return true, if the decl is part of the std namespace.
Definition: TClingUtils.cxx:4398
RScanner::fDeclTable
bool fDeclTable[fgDeclLast+1]
Definition: Scanner.h:189
BaseSelectionRule::GetSelFileName
const char * GetSelFileName() const
Definition: BaseSelectionRule.h:102
BaseSelectionRule::GetRequestedType
const clang::Type * GetRequestedType() const
Definition: BaseSelectionRule.cxx:525
ROOT::TMetaUtils::GetNameTypeForIO
std::pair< std::string, clang::QualType > GetNameTypeForIO(const clang::QualType &templateInstanceType, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt, TClassEdit::EModType mode=TClassEdit::kNone)
Definition: TClingUtils.cxx:4105
BaseSelectionRule::IsFromTypedef
bool IsFromTypedef() const
Definition: BaseSelectionRule.h:128
RScanner::UnknownType
void UnknownType(clang::QualType qual_type) const
Definition: Scanner.cxx:359
BaseSelectionRule::GetAttributePattern
const std::string & GetAttributePattern() const
Definition: BaseSelectionRule.h:116
RScanner::GetDeclName
bool GetDeclName(clang::Decl *D, std::string &name) const
Definition: Scanner.cxx:979
RScanner::fScanType
EScanType fScanType
Definition: Scanner.h:199
RScanner::GetName
std::string GetName(clang::Decl *D) const
Definition: Scanner.cxx:251
RScanner::Scan
void Scan(const clang::ASTContext &C)
Definition: Scanner.cxx:1047
RScanner::GetSrcLocation
std::string GetSrcLocation(clang::SourceLocation L) const
Definition: Scanner.cxx:224
RScanner::ShowError
void ShowError(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:206
RScanner::AddDelayedAnnotatedRecordDecls
void AddDelayedAnnotatedRecordDecls()
Definition: Scanner.cxx:810
RScanner::VisitNamespaceDecl
bool VisitNamespaceDecl(clang::NamespaceDecl *D)
This method visits a namespace node.
Definition: Scanner.cxx:478
ClassSelectionRule::RequestStreamerInfo
bool RequestStreamerInfo() const
Definition: ClassSelectionRule.cxx:110
ClassSelectionRule
Definition: ClassSelectionRule.h:34
IntToStd
std::string IntToStd(int num)
Definition: Scanner.cxx:169
RScanner::fSelectedFunctions
FunctionColl_t fSelectedFunctions
Definition: Scanner.h:131
BaseSelectionRule::kYes
@ kYes
Definition: BaseSelectionRule.h:44
RScanner::fgAnonymousEnumCounter
static int fgAnonymousEnumCounter
Definition: Scanner.h:194
RScanner::fselectedRecordDecls
std::set< clang::RecordDecl * > fselectedRecordDecls
Definition: Scanner.h:198
RScanner::TreatRecordDeclOrTypedefNameDecl
bool TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl *typeDecl)
Definition: Scanner.cxx:607
ROOT::TMetaUtils::TNormalizedCtxt
Definition: TClingUtils.h:138
APIntToLong
long APIntToLong(const llvm::APInt &num)
Definition: Scanner.cxx:146
RScanner::shouldVisitDecl
bool shouldVisitDecl(clang::NamedDecl *D)
Whether we can actually visit this declaration, i.e.
Definition: Scanner.cxx:121
RScanner::fSelectedClasses
ClassColl_t fSelectedClasses
Definition: Scanner.h:125
RScanner::GetDeclQualName
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
Definition: Scanner.cxx:995
RScanner::DeclCallback
void(* DeclCallback)(const clang::RecordDecl *)
Definition: Scanner.h:77
ClassSelectionRule::RequestedVersionNumber
int RequestedVersionNumber() const
Definition: ClassSelectionRule.cxx:175
RScanner::EScanType::kOnePCM
@ kOnePCM
RScanner::ConvTemplateName
std::string ConvTemplateName(clang::TemplateName &N) const
Definition: Scanner.cxx:416
RScanner::fVerboseLevel
unsigned int fVerboseLevel
Definition: Scanner.h:167
RScanner::fSelectedVariables
VariableColl_t fSelectedVariables
Definition: Scanner.h:132
RScanner::fDelayedAnnotatedRecordDecls
std::vector< DelayedAnnotatedRecordDeclInfo > fDelayedAnnotatedRecordDecls
Definition: Scanner.h:140
SelectionRulesUtils::areEqual< ClassSelectionRule >
bool areEqual< ClassSelectionRule >(const ClassSelectionRule *r1, const ClassSelectionRule *r2, bool moduloNameOrPattern)
Definition: SelectionRules.h:75
TClassEdit.h
BaseSelectionRule::GetLineNumber
long GetLineNumber() const
Definition: BaseSelectionRule.h:101
clang
Definition: BaseSelectionRule.h:29
RScanner::fTypeTable
bool fTypeTable[fgTypeLast+1]
Definition: Scanner.h:192
ROOT::TMetaUtils::GetClassVersion
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.
Definition: TClingUtils.cxx:2588
BaseSelectionRule::GetAttributeName
const std::string & GetAttributeName() const
Definition: BaseSelectionRule.h:110
RScanner::SetRecordDeclCallback
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
Definition: Scanner.cxx:1078
name
char name[80]
Definition: TGX11.cxx:110
SelectionRules::GetHasFileNameRule
bool GetHasFileNameRule() const
Definition: SelectionRules.h:153
RScanner::FuncParameterList
std::string FuncParameterList(clang::FunctionDecl *D) const
Definition: Scanner.cxx:458
ROOT::Math::Chebyshev::T
double T(double x)
Definition: ChebyshevPol.h:34
genreflex::verbose
bool verbose
Definition: rootcling_impl.cxx:133
RScanner::fSelectedNamespaces
NamespaceColl_t fSelectedNamespaces
Definition: Scanner.h:129
RScanner::GetLocation
std::string GetLocation(clang::Decl *D) const
Definition: Scanner.cxx:234
I
#define I(x, y, z)
APIntToStr
std::string APIntToStr(const llvm::APInt &num)
Definition: Scanner.cxx:153
RScanner::VisitVarDecl
bool VisitVarDecl(clang::VarDecl *D)
Definition: Scanner.cxx:888
RScanner::RScanner
RScanner(SelectionRules &rules, EScanType stype, const cling::Interpreter &interpret, ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, unsigned int verbose=0)
Regular constructor setting up the scanner to search for entities matching the 'rules'.
Definition: Scanner.cxx:76
BaseSelectionRule::HasAttributeFileName
bool HasAttributeFileName() const
Definition: BaseSelectionRule.h:123
RScanner::fgAnonymousClassCounter
static int fgAnonymousClassCounter
Definition: Scanner.h:193
type
int type
Definition: TGX11.cxx:121
BaseSelectionRule::HasAttributeName
bool HasAttributeName() const
Definition: BaseSelectionRule.h:111
RScanner::VisitRecordDecl
bool VisitRecordDecl(clang::RecordDecl *D)
Definition: Scanner.cxx:521
RScanner::fgBadClassCounter
static int fgBadClassCounter
Definition: Scanner.h:195
Message
std::string Message(const std::string &msg, const std::string &location)
Definition: Scanner.cxx:178
RScanner::fDeclSelRuleMap
DeclsSelRulesMap_t fDeclSelRuleMap
Definition: Scanner.h:201
RScanner::AddAnnotatedRecordDecl
int AddAnnotatedRecordDecl(const ClassSelectionRule *, const clang::Type *, const clang::RecordDecl *, const std::string &, const clang::TypedefNameDecl *, unsigned int indexOffset=0)
Definition: Scanner.cxx:534
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
TMath::E
constexpr Double_t E()
Base of natural log:
Definition: TMath.h:96
RScanner::fRecordDeclCallback
DeclCallback fRecordDeclCallback
Definition: Scanner.h:191
RScanner::fSelectedTypedefs
TypedefColl_t fSelectedTypedefs
Definition: Scanner.h:130
RScanner::fInterpreter
const cling::Interpreter & fInterpreter
Definition: Scanner.h:186
RScanner::GetFunctionPrototype
bool GetFunctionPrototype(clang::Decl *D, std::string &prototype) const
Definition: Scanner.cxx:1011
ClassSelectionRule::RequestNoStreamer
bool RequestNoStreamer() const
Definition: ClassSelectionRule.cxx:120
RScanner::AnnotatedNamespaceDecl
Definition: Scanner.h:56
RScanner::VisitFunctionDecl
bool VisitFunctionDecl(clang::FunctionDecl *D)
Definition: Scanner.cxx:929
RScanner::UnsupportedType
void UnsupportedType(clang::QualType qual_type) const
Definition: Scanner.cxx:368
RScanner::fgAnonymousEnumMap
static std::map< clang::Decl *, std::string > fgAnonymousEnumMap
Definition: Scanner.h:176
SelectionRules
The class representing the collection of selection rules.
Definition: SelectionRules.h:92
BaseSelectionRule::GetIndex
long GetIndex() const
Definition: BaseSelectionRule.h:98
RScanner::VisitEnumDecl
bool VisitEnumDecl(clang::EnumDecl *D)
Definition: Scanner.cxx:870