ROOT  6.06/09
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 //#define DEBUG
31 
32 #define SHOW_WARNINGS
33 // #define SHOW_TEMPLATE_INFO
34 
35 // #define COMPLETE_TEMPLATES
36 // #define CHECK_TYPES
37 
38 #define FILTER_WARNINGS
39 #define DIRECT_OUTPUT
40 
41 // SHOW_WARNINGS - enable warnings
42 // SHOW_TEMPLATE_INFO - enable informations about encoutered tempaltes
43 
44 // COMPLETE_TEMPLATES - process templates, not only specializations (instantiations)
45 
46 // FILTER_WARNINGS -- do not repeat same type of warning
47 // DIRECT_OUTPUT -- output to std err with gcc compatible filename an line number
48 
49 // #define SELECTION_DEBUG
50 
51 
52 
53 namespace {
54 
55  class RPredicateIsSameNamespace
56  {
57  private:
58  clang::NamespaceDecl *fTarget;
59  public:
60  RPredicateIsSameNamespace(clang::NamespaceDecl *target) : fTarget(target) {}
61 
62  bool operator()(const RScanner::AnnotatedNamespaceDecl& element)
63  {
64  return (fTarget == element);
65  }
66  };
67 
68 template<class T>
69 inline static bool IsElementPresent(const std::vector<T> &v, const T &el){
70  return std::find(v.begin(),v.end(),el) != v.end();
71 }
72 
73 }
74 
75 using namespace ROOT;
76 using namespace clang;
77 
78 extern cling::Interpreter *gInterp;
79 
80 const char* RScanner::fgClangDeclKey = "ClangDecl"; // property key used for connection with Clang objects
81 const char* RScanner::fgClangFuncKey = "ClangFunc"; // property key for demangled names
82 
86 
87 std::map <clang::Decl*, std::string> RScanner::fgAnonymousClassMap;
88 std::map <clang::Decl*, std::string> RScanner::fgAnonymousEnumMap;
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Regular constructor setting up the scanner to search for entities
92 /// matching the 'rules'.
93 
96  const cling::Interpreter &interpret,
98  unsigned int verbose /* = 0 */) :
99  fVerboseLevel(verbose),
100  fSourceManager(0),
101  fInterpreter(interpret),
102  fRecordDeclCallback(0),
103  fNormCtxt(normCtxt),
104  fSelectionRules(rules),
105  fScanType(stype),
106  fFirstPass(true)
107 {
108  // Build the cache for all selection rules
110 
111  for (int i = 0; i <= fgDeclLast; i ++)
112  fDeclTable [i] = false;
113 
114  for (int i = 0; i <= fgTypeLast; i ++)
115  fTypeTable [i] = false;
116 
117  fLastDecl = 0;
118 }
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 
123 {
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 
128 inline void* ToDeclProp(clang::Decl* item)
129 {
130  /* conversion and type check used by AddProperty */
131  return item;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 
136 inline size_t APIntToSize(const llvm::APInt& num)
137 {
138  return *num.getRawData();
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 
143 inline long APIntToLong(const llvm::APInt& num)
144 {
145  return *num.getRawData();
146 }
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 
150 inline std::string APIntToStr(const llvm::APInt& num)
151 {
152  return num.toString(10, true);
153 }
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 
157 inline std::string IntToStr(int num)
158 {
159  std::string txt = "";
160  txt += num;
161  return txt;
162 }
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 
166 inline std::string IntToStd(int num)
167 {
168  std::ostringstream stream;
169  stream << num;
170  return stream.str();
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 
175 inline std::string Message(const std::string &msg, const std::string &location)
176 {
177  std::string loc = location;
178 
179 #ifdef DIRECT_OUTPUT
180  int n = loc.length ();
181  while (n > 0 && loc [n] != ':')
182  n--;
183  if (n > 0)
184  loc = loc.substr (0, n) + ":";
185 #endif
186 
187  if (loc == "")
188  return msg;
189  else
190  return loc + " " + msg;
191 }
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 
195 void RScanner::ShowInfo(const std::string &msg, const std::string &location) const
196 {
197  const std::string message = Message(msg, location);
198 #ifdef DIRECT_OUTPUT
199  std::cout << message << std::endl;
200 #else
201  fReporter->Info("RScanner:ShowInfo", "CLR %s", message.Data());
202 #endif
203 }
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 
207 void RScanner::ShowWarning(const std::string &msg, const std::string &location) const
208 {
209 #ifdef SHOW_WARNINGS
210  const std::string message = Message(msg, location);
211 #ifdef DIRECT_OUTPUT
212  std::cout << message << std::endl;
213 #else
214  fReporter->Warning("RScanner:ShowWarning", "CLR %s", message.Data());
215 #endif
216 #endif
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 
221 void RScanner::ShowError(const std::string &msg, const std::string &location) const
222 {
223  const std::string message = Message(msg, location);
224 #ifdef DIRECT_OUTPUT
225  std::cout << message << std::endl;
226 #else
227  fReporter->Error("RScanner:ShowError", "CLR %s", message.Data());
228 #endif
229 }
230 
231 ////////////////////////////////////////////////////////////////////////////////
232 
233 void RScanner::ShowTemplateInfo(const std::string &msg, const std::string &location) const
234 {
235 #ifdef SHOW_TEMPLATE_INFO
236  std::string loc = location;
237  if (loc == "")
238  loc = GetLocation (fLastDecl);
239  ShowWarning(msg, loc);
240 #endif
241 }
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 
245 std::string RScanner::GetSrcLocation(clang::SourceLocation L) const
246 {
247  std::string location = "";
248  llvm::raw_string_ostream stream(location);
249  L.print(stream, *fSourceManager);
250  return stream.str();
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 
255 std::string RScanner::GetLocation(clang::Decl* D) const
256 {
257  if (D == NULL)
258  {
259  return "";
260  }
261  else
262  {
263  std::string location = "";
264  llvm::raw_string_ostream stream(location);
265  D->getLocation().print(stream, *fSourceManager);
266  return stream.str();
267  }
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 
272 std::string RScanner::GetName(clang::Decl* D) const
273 {
274  std::string name = "";
275  // std::string kind = D->getDeclKindName();
276 
277  if (clang::NamedDecl* ND = dyn_cast <clang::NamedDecl> (D)) {
278  name = ND->getQualifiedNameAsString();
279  }
280 
281  return name;
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 
286 inline std::string AddSpace(const std::string &txt)
287 {
288  if (txt == "")
289  return "";
290  else
291  return txt + " ";
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 
296 void RScanner::DeclInfo(clang::Decl* D) const
297 {
298  std::string location = GetLocation(D);
299  std::string kind = D->getDeclKindName();
300  std::string name = GetName(D);
301  ShowInfo("Scan: " + kind + " declaration " + name, location);
302 }
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// unknown - this kind of declaration was not known to programmer
306 
307 void RScanner::UnknownDecl(clang::Decl* D, const std::string &txt) const
308 {
309  std::string location = GetLocation(D);
310  std::string kind = D->getDeclKindName();
311  std::string name = GetName(D);
312  ShowWarning("Unknown " + AddSpace(txt) + kind + " declaration " + name, location);
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// unexpected - this kind of declaration is unexpected (in concrete place)
317 
318 void RScanner::UnexpectedDecl(clang::Decl* D, const std::string &txt) const
319 {
320  std::string location = GetLocation(D);
321  std::string kind = D->getDeclKindName();
322  std::string name = GetName(D);
323  ShowWarning("Unexpected " + kind + " declaration " + name, location);
324 }
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 /// unsupported - this kind of declaration is probably not used (in current version of C++)
328 
329 void RScanner::UnsupportedDecl(clang::Decl* D, const std::string &txt) const
330 {
331  std::string location = GetLocation(D);
332  std::string kind = D->getDeclKindName();
333  std::string name = GetName(D);
334  ShowWarning("Unsupported " + AddSpace(txt) + kind + " declaration " + name, location);
335 }
336 
337 ////////////////////////////////////////////////////////////////////////////////
338 /// unimportant - this kind of declaration is not stored into reflex
339 
340 void RScanner::UnimportantDecl(clang::Decl* D, const std::string &txt) const
341 {
342 }
343 
344 ////////////////////////////////////////////////////////////////////////////////
345 /// information about item, that should be implemented
346 
347 void RScanner::UnimplementedDecl(clang::Decl* D, const std::string &txt)
348 {
349  clang::Decl::Kind k = D->getKind();
350 
351  bool show = true;
352 #ifdef FILTER_WARNINGS
353  if (k >= 0 || k <= fgDeclLast) {
354  if (fDeclTable [k])
355  show = false; // already displayed
356  else
357  fDeclTable [k] = true;
358  }
359 #endif
360 
361  if (show)
362  {
363  std::string location = GetLocation(D);
364  std::string kind = D->getDeclKindName();
365  std::string name = GetName(D);
366  std::string msg = "Unimplemented ";
367  if (txt == "") {
368  msg += "declaration";
369  } else {
370  msg += txt;
371  }
372  msg += ": ";
373  msg += kind;
374  msg += " ";
375  msg += name;
376  ShowWarning(msg,location);
377  }
378 }
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 
382 void RScanner::UnknownType(clang::QualType qual_type) const
383 {
384  std::string location = GetLocation(fLastDecl);
385  std::string kind = qual_type.getTypePtr()->getTypeClassName();
386  ShowWarning("Unknown " + kind + " type " + qual_type.getAsString(), location);
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 
391 void RScanner::UnsupportedType(clang::QualType qual_type) const
392 {
393  std::string location = GetLocation(fLastDecl);
394  std::string kind = qual_type.getTypePtr()->getTypeClassName();
395  ShowWarning("Unsupported " + kind + " type " + qual_type.getAsString(), location);
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// unimportant - this kind of declaration is not stored into reflex
400 
401 void RScanner::UnimportantType(clang::QualType qual_type) const
402 {
403 }
404 
405 ////////////////////////////////////////////////////////////////////////////////
406 
407 void RScanner::UnimplementedType(clang::QualType qual_type)
408 {
409  clang::Type::TypeClass k = qual_type.getTypePtr()->getTypeClass();
410 
411  bool show = true;
412 #ifdef FILTER_WARNINGS
413  if (k >= 0 || k <= fgTypeLast) {
414  if (fTypeTable [k])
415  show = false; // already displayed
416  else
417  fTypeTable [k] = true;
418  }
419 #endif
420 
421  if (show)
422  {
423  std::string location = GetLocation(fLastDecl);
424  std::string kind = qual_type.getTypePtr()->getTypeClassName();
425  ShowWarning("Unimplemented type: " + kind + " " + qual_type.getAsString(), location);
426  }
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 
432 {
433  clang::Type::TypeClass k = T->getTypeClass();
434 
435  bool show = true;
436 #ifdef FILTER_WARNINGS
437  if (k >= 0 || k <= fgTypeLast) {
438  if (fTypeTable [k])
439  show = false; // already displayed
440  else
441  fTypeTable [k] = true;
442  }
443 #endif
444 
445  if (show)
446  {
447  std::string location = GetLocation(fLastDecl);
448  std::string kind = T->getTypeClassName ();
449  ShowWarning ("Unimplemented type: " + kind, location);
450  }
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 
455 std::string RScanner::GetClassName(clang::RecordDecl* D) const
456 {
457  std::string cls_name = D->getQualifiedNameAsString();
458 
459  // NO if (cls_name == "")
460  // NO if (D->isAnonymousStructOrUnion())
461  // NO if (cls_name == "(anonymous)") {
462  if (! D->getDeclName ()) {
463  if (fgAnonymousClassMap.find (D) != fgAnonymousClassMap.end())
464  {
465  // already encountered anonymous class
466  cls_name = fgAnonymousClassMap [D];
467  }
468  else
469  {
471  cls_name = "_ANONYMOUS_CLASS_" + IntToStd(fgAnonymousClassCounter) + "_"; // !?
472  fgAnonymousClassMap [D] = cls_name;
473  // ShowInfo ("anonymous class " + cls_name, GetLocation (D));
474  }
475  }
476 
477  return cls_name;
478 }
479 
480 ////////////////////////////////////////////////////////////////////////////////
481 
482 std::string RScanner::GetEnumName(clang::EnumDecl* D) const
483 {
484  std::string enum_name = D->getQualifiedNameAsString();
485 
486  if (! D->getDeclName ()) {
487  if (fgAnonymousEnumMap.find (D) != fgAnonymousEnumMap.end())
488  {
489  // already encountered anonymous enumeration type
490  enum_name = fgAnonymousEnumMap [D];
491  }
492  else
493  {
495  enum_name = "_ANONYMOUS_ENUM_" + IntToStd(fgAnonymousEnumCounter) + "_"; // !?
496  fgAnonymousEnumMap [D] = enum_name;
497  // ShowInfo ("anonymous enum " + enum_name, GetLocation (D));
498  }
499  }
500 
501  return enum_name;
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 
506 std::string RScanner::ExprToStr(clang::Expr* expr) const
507 {
508  clang::LangOptions lang_opts;
509  clang::PrintingPolicy print_opts(lang_opts); // !?
510 
511  std::string text = "";
512  llvm::raw_string_ostream stream(text);
513 
514  expr->printPretty(stream, NULL, print_opts);
515 
516  return stream.str();
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 
521 std::string RScanner::ConvTemplateName(clang::TemplateName& N) const
522 {
523  clang::LangOptions lang_opts;
524  clang::PrintingPolicy print_opts(lang_opts); // !?
525 
526  std::string text = "";
527  llvm::raw_string_ostream stream(text);
528 
529  N.print(stream, print_opts);
530 
531  return stream.str();
532 }
533 
534 #ifdef COMPLETE_TEMPLATES
535 ////////////////////////////////////////////////////////////////////////////////
536 
537 std::string RScanner::ConvTemplateParameterList(clang::TemplateParameterList* list) const
538 {
539  std::string result = "";
540  bool any = false;
541 
542  for (clang::TemplateParameterList::iterator I = list->begin(), E = list->end(); I != E; ++I) {
543  if (any)
544  result += ",";
545  any = true;
546 
547  clang::NamedDecl * D = *I;
548 
549  switch (D->getKind()) {
550 
551  case clang::Decl::TemplateTemplateParm:
552  UnimplementedDecl(dyn_cast <clang::TemplateTemplateParmDecl> (D), "template parameter");
553  break;
554 
555  case clang::Decl::TemplateTypeParm:
556  {
557  clang::TemplateTypeParmDecl* P = dyn_cast <clang::TemplateTypeParmDecl> (D);
558 
559  if (P->wasDeclaredWithTypename())
560  result += "typename ";
561  else
562  result += "class ";
563 
564  if (P->isParameterPack())
565  result += "... ";
566 
567  result += P->getNameAsString();
568  }
569  break;
570 
571  case clang::Decl::NonTypeTemplateParm:
572  {
573  clang::NonTypeTemplateParmDecl* P = dyn_cast <clang::NonTypeTemplateParmDecl> (D);
574  result += P->getType().getAsString();
575 
576  if (clang::IdentifierInfo* N = P->getIdentifier()) {
577  result += " ";
578  std::string s = N->getName();
579  result += s;
580  }
581 
582  if (P->hasDefaultArgument())
583  result += " = " + ExprToStr(P->getDefaultArgument());
584  }
585  break;
586 
587  default:
588  UnknownDecl(*I, "template parameter");
589  }
590  }
591 
592  // ShowInfo ("template parameters <" + result + ">");
593 
594  return "<" + result + ">";
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 
599 std::string RScanner::ConvTemplateParams(clang::TemplateDecl* D)
600 {
601  return ConvTemplateParameterList(D->getTemplateParameters());
602 }
603 
604 ////////////////////////////////////////////////////////////////////////////////
605 
606 std::string RScanner::ConvTemplateArguments(const clang::TemplateArgumentList& list)
607 {
608  clang::LangOptions lang_opts;
609  clang::PrintingPolicy print_opts(lang_opts); // !?
610  return clang::TemplateSpecializationType::PrintTemplateArgumentList
611  (list.data(), list.size(), print_opts);
612 }
613 #endif // COMPLETE_TEMPLATES
614 
615 ////////////////////////////////////////////////////////////////////////////////
616 
617 std::string RScanner::FuncParameters(clang::FunctionDecl* D) const
618 {
619  std::string result = "";
620 
621  for (clang::FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) {
622  clang::ParmVarDecl* P = *I;
623 
624  if (result != "")
625  result += ";"; // semicolon, not comma, important
626 
627  std::string type = P->getType().getAsString();
628  std::string name = P->getNameAsString();
629 
630  result += type + " " + name;
631 
632  // NO if (P->hasDefaultArg ()) // check hasUnparsedDefaultArg () and hasUninstantiatedDefaultArg ()
633  if (P->getInit()) {
634  std::string init_value = ExprToStr(P->getDefaultArg());
635  result += "=" + init_value;
636  }
637  }
638 
639  return result;
640 }
641 
642 ////////////////////////////////////////////////////////////////////////////////
643 
644 std::string RScanner::FuncParameterList(clang::FunctionDecl* D) const
645 {
646  std::string result = "";
647 
648  for (clang::FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) {
649  clang::ParmVarDecl* P = *I;
650 
651  if (result != "")
652  result += ",";
653 
654  std::string type = P->getType().getAsString();
655  result += type;
656  }
657 
658  return "(" + result + ")";
659 }
660 
661 ////////////////////////////////////////////////////////////////////////////////
662 /// This method visits a namespace node
663 
664 bool RScanner::VisitNamespaceDecl(clang::NamespaceDecl* N)
665 {
666  // We don't need to visit this while creating the big PCM
668  return true;
669 
670  // in case it is implicit we don't create a builder
671  if(N && N->isImplicit()){
672  return true;
673  }
674 
675  bool ret = true;
676 
678  if (selected) {
679 
680 #ifdef SELECTION_DEBUG
681  if (fVerboseLevel > 3) std::cout<<"\n\tSelected -> true";
682 #endif
683  clang::DeclContext* primary_ctxt = N->getPrimaryContext();
684  clang::NamespaceDecl* primary = llvm::dyn_cast<clang::NamespaceDecl>(primary_ctxt);
685 
686  RPredicateIsSameNamespace pred(primary);
687  if ( find_if(fSelectedNamespaces.begin(),fSelectedNamespaces.end(),pred) == fSelectedNamespaces.end() ) {
688  // The namespace is not already registered.
689 
690  if (fVerboseLevel > 0) {
691  std::string qual_name;
692  GetDeclQualName(N,qual_name);
693  // std::cout<<"\tSelected namespace -> " << qual_name << " ptr " << (void*)N << " decl ctxt " << (void*)N->getPrimaryContext() << " classname " <<primary->getNameAsString() << "\n";
694  std::cout<<"\tSelected namespace -> " << qual_name << "\n";
695  }
696  fSelectedNamespaces.push_back(AnnotatedNamespaceDecl(primary,selected->GetIndex(),selected->RequestOnlyTClass()));
697  }
698  ret = true;
699  }
700  else {
701 #ifdef SELECTION_DEBUG
702  if (fVerboseLevel > 3) std::cout<<"\n\tSelected -> false";
703 #endif
704  }
705 
706  // DEBUG if(ret) std::cout<<"\n\tReturning true ...";
707  // DEBUG else std::cout<<"\n\tReturning false ...";
708  return ret;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 
713 bool RScanner::VisitRecordDecl(clang::RecordDecl* D)
714 {
715  // This method visits a class node
717 
718 
719 }
720 
721 ////////////////////////////////////////////////////////////////////////////////
722 
723 bool RScanner::TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl* typeDecl)
724 {
725  // For every class is created a new class buider irrespectful of weather the
726  // class is internal for another class declaration or not.
727  // RecordDecls and TypedefDecls (or RecordDecls!) are treated.
728  // We follow two different codepaths if the typeDecl is a RecordDecl or
729  // a TypedefDecl. If typeDecl is a TypedefDecl, recordDecl becomes the
730  // underlying RecordDecl.
731  // This is done to leverage the selections rule matching in SelectionRules
732  // which works basically with names.
733  // At the end of the method, if the typedef name is matched, an AnnotatedRecordDecl
734  // with the underlying RecordDecl is fed to the machinery.
735 
736  clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(typeDecl);
737  clang::TypedefNameDecl* typedefNameDecl = clang::dyn_cast<clang::TypedefNameDecl>(typeDecl);
738 
739  // If typeDecl is not a RecordDecl, try to fetch the RecordDecl behind the TypedefDecl
740  if (!recordDecl && typedefNameDecl) {
741  recordDecl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(typedefNameDecl->getUnderlyingType());
742  }
743 
744  // If at this point recordDecl is still NULL, we have a problem
745  if (!recordDecl) {
746  ROOT::TMetaUtils::Warning("RScanner::TreatRecordDeclOrTypeNameDecl",
747  "Could not cast typeDecl either to RecordDecl or could not get RecordDecl underneath typedef.\n");
748  return true;
749  }
750 
751  // Do not select unnamed records.
752  if (!recordDecl->getIdentifier())
753  return true;
754 
756  return true;
757 
758 
759  // At this point, recordDecl must be a RecordDecl pointer.
760 
761  if (recordDecl && fRecordDeclCallback) {
762  // Pass on any declaration. This is usually used to record dependency.
763  // Since rootcint see C++ compliant header files, we can assume that
764  // if a forward declaration or declaration has been inserted, the
765  // classes for which we are creating a dictionary will be using
766  // them either directly or indirectly. Any false positive can be
767  // resolved by removing the spurrious dependency in the (user) header
768  // files.
769  std::string qual_name;
770  GetDeclQualName(recordDecl,qual_name);
771  fRecordDeclCallback(qual_name.c_str());
772  }
773 
774  // in case it is implicit or a forward declaration, we are not interested.
775  if(recordDecl && (recordDecl->isImplicit() || !recordDecl->isCompleteDefinition()) ) {
776  return true;
777  }
778 
779  // Never select the class templates themselves.
780  const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(recordDecl);
781  if (cxxdecl && cxxdecl->getDescribedClassTemplate ()) {
782  return true;
783  }
784 
785  const ClassSelectionRule *selectedFromTypedef = typedefNameDecl ? fSelectionRules.IsDeclSelected(typedefNameDecl) : 0;
786 
787  const ClassSelectionRule *selectedFromRecDecl = fSelectionRules.IsDeclSelected(recordDecl);
788 
789  const ClassSelectionRule *selected = typedefNameDecl ? selectedFromTypedef : selectedFromRecDecl;
790 
791  if (! selected) return true; // early exit. Nothing more to be done.
792 
793  // Selected through typedef but excluded with concrete classname
794  bool excludedFromRecDecl = false;
795  if ( selectedFromRecDecl )
796  excludedFromRecDecl = selectedFromRecDecl->GetSelected() == BaseSelectionRule::kNo;
797 
798  if (selected->GetSelected() == BaseSelectionRule::kYes && !excludedFromRecDecl) {
799  // The record decl will results to be selected
800 
801  // Save the typedef
802  if (selectedFromTypedef){
803  if (!IsElementPresent(fSelectedTypedefs, typedefNameDecl))
804  fSelectedTypedefs.push_back(typedefNameDecl);
805  // Early exit here if we are not in presence of XML
806  if (!fSelectionRules.IsSelectionXMLFile()) return true;
807  }
808 
809  if (fSelectionRules.IsSelectionXMLFile() && selected->IsFromTypedef()) {
810  if (!IsElementPresent(fSelectedTypedefs, typedefNameDecl))
811  fSelectedTypedefs.push_back(typedefNameDecl);
812  return true;
813  }
814 
815  if (typedefNameDecl)
816  ROOT::TMetaUtils::Info("RScanner::TreatRecordDeclOrTypedefNameDecl",
817  "Typedef is selected %s.\n", typedefNameDecl->getNameAsString().c_str());
818 
819  // For the case kNo, we could (but don't) remove the node from the pcm
820  // For the case kDontCare, the rule is just a place holder and we are actually trying to exclude some of its children
821  // (this is used only in the selection xml case).
822 
823  // Reject the selection of std::pair on the ground that it is trivial
824  // and can easily be recreated from the AST information.
825  if (recordDecl && recordDecl->getName() == "pair") {
826  const clang::NamespaceDecl *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(recordDecl->getDeclContext());
827  if (!nsDecl){
828  ROOT::TMetaUtils::Error("RScanner::TreatRecordDeclOrTypedefNameDecl",
829  "Cannot convert context of RecordDecl called pair into a namespace.\n");
830  return true;
831  }
832  const clang::NamespaceDecl *nsCanonical = nsDecl->getCanonicalDecl();
833  if (nsCanonical && nsCanonical == fInterpreter.getCI()->getSema().getStdNamespace()) {
834  if (selected->HasAttributeFileName() || selected->HasAttributeFilePattern()) {
835  return true;
836  }
837  }
838  }
839 
840  // Insert in the selected classes if not already there
841  // We need this check since the same class can be selected through its name or typedef
842  bool rcrdDeclNotAlreadySelected = fselectedRecordDecls.insert((RecordDecl*)recordDecl->getCanonicalDecl()).second;
843 
844  auto declSelRuleMapIt = fDeclSelRuleMap.find(recordDecl->getCanonicalDecl());
845  if (!fFirstPass &&
846  !rcrdDeclNotAlreadySelected &&
847  declSelRuleMapIt != fDeclSelRuleMap.end() &&
848  declSelRuleMapIt->second != selected){
849  std::string normName;
851  recordDecl->getASTContext().getTypeDeclType(recordDecl),
852  fInterpreter,
853  fNormCtxt);
854 
855  auto previouslyMatchingRule = (const ClassSelectionRule*)declSelRuleMapIt->second;
856  int previouslineno = previouslyMatchingRule->GetLineNumber();
857 
858  std::string cleanFileName = llvm::sys::path::filename(selected->GetSelFileName());
859  auto lineno = selected->GetLineNumber();
860  auto rulesAreCompatible = SelectionRulesUtils::areEqual<ClassSelectionRule>(selected, previouslyMatchingRule, true /*moduloNameOrPattern*/);
861  if (!rulesAreCompatible){
862  std::stringstream message;
863  if (lineno > 1) message << "Selection file " << cleanFileName << ", lines "
864  << lineno << " and " << previouslineno << ". ";
865  message << "Attempt to select a class "<< normName << " with two rules which have incompatible attributes. "
866  << "The attributes such as transiency might not be correctly propagated to the typesystem of ROOT.\n";
867  selected->Print(message);
868  message << "Conflicting rule already matched:\n";
869  previouslyMatchingRule->Print(message);
870  ROOT::TMetaUtils::Warning(0,"%s\n", message.str().c_str());
871  }
872  }
873 
874  fDeclSelRuleMap[recordDecl->getCanonicalDecl()]=selected;
875 
876  if(rcrdDeclNotAlreadySelected &&
877  !fFirstPass){
878 
879 
880  // Before adding the decl to the selected ones, check its access.
881  // We do not yet support I/O of private or protected classes.
882  // See ROOT-7450
883  // We exclude filename selections as they can come from aclic
884  auto isFileSelection = selected->HasAttributeFileName() &&
885  selected->HasAttributePattern() &&
886  "*" == selected->GetAttributePattern();
887  auto canDeclAccess = recordDecl->getCanonicalDecl()->getAccess();
888  if (!isFileSelection && (AS_protected == canDeclAccess || AS_private == canDeclAccess)){
889  std::string normName;
891  recordDecl->getASTContext().getTypeDeclType(recordDecl),
892  fInterpreter,
893  fNormCtxt);
894  auto msg = "Class or struct %s was selected but its dictionary cannot be generated: "
895  "this is a private or protected class and this is not supported. No direct "
896  "I/O operation of %s instances will be possible.\n";
897  ROOT::TMetaUtils::Warning(0,msg,normName.c_str(),normName.c_str());
898  return true;
899  }
900 
901  const std::string& name_value = selected->GetAttributeName();
902  if (selected->HasAttributeName()) {
903  ROOT::TMetaUtils::AnnotatedRecordDecl annRecDecl(selected->GetIndex(),
904  selected->GetRequestedType(),
905  recordDecl,
906  name_value.c_str(),
907  selected->RequestStreamerInfo(),
908  selected->RequestNoStreamer(),
909  selected->RequestNoInputOperator(),
910  selected->RequestOnlyTClass(),
911  selected->RequestedVersionNumber(),
912  fInterpreter,
913  fNormCtxt);
914  fSelectedClasses.push_back(annRecDecl);
915 
916 
917 
918  } else {
919  ROOT::TMetaUtils::AnnotatedRecordDecl annRecDecl(selected->GetIndex(),
920  recordDecl,
921  selected->RequestStreamerInfo(),
922  selected->RequestNoStreamer(),
923  selected->RequestNoInputOperator(),
924  selected->RequestOnlyTClass(),
925  selected->RequestedVersionNumber(),
926  fInterpreter,
927  fNormCtxt);
928  fSelectedClasses.push_back(annRecDecl);
929  }
930 
931  if (fVerboseLevel > 0) {
932  std::string qual_name;
933  GetDeclQualName(recordDecl,qual_name);
934  std::string normName;
936  recordDecl->getASTContext().getTypeDeclType(recordDecl),
937  fInterpreter,
938  fNormCtxt);
939  std::string typedef_qual_name;
940  std::string typedefMsg;
941  if (typedefNameDecl){
942  GetDeclQualName(typedefNameDecl,typedef_qual_name);
943  typedefMsg = "(through typedef/alias " + typedef_qual_name + ") ";
944  }
945 
946  std::cout <<"Selected class "
947  << typedefMsg
948  << "-> "
949  << qual_name
950  << " for ROOT: "
951  << normName
952  << "\n";
953  }
954 
955  }
956  }
957 
958 
959 
960  return true;
961 }
962 
963 ////////////////////////////////////////////////////////////////////////////////
964 /// Visitor for every TypedefNameDecl, i.e. aliases and typedefs
965 /// We check three conditions before trying to match the name:
966 /// 1) If we are creating a big PCM
967 /// 2) If the underlying decl is a RecordDecl
968 /// 3) If the typedef is eventually contained in the std namespace
969 
970 bool RScanner::VisitTypedefNameDecl(clang::TypedefNameDecl* D)
971 {
973  return true;
974 
975  const clang::DeclContext *ctx = D->getDeclContext();
976 
977  bool isInStd=false;
978  if (ctx) {
979  const clang::NamedDecl *parent = llvm::dyn_cast<clang::NamedDecl> (ctx);
980  isInStd = parent && 0 == parent->getQualifiedNameAsString().compare(0,5,"std::");
981  }
982 
983  if (ROOT::TMetaUtils::GetUnderlyingRecordDecl(D->getUnderlyingType()) &&
984  !isInStd){
986  }
987 
988  return true;
989 }
990 
991 ////////////////////////////////////////////////////////////////////////////////
992 
993 bool RScanner::VisitEnumDecl(clang::EnumDecl* D)
994 {
996  return true;
997 
999  !IsElementPresent(fSelectedEnums, D)){ // Removal of duplicates.
1000  fSelectedEnums.push_back(D);
1001  }
1002 
1003  return true;
1004 }
1005 
1006 ////////////////////////////////////////////////////////////////////////////////
1007 
1008 bool RScanner::VisitVarDecl(clang::VarDecl* D)
1009 {
1010  if (!D->hasGlobalStorage() ||
1012  return true;
1013 
1015  fSelectedVariables.push_back(D);
1016  }
1017 
1018  return true;
1019 }
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Nothing to be done here
1023 
1024 bool RScanner::VisitFieldDecl(clang::FieldDecl* D)
1025 {
1026  return true;
1027 
1028 // bool ret = true;
1029 //
1030 // if(fSelectionRules.IsDeclSelected(D)){
1031 // #ifdef SELECTION_DEBUG
1032 // if (fVerboseLevel > 3) std::cout<<"\n\tSelected -> true";
1033 // #endif
1034 //
1035 // // if (fVerboseLevel > 0) {
1036 // // std::string qual_name;
1037 // // GetDeclQualName(D,qual_name);
1038 // // std::cout<<"\tSelected field -> " << qual_name << "\n";
1039 // // }
1040 // }
1041 // else {
1042 // #ifdef SELECTION_DEBUG
1043 // if (fVerboseLevel > 3) std::cout<<"\n\tSelected -> false";
1044 // #endif
1045 // }
1046 //
1047 // return ret;
1048 }
1049 
1050 ////////////////////////////////////////////////////////////////////////////////
1051 
1052 bool RScanner::VisitFunctionDecl(clang::FunctionDecl* D)
1053 {
1055  return true;
1056 
1057  if(clang::FunctionDecl::TemplatedKind::TK_FunctionTemplate == D->getTemplatedKind())
1058  return true;
1059 
1061  fSelectedFunctions.push_back(D);
1062  }
1063 
1064  return true;
1065 }
1066 
1067 ////////////////////////////////////////////////////////////////////////////////
1068 
1070 {
1071  bool ret = true;
1072 
1073  if (!DC)
1074  return true;
1075 
1076  clang::Decl* D = dyn_cast<clang::Decl>(DC);
1077  // skip implicit decls
1078  if (D && D->isImplicit()){
1079  return true;
1080  }
1081 
1082  if (fScanType == EScanType::kOnePCM){
1083  const clang::NamespaceDecl *parent = llvm::dyn_cast<clang::NamespaceDecl> (DC);
1084  if (parent && 0 == parent->getQualifiedNameAsString().compare(0,5,"std::"))
1085  return true;
1086  }
1087 
1088  for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end();
1089  ret && (Child != ChildEnd); ++Child) {
1090  ret=TraverseDecl(*Child);
1091  }
1092 
1093  return ret;
1094 
1095 }
1096 
1097 ////////////////////////////////////////////////////////////////////////////////
1098 
1099 std::string RScanner::GetClassName(clang::DeclContext* DC) const
1100 {
1101  clang::NamedDecl* N=dyn_cast<clang::NamedDecl>(DC);
1102  std::string ret;
1103  if(N && (N->getIdentifier()!=NULL))
1104  ret = N->getNameAsString().c_str();
1105 
1106  return ret;
1107 }
1108 
1109 ////////////////////////////////////////////////////////////////////////////////
1110 
1111 bool RScanner::GetDeclName(clang::Decl* D, std::string& name) const
1112 {
1113  clang::NamedDecl* N = dyn_cast<clang::NamedDecl> (D);
1114 
1115  if (N) {
1116  name = N->getNameAsString();
1117  return true;
1118  }
1119  else {
1120  name = "UNNAMED";
1121  return false;
1122  }
1123 }
1124 
1125 ////////////////////////////////////////////////////////////////////////////////
1126 
1127 bool RScanner::GetDeclQualName(clang::Decl* D, std::string& qual_name) const
1128 {
1129  clang::NamedDecl* N = dyn_cast<clang::NamedDecl> (D);
1130 
1131  if (N) {
1132  llvm::raw_string_ostream stream(qual_name);
1133  N->getNameForDiagnostic(stream,D->getASTContext().getPrintingPolicy(),true); // qual_name = N->getQualifiedNameAsString();
1134  return true;
1135  }
1136  else {
1137  return false;
1138  }
1139 }
1140 
1141 ////////////////////////////////////////////////////////////////////////////////
1142 
1143 bool RScanner::GetFunctionPrototype(clang::Decl* D, std::string& prototype) const {
1144  if (!D) {
1145  return false;
1146  }
1147 
1148  clang::FunctionDecl* F = dyn_cast<clang::FunctionDecl> (D);
1149 
1150  if (F) {
1151 
1152  prototype = "";
1153  for (clang::FunctionDecl::param_iterator I = F->param_begin(), E = F->param_end(); I != E; ++I) {
1154  clang::ParmVarDecl* P = *I;
1155 
1156  if (prototype != "")
1157  prototype += ",";
1158 
1159  //std::string type = P->getType().getAsString();
1160  std::string type = P->getType().getAsString();
1161  if (type.at(type.length()-1) == '*') {
1162  type.at(type.length()-2) = '*';
1163  type.erase(type.length()-1);
1164  }
1165  prototype += type;
1166  }
1167 
1168  prototype = "(" + prototype + ")";
1169  return true;
1170  }
1171  else {
1172  ShowWarning("can't convert Decl to FunctionDecl","");
1173  return false;
1174  }
1175 }
1176 
1177 ////////////////////////////////////////////////////////////////////////////////
1178 
1179 void RScanner::Scan(const clang::ASTContext &C)
1180 {
1181  fSourceManager = &C.getSourceManager();
1182 
1183 // if (fVerboseLevel >= 3) fSelectionRules.PrintSelectionRules();
1184 
1186  std::cout<<"File name detected"<<std::endl;
1187  }
1188 
1190  TraverseDecl(C.getTranslationUnitDecl());
1191 
1192  fFirstPass=false;
1193  fselectedRecordDecls.clear();
1194  fSelectedEnums.clear();
1195  fSelectedTypedefs.clear();
1196  fSelectedFunctions.clear();
1197  TraverseDecl(C.getTranslationUnitDecl());
1198 
1199  // And finally resort the results according to the rule ordering.
1200  std::sort(fSelectedClasses.begin(),fSelectedClasses.end());
1201 }
1202 
1203 
1204 ////////////////////////////////////////////////////////////////////////////////
1205 /// Set the callback to the RecordDecl and return the previous one.
1206 
1208 {
1210  fRecordDeclCallback = callback;
1211  return old;
1212 }
std::string ConvTemplateArguments(const clang::TemplateArgumentList &list) const
NamespaceColl_t fSelectedNamespaces
Definition: Scanner.h:122
bool VisitVarDecl(clang::VarDecl *D)
Definition: Scanner.cxx:1008
void ShowWarning(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:207
const ClassSelectionRule * IsDeclSelected(const clang::RecordDecl *D) const
bool HasAttributeName() const
std::string IntToStr(int num)
Definition: Scanner.cxx:157
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
cling::Interpreter * gInterp
bool RequestStreamerInfo() const
bool GetDeclQualName(clang::Decl *D, std::string &qual_name) const
Definition: Scanner.cxx:1127
void UnimplementedDecl(clang::Decl *D, const std::string &txt="")
information about item, that should be implemented
Definition: Scanner.cxx:347
std::string GetLocation(clang::Decl *D) const
Definition: Scanner.cxx:255
RooArgList L(const RooAbsArg &v1)
void Error(const char *location, const char *va_(fmt),...)
Use this function in case an error occured.
double T(double x)
Definition: ChebyshevPol.h:34
static const int fgTypeLast
Definition: Scanner.h:172
clang::RecordDecl * GetUnderlyingRecordDecl(clang::QualType type)
bool RequestNoStreamer() const
static std::map< clang::Decl *, std::string > fgAnonymousEnumMap
Definition: Scanner.h:157
static const char * filename()
#define N
void ShowTemplateInfo(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:233
void(* DeclCallback)(const char *type)
Definition: Scanner.h:70
static std::map< clang::Decl *, std::string > fgAnonymousClassMap
Definition: Scanner.h:156
clang::Decl * fLastDecl
Definition: Scanner.h:174
static int fgAnonymousEnumCounter
Definition: Scanner.h:178
virtual ~RScanner()
Definition: Scanner.cxx:122
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
Definition: Scanner.h:180
unsigned int fVerboseLevel
Definition: Scanner.h:148
bool RequestNoInputOperator() const
bool fDeclTable[fgDeclLast+1]
Definition: Scanner.h:173
SelectionRules & fSelectionRules
Definition: Scanner.h:181
void UnexpectedDecl(clang::Decl *D, const std::string &txt="") const
unexpected - this kind of declaration is unexpected (in concrete place)
Definition: Scanner.cxx:318
static const char * fgClangDeclKey
Definition: Scanner.h:115
int RequestedVersionNumber() const
VariableColl_t fSelectedVariables
Definition: Scanner.h:125
const char Int_t const char TProof Int_t stype
Definition: TXSlave.cxx:46
void UnimportantDecl(clang::Decl *D, const std::string &txt="") const
unimportant - this kind of declaration is not stored into reflex
Definition: Scanner.cxx:340
static int fgAnonymousClassCounter
Definition: Scanner.h:177
bool VisitTypedefNameDecl(clang::TypedefNameDecl *D)
Visitor for every TypedefNameDecl, i.e.
Definition: Scanner.cxx:970
bool GetFunctionPrototype(clang::Decl *D, std::string &prototype) const
Definition: Scanner.cxx:1143
bool VisitFieldDecl(clang::FieldDecl *D)
Nothing to be done here.
Definition: Scanner.cxx:1024
std::string FuncParameterList(clang::FunctionDecl *D) const
Definition: Scanner.cxx:644
void UnknownDecl(clang::Decl *D, const std::string &txt="") const
unknown - this kind of declaration was not known to programmer
Definition: Scanner.cxx:307
EScanType fScanType
Definition: Scanner.h:183
FunctionColl_t fSelectedFunctions
Definition: Scanner.h:124
void * ToDeclProp(clang::Decl *item)
Definition: Scanner.cxx:128
The class representing the collection of selection rules.
std::string GetSrcLocation(clang::SourceLocation L) const
Definition: Scanner.cxx:245
bool IsStdClass(const clang::RecordDecl &cl)
Return true, if the decl is part of the std namespace.
void UnimplementedType(clang::QualType qual_type)
Definition: Scanner.cxx:407
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
Definition: Scanner.cxx:1207
bool HasAttributeFilePattern() const
const clang::Type * GetRequestedType() const
const cling::Interpreter & fInterpreter
Definition: Scanner.h:170
void Info(const char *location, const char *va_(fmt),...)
Use this function for informational messages.
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:94
std::string GetName(clang::Decl *D) const
Definition: Scanner.cxx:272
#define F(x, y, z)
std::string APIntToStr(const llvm::APInt &num)
Definition: Scanner.cxx:150
static double C[]
SVector< double, 2 > v
Definition: Dict.h:5
std::string IntToStd(int num)
Definition: Scanner.cxx:166
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:787
bool verbose
static const int fgDeclLast
Definition: Scanner.h:171
EScanType
Definition: Scanner.h:73
bool IsFromTypedef() const
Double_t E()
Definition: TMath.h:54
void ShowError(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:221
bool HasAttributeFileName() const
DeclsSelRulesMap_t fDeclSelRuleMap
Definition: Scanner.h:185
size_t APIntToSize(const llvm::APInt &num)
Definition: Scanner.cxx:136
ClassColl_t fSelectedClasses
Definition: Scanner.h:118
ESelect GetSelected() const
std::string GetEnumName(clang::EnumDecl *D) const
Definition: Scanner.cxx:482
std::string ConvTemplateParams(clang::TemplateDecl *D) const
Type
enumeration specifying the integration types.
const std::string & GetAttributePattern() const
void ShowInfo(const std::string &msg, const std::string &location="") const
Definition: Scanner.cxx:195
void Scan(const clang::ASTContext &C)
Definition: Scanner.cxx:1179
const std::string & GetAttributeName() const
TRObject operator()(const T1 &t1) const
std::string ExprToStr(clang::Expr *expr) const
Definition: Scanner.cxx:506
bool fFirstPass
Definition: Scanner.h:184
bool HasAttributePattern() const
std::string Message(const std::string &msg, const std::string &location)
Definition: Scanner.cxx:175
const char * GetSelFileName() const
TText * text
bool VisitFunctionDecl(clang::FunctionDecl *D)
Definition: Scanner.cxx:1052
const clang::SourceManager * fSourceManager
Definition: Scanner.h:169
Definition: TCling.h:48
void DeclInfo(clang::Decl *D) const
Definition: Scanner.cxx:296
int type
Definition: TGX11.cxx:120
bool VisitEnumDecl(clang::EnumDecl *D)
Definition: Scanner.cxx:993
bool GetHasFileNameRule() const
bool VisitRecordDecl(clang::RecordDecl *D)
Definition: Scanner.cxx:713
std::string ConvTemplateName(clang::TemplateName &N) const
Definition: Scanner.cxx:521
bool fTypeTable[fgTypeLast+1]
Definition: Scanner.h:176
void Warning(const char *location, const char *va_(fmt),...)
Use this function in warning situations.
std::set< clang::RecordDecl * > fselectedRecordDecls
Definition: Scanner.h:182
EnumColl_t fSelectedEnums
Definition: Scanner.h:126
#define name(a, b)
Definition: linkTestLib0.cpp:5
bool TraverseDeclContextHelper(clang::DeclContext *DC)
Definition: Scanner.cxx:1069
bool IsSelectionXMLFile() const
bool VisitNamespaceDecl(clang::NamespaceDecl *D)
This method visits a namespace node.
Definition: Scanner.cxx:664
long GetLineNumber() const
long GetIndex() const
void UnknownType(clang::QualType qual_type) const
Definition: Scanner.cxx:382
#define NULL
Definition: Rtypes.h:82
static const char * fgClangFuncKey
Definition: Scanner.h:116
std::string AddSpace(const std::string &txt)
Definition: Scanner.cxx:286
double result[121]
bool areEqual< ClassSelectionRule >(const ClassSelectionRule *r1, const ClassSelectionRule *r2, bool moduloNameOrPattern)
std::string FuncParameters(clang::FunctionDecl *D) const
Definition: Scanner.cxx:617
bool GetDeclName(clang::Decl *D, std::string &name) const
Definition: Scanner.cxx:1111
string message
Definition: ROOT.py:94
long APIntToLong(const llvm::APInt &num)
Definition: Scanner.cxx:143
DeclCallback fRecordDeclCallback
Definition: Scanner.h:175
#define I(x, y, z)
std::string GetClassName(clang::DeclContext *DC) const
Definition: Scanner.cxx:1099
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:329
bool RequestOnlyTClass() const
bool TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl *typeDecl)
Definition: Scanner.cxx:723
const Int_t n
Definition: legend1.C:16
void UnsupportedType(clang::QualType qual_type) const
Definition: Scanner.cxx:391
static int fgBadClassCounter
Definition: Scanner.h:179
void UnimportantType(clang::QualType qual_type) const
unimportant - this kind of declaration is not stored into reflex
Definition: Scanner.cxx:401
std::string ConvTemplateParameterList(clang::TemplateParameterList *list) const
TypedefColl_t fSelectedTypedefs
Definition: Scanner.h:123