Logo ROOT  
Reference Guide
SelectionRules.cxx
Go to the documentation of this file.
1 // @(#)root/core/utils:$Id: SelectionRules.cxx 41697 2011-11-01 21:03:41Z pcanal $
2 // Author: Velislava Spasova September 2010
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**
13 \class SelectionRules
14 The class representing the collection of selection rules.
15 */
16 
17 #include <iostream>
18 #include <sstream>
19 #include <algorithm>
20 #ifndef WIN32
21 #include <fnmatch.h>
22 #else
23 #include "Shlwapi.h"
24 #define fnmatch(glob, path, dummy) PathMatchSpecA(path, glob);
25 #endif
26 #include "RtypesCore.h"
27 #include "SelectionRules.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "clang/Basic/SourceLocation.h"
30 #include "clang/Basic/SourceManager.h"
31 #include "clang/AST/ASTContext.h"
32 #include "clang/AST/DeclCXX.h"
33 #include "clang/AST/DeclTemplate.h"
34 
35 #include "cling/Interpreter/Interpreter.h"
36 
37 const clang::CXXRecordDecl *R__ScopeSearch(const char *name, const clang::Type** resultType = nullptr) ;
38 
40 {
41  fRulesCounter++;
42  fClassSelectionRules.push_front(classSel);
43  if (!classSel.HasInterpreter())
44  fClassSelectionRules.begin()->SetInterpreter(fInterp);
45  if (classSel.GetIndex() < 0)
46  fClassSelectionRules.begin()->SetIndex(fRulesCounter);
47 }
48 
50 {
51  fRulesCounter++;
52  fFunctionSelectionRules.push_back(funcSel);
53  if (!funcSel.HasInterpreter())
54  fFunctionSelectionRules.begin()->SetInterpreter(fInterp);
55  if (funcSel.GetIndex() < 0)
56  fFunctionSelectionRules.begin()->SetIndex(fRulesCounter);
57 }
58 
60 {
61  fRulesCounter++;
62  fVariableSelectionRules.push_back(varSel);
63  if (!varSel.HasInterpreter())
64  fVariableSelectionRules.begin()->SetInterpreter(fInterp);
65  if (varSel.GetIndex() < 0)
66  fVariableSelectionRules.begin()->SetIndex(fRulesCounter);
67 }
68 
70 {
71  fRulesCounter++;
72  fEnumSelectionRules.push_back(enumSel);
73  if (!enumSel.HasInterpreter())
74  fEnumSelectionRules.begin()->SetInterpreter(fInterp);
75  if (enumSel.GetIndex() < 0)
76  fEnumSelectionRules.begin()->SetIndex( fRulesCounter );
77 }
78 
80 {
81  std::cout<<"Printing Selection Rules:"<<std::endl;
82  if (!fClassSelectionRules.empty()) {
83  int i = 0;
84  for(std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
85  it != fClassSelectionRules.end(); ++it, ++i) {
86  std::cout<<"\tClass sel rule "<<i<<":"<<std::endl;
87  std::cout<< *it;
88  }
89  }
90  else {
91  std::cout<<"\tNo Class Selection Rules"<<std::endl;
92  }
93 
94  if (!fFunctionSelectionRules.empty()) {
95  //std::cout<<""<<std::endl;
96  std::list<FunctionSelectionRule>::const_iterator it2;
97  int i = 0;
98 
99  for (it2 = fFunctionSelectionRules.begin(); it2 != fFunctionSelectionRules.end(); ++it2, ++i) {
100  std::cout<<"\tFunction sel rule "<<i<<":"<<std::endl;
101  std::cout<<"\t\tSelected: ";
102  switch(it2->GetSelected()){
103  case BaseSelectionRule::kYes: std::cout<<"Yes"<<std::endl;
104  break;
105  case BaseSelectionRule::kNo: std::cout<<"No"<<std::endl;
106  break;
107  case BaseSelectionRule::kDontCare: std::cout<<"Don't Care"<<std::endl;
108  break;
109  default: std::cout<<"Unspecified"<<std::endl;
110  }
111  it2->PrintAttributes(std::cout,2);
112  }
113  }
114  else {
115  std::cout<<"\tNo function sel rules"<<std::endl;
116  }
117 
118  if (!fVariableSelectionRules.empty()) {
119  std::list<VariableSelectionRule>::const_iterator it3;
120  int i = 0;
121 
122  for (it3 = fVariableSelectionRules.begin(); it3 != fVariableSelectionRules.end(); ++it3, ++i) {
123  std::cout<<"\tVariable sel rule "<<i<<":"<<std::endl;
124  std::cout<<"\t\tSelected: ";
125  switch(it3->GetSelected()){
126  case BaseSelectionRule::kYes: std::cout<<"Yes"<<std::endl;
127  break;
128  case BaseSelectionRule::kNo: std::cout<<"No"<<std::endl;
129  break;
130  case BaseSelectionRule::kDontCare: std::cout<<"Don't Care"<<std::endl;
131  break;
132  default: std::cout<<"Unspecified"<<std::endl;
133  }
134  it3->PrintAttributes(std::cout,2);
135  }
136  }
137  else {
138  std::cout<<"\tNo variable sel rules"<<std::endl;
139  }
140 
141  if (!fEnumSelectionRules.empty()) {
142  std::list<EnumSelectionRule>::const_iterator it4;
143  int i = 0;
144 
145  for (it4 = fEnumSelectionRules.begin(); it4 != fEnumSelectionRules.end(); ++it4, ++i) {
146  std::cout<<"\tEnum sel rule "<<i<<":"<<std::endl;
147  std::cout<<"\t\tSelected: ";
148  switch(it4->GetSelected()){
149  case BaseSelectionRule::kYes: std::cout<<"Yes"<<std::endl;
150  break;
151  case BaseSelectionRule::kNo: std::cout<<"No"<<std::endl;
152  break;
153  case BaseSelectionRule::kDontCare: std::cout<<"Don't Care"<<std::endl;
154  break;
155  default: std::cout<<"Unspecified"<<std::endl;
156  }
157  it4->PrintAttributes(std::cout,2);
158  }
159  }
160  else {
161  std::cout<<"\tNo enum sel rules"<<std::endl;
162  }
163 }
164 
166 {
167  fClassSelectionRules.clear();
168  fFunctionSelectionRules.clear();
169  fVariableSelectionRules.clear();
170  fEnumSelectionRules.clear();
171 }
172 
173 template<class RULE>
174 static bool HasDuplicate(RULE* rule,
175  std::unordered_map<std::string,RULE*>& storedRules,
176  const std::string& attrName){
177  auto itRetCodePair = storedRules.emplace( attrName, rule );
178 
179  auto storedRule = storedRules[attrName];
180 
181  if (itRetCodePair.second ||
182  storedRule->GetSelected() != rule->GetSelected()) return false;
183  auto areEqual = SelectionRulesUtils::areEqual(storedRule,rule);
184 
185  std::stringstream sstr; sstr << "Rule:\n";
186  rule->Print(sstr);
187  sstr << (areEqual ? "Identical " : "Conflicting ");
188  sstr << "rule already stored:\n";
189  storedRule->Print(sstr);
190  ROOT::TMetaUtils::Warning("SelectionRules::CheckDuplicates",
191  "Duplicated rule found.\n%s",sstr.str().c_str());
192  return !areEqual;
193 }
194 
195 template<class RULESCOLLECTION, class RULE = typename RULESCOLLECTION::value_type>
196 static int CheckDuplicatesImp(RULESCOLLECTION& rules){
197  int nDuplicates = 0;
198  std::unordered_map<std::string, RULE*> patterns,names;
199  for (auto&& rule : rules){
200  if (rule.HasAttributeName() && HasDuplicate(&rule,names,rule.GetAttributeName())) nDuplicates++;
201  if (rule.HasAttributePattern() && HasDuplicate(&rule,patterns,rule.GetAttributePattern())) nDuplicates++;
202  }
203  return nDuplicates;
204 }
205 
207 
208  int nDuplicates = 0;
212  nDuplicates += CheckDuplicatesImp(fEnumSelectionRules);
213  if (0 != nDuplicates){
214  ROOT::TMetaUtils::Error("SelectionRules::CheckDuplicates",
215  "Duplicates in rules were found.\n");
216  }
217  return nDuplicates;
218 }
219 
220 static bool Implies(const ClassSelectionRule& patternRule, const ClassSelectionRule& nameRule){
221 
222  // Check if these both select or both exclude
223  if (patternRule.GetSelected() != nameRule.GetSelected()) return false;
224 
225  // If the two rules are not compatible modulo their name/pattern, bail out
226  auto nAttrsPattern = patternRule.GetAttributes().size();
227  auto nAttrsName = nameRule.GetAttributes().size();
228  if ((nAttrsPattern != 1 || nAttrsName !=1) &&
229  !SelectionRulesUtils::areEqual(&patternRule, &nameRule, true /*moduloNameOrPattern*/)) {
230  return false;
231  }
232 
233  auto pattern = patternRule.GetAttributePattern().c_str();
234  auto name = nameRule.GetAttributeName().c_str();
235 
236  // Now check if the pattern matches the name
237  auto implies = 0 == fnmatch(pattern, name, FNM_PATHNAME);
238 
239  if (implies){
240  static const auto msg = "The pattern rule %s matches the name rule %s. "
241  "Since the name rule has compatible attributes, "
242  "it will be removed: the pattern rule will match the necessary classes if needed.\n";
243 
244  ROOT::TMetaUtils::Info("SelectionRules::Optimize", msg, pattern, name);
245  }
246 
247 
248  return implies;
249 
250 }
251 
253 
254  // Remove name rules "implied" by pattern rules
255 
256  if (!IsSelectionXMLFile()) return;
257 
258  const auto& selectionRules = fClassSelectionRules;
259 
260  auto predicate = [&selectionRules](const ClassSelectionRule &rule) -> bool {
261  if (rule.HasAttributeName()) {
262  for (auto&& intRule : selectionRules){
263  if (intRule.HasAttributePattern() && Implies(intRule, rule)) {
264  return true;
265  }
266  }
267  }
268  return false;
269  };
270  fClassSelectionRules.remove_if(predicate);
271 }
272 
273 const ClassSelectionRule *SelectionRules::IsDeclSelected(const clang::RecordDecl *D, bool includeTypedefRule) const
274 {
275  std::string qual_name;
276  GetDeclQualName(D,qual_name);
277  return IsClassSelected(D, qual_name, includeTypedefRule);
278 }
279 
280 const ClassSelectionRule *SelectionRules::IsDeclSelected(const clang::TypedefNameDecl *D) const
281 {
282  std::string qual_name;
283  GetDeclQualName(D,qual_name);
284  return IsClassSelected(D, qual_name, true);
285 }
286 
287 const ClassSelectionRule *SelectionRules::IsDeclSelected(const clang::NamespaceDecl *D) const
288 {
289  std::string qual_name;
290  GetDeclQualName(D,qual_name);
291  return IsNamespaceSelected(D, qual_name);
292 }
293 
294 const BaseSelectionRule *SelectionRules::IsDeclSelected(const clang::EnumDecl *D) const
295 {
296  // Currently rootcling does not need any information on enums, except
297  // for the PCM / proto classes that register them to build TEnums without
298  // parsing. This can be removed once (real) PCMs are available.
299  // Note that the code below was *not* properly matching the case
300  // typedef enum { ... } abc;
301  // as the typedef is stored as an anonymous EnumDecl in clang.
302  // It is likely that using a direct lookup on the name would
303  // return the appropriate typedef (and then we would need to
304  // select 'both' the typedef and the anonymous enums.
305 
306 #if defined(R__MUST_REVISIT)
307 # if R__MUST_REVISIT(6,4)
308  "Can become no-op once PCMs are available."
309 # endif
310 #endif
311 
312  std::string str_name; // name of the Decl
313  std::string qual_name; // fully qualified name of the Decl
314  GetDeclName(D, str_name, qual_name);
315 
316  if (IsParentClass(D)) {
317  const BaseSelectionRule *selector = IsMemberSelected(D, str_name);
318  if (!selector) // if the parent class is deselected, we could still select the enum
319  return IsEnumSelected(D, qual_name);
320  else // if the parent class is selected so are all nested enums
321  return selector;
322  }
323 
324  // Enum is not part of a class
325  else {
326  if (IsLinkdefFile())
327  return IsLinkdefEnumSelected(D, qual_name);
328  return IsEnumSelected(D, qual_name);
329  }
330 
331  return nullptr;
332 }
333 
334 const BaseSelectionRule *SelectionRules::IsDeclSelected(const clang::VarDecl* D) const
335 {
336  std::string qual_name; // fully qualified name of the Decl
337  GetDeclQualName(D, qual_name);
338 
339  if (IsLinkdefFile())
340  return IsLinkdefVarSelected(D, qual_name);
341  else
342  return IsVarSelected(D, qual_name);
343 
344 }
345 
346 const BaseSelectionRule *SelectionRules::IsDeclSelected(const clang::FieldDecl* /* D */) const
347 {
348  // Currently rootcling does not need any information about fields.
349  return nullptr;
350 #if 0
351  std::string str_name; // name of the Decl
352  std::string qual_name; // fully qualified name of the Decl
353  GetDeclName(D, str_name, qual_name);
354 
355  return IsMemberSelected(D, str_name);
356 #endif
357 }
358 
359 const BaseSelectionRule *SelectionRules::IsDeclSelected(const clang::FunctionDecl* D) const
360 {
361  // Implement a simple matching for functions
362  std::string qual_name; // fully qualified name of the Decl
363  GetDeclQualName(D, qual_name);
364  if (IsLinkdefFile())
365  return IsLinkdefFunSelected(D, qual_name);
366  else
367  return IsFunSelected(D, qual_name);
368 }
369 
370 const BaseSelectionRule *SelectionRules::IsDeclSelected(const clang::Decl *D) const
371 {
372  if (!D) {
373  return nullptr;
374  }
375 
376  clang::Decl::Kind declkind = D->getKind();
377 
378  switch (declkind) {
379  case clang::Decl::CXXRecord:
380  case clang::Decl::ClassTemplateSpecialization:
381  case clang::Decl::ClassTemplatePartialSpecialization:
382  // structs, unions and classes are all CXXRecords
383  return IsDeclSelected(llvm::dyn_cast<clang::RecordDecl>(D));
384  case clang::Decl::Namespace:
385  return IsDeclSelected(llvm::dyn_cast<clang::NamespaceDecl>(D));
386  case clang::Decl::Enum:
387  // Enum is part of a class
388  return IsDeclSelected(llvm::dyn_cast<clang::EnumDecl>(D));
389  case clang::Decl::Var:
390  return IsDeclSelected(llvm::dyn_cast<clang::VarDecl>(D));
391 #if ROOTCLING_NEEDS_FUNCTIONS_SELECTION
393  return IsDeclSelected(llvm::dyn_cast<clang::FunctionDecl>(D));
394  case clang::Decl::CXXMethod:
395  case clang::Decl::CXXConstructor:
396  case clang::Decl::CXXDestructor: {
397  // std::string proto;
398  // if (GetFunctionPrototype(D,proto))
399  // std::cout<<"\n\tFunction prototype: "<<str_name + proto;
400  // else
401  // std::cout<<"Error in prototype formation";
402  std::string str_name; // name of the Decl
403  std::string qual_name; // fully qualified name of the Decl
404  GetDeclName(D, str_name, qual_name);
405  if (IsLinkdefFile()) {
406  return IsLinkdefMethodSelected(D, qual_name);
407  }
408  return IsMemberSelected(D, str_name);
409  }
410 #endif
411  case clang::Decl::Field:
412  return IsDeclSelected(llvm::dyn_cast<clang::FieldDecl>(D));
413  default:
414  // Humm we are not treating this case!
415  return nullptr;
416  }
417 
418  // std::string str_name; // name of the Decl
419  // std::string qual_name; // fully qualified name of the Decl
420  // GetDeclName(D, str_name, qual_name);
421  // fprintf(stderr,"IsDeclSelected: %s %s\n", str_name.c_str(), qual_name.c_str());
422 }
423 
424 
425 bool SelectionRules::GetDeclName(const clang::Decl* D, std::string& name, std::string& qual_name) const
426 {
427  const clang::NamedDecl* N = llvm::dyn_cast<clang::NamedDecl> (D);
428 
429  if (!N)
430  return false;
431 
432  // the identifier is NULL for some special methods like constructors, destructors and operators
433  if (N->getIdentifier()) {
434  name = N->getNameAsString();
435  }
436  else if (N->isCXXClassMember()) { // for constructors, destructors, operator=, etc. methods
437  name = N->getNameAsString(); // we use this (unefficient) method to Get the name in that case
438  }
439  llvm::raw_string_ostream stream(qual_name);
440  N->getNameForDiagnostic(stream,N->getASTContext().getPrintingPolicy(),true);
441  return true;
442 }
443 
444 void SelectionRules::GetDeclQualName(const clang::Decl* D, std::string& qual_name) const
445 {
446  const clang::NamedDecl* N = static_cast<const clang::NamedDecl*> (D);
447  llvm::raw_string_ostream stream(qual_name);
448  if (N)
449  N->getNameForDiagnostic(stream,N->getASTContext().getPrintingPolicy(),true);
450 }
451 
452 bool SelectionRules::GetFunctionPrototype(const clang::FunctionDecl* F, std::string& prototype) const
453 {
454 
455  if (!F) {
456  return false;
457  }
458 
459  const std::vector<std::string> quals={"*","&"};
460 
461  prototype = "";
462  // iterate through all the function parameters
463  std::string type;
464  for (auto I = F->param_begin(), E = F->param_end(); I != E; ++I) {
465 
466  clang::ParmVarDecl* P = *I;
467 
468  if (prototype != "")
469  prototype += ",";
470 
472 
473  // We need to get rid of the "class " string if present
474  ROOT::TMetaUtils::ReplaceAll(type,"class ", "");
475  // We need to get rid of the "restrict " string if present
476  ROOT::TMetaUtils::ReplaceAll(type,"restrict", "");
477 
478  // pointers are returned in the form "int *" and I need them in the form "int*"
479  // same for &
480  for (auto& qual : quals){
481  auto pos = type.find(" "+qual);
482  if (pos != std::string::npos)
483  type.replace( pos, 2, qual );
484  }
485 // for (auto& qual : quals){
486 // if (type.at(type.length()-1) == qual && type.at(type.length()-2) == ' ') {
487 // type.at(type.length()-2) = qual;
488 // type.erase(type.length()-1);
489 // }
490 // }
491  prototype += type;
492  }
493  prototype = "(" + prototype + ")";
494  return true;
495 
496 }
497 
498 
499 bool SelectionRules::IsParentClass(const clang::Decl* D) const
500 {
501  //TagDecl has methods to understand of what kind is the Decl - class, struct or union
502  if (!D)
503  return false;
504  if (const clang::TagDecl *T = llvm::dyn_cast<clang::TagDecl>(
505  D->getDeclContext()))
506  return T->isClass() || T->isStruct();
507  return false;
508 }
509 
510 
511 bool SelectionRules::IsParentClass(const clang::Decl* D, std::string& parent_name, std::string& parent_qual_name) const
512 {
513  if (const clang::TagDecl* parent
514  = llvm::dyn_cast<clang::TagDecl>(D->getDeclContext())) {
515  if (parent->isClass()|| parent->isStruct()) {
516  GetDeclName(parent, parent_name, parent_qual_name);
517  return true;
518  }
519  }
520  return false;
521 }
522 
523 bool SelectionRules::GetParentName(const clang::Decl* D, std::string& parent_name, std::string& parent_qual_name) const
524 {
525  if (const clang::RecordDecl* parent
526  = llvm::dyn_cast<clang::RecordDecl>(D->getDeclContext())) {
527  GetDeclName(parent, parent_name, parent_qual_name);
528  return true;
529  }
530  return false;
531 }
532 
533 /* This is the method that crashes
534  bool SelectionRules::GetParent(clang::Decl* D, clang::Decl* parent)
535  {
536  clang::DeclContext *ctx = D->GetDeclContext();
537 
538  if (ctx->isRecord()){
539  //DEBUG std::cout<<"\n\tDeclContext is Record";
540  parent = llvm::dyn_cast<clang::Decl> (ctx);
541  if (!parent) {
542  return false;
543  }
544  else {
545  return true;
546  }
547  }
548  else return false;
549  }
550  */
551 
552 
553 // isClassSelected checks if a class is selected or not. Thre is a difference between the
554 // behaviour of rootcint and genreflex especially with regard to class pattern processing.
555 // In genreflex if we have <class pattern = "*" /> this will select all the classes
556 // (and structs) found in the header file. In rootcint if we have something similar, i.e.
557 // #pragma link C++ class *, we will select only the outer classes - for the nested
558 // classes we have to specifie #pragma link C++ class *::*. And yet this is only valid
559 // for one level of nesting - if you need it for many levels of nesting, you will
560 // probably have to implement it yourself.
561 // Here the idea is the following - we traverse the list of class selection rules.
562 // For every class we check do we have a class selection rule. We use here the
563 // method isSelected() (defined in BaseSelectionRule.cxx). This method returns true
564 // only if we have class selection rule which says "Select". Otherwise it returns
565 // false - in which case we have to check wether we found a class selection rule
566 // which says "Veto" (noName = false and don't Care = false; OR noName = false and
567 // don't Care = true and we don't have neither method nor field selection rules -
568 // which is for the selection.xml file case). If noName is true than we just continue -
569 // this means that the current class selection rule isn't applicable for this class.
570 
571 const ClassSelectionRule *SelectionRules::IsNamespaceSelected(const clang::Decl* D, const std::string& qual_name) const
572 {
573  const clang::NamespaceDecl* N = llvm::dyn_cast<clang::NamespaceDecl> (D); //TagDecl has methods to understand of what kind is the Decl
574  if (N==nullptr) {
575  std::cout<<"\n\tCouldn't cast Decl to NamespaceDecl";
576  return nullptr;
577  }
578 
579  const ClassSelectionRule *selector = nullptr;
580  int fImplNo = 0;
581  const ClassSelectionRule *explicit_selector = nullptr;
582  const ClassSelectionRule *specific_pattern_selector = nullptr;
583  int fFileNo = 0;
584 
585  // NOTE: should we separate namespaces from classes in the rules?
586  std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
587  // iterate through all class selection rles
588  std::string name_value;
589  std::string pattern_value;
591  for(; it != fClassSelectionRules.end(); ++it) {
592 
593  match = it->Match(N,qual_name,"",IsLinkdefFile());
594 
595  if (match != BaseSelectionRule::kNoMatch) {
596  // If we have a match.
597  if (it->GetSelected() == BaseSelectionRule::kYes) {
598  selector = &(*it);
599  if (IsLinkdefFile()){
600  // rootcint prefers explicit rules over pattern rules
601  if (match == BaseSelectionRule::kName) {
602  explicit_selector = &(*it);
603  } else if (match == BaseSelectionRule::kPattern) {
604  // NOTE: weird ...
605  if (it->GetAttributeValue("pattern", pattern_value) &&
606  pattern_value != "*" && pattern_value != "*::*") specific_pattern_selector = &(*it);
607  }
608  }
609  } else if (it->GetSelected() == BaseSelectionRule::kNo) {
610  if (!IsLinkdefFile()) {
611  // in genreflex - we could explicitly select classes from other source files
612  if (match == BaseSelectionRule::kFile) ++fFileNo; // if we have veto because of class defined in other source file -> implicit No
613  else {
614 
615 #ifdef SELECTION_DEBUG
616  std::cout<<"\tNo returned"<<std::endl;
617 #endif
618 
619  return nullptr; // explicit No returned
620  }
621  }
622  if (match == BaseSelectionRule::kPattern) {
623  //this is for the Linkdef selection
624  if (it->GetAttributeValue("pattern", pattern_value) &&
625  (pattern_value == "*" || pattern_value == "*::*")) ++fImplNo;
626  else
627  return nullptr;
628  }
629  else
630  return nullptr;
631  }
632  else if (it->GetSelected() == BaseSelectionRule::kDontCare && !(it->HasMethodSelectionRules()) && !(it->HasFieldSelectionRules())) {
633 
634 #ifdef SELECTION_DEBUG
635  std::cout<<"Empty dontC returned = No"<<std::endl;
636 #endif
637 
638  return nullptr;
639  }
640  }
641  }
642  if (IsLinkdefFile()) {
643  // for rootcint explicit (name) Yes is stronger than implicit (pattern) No which is stronger than implicit (pattern) Yes
644 
645 #ifdef SELECTION_DEBUG
646  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
647 #endif
648 
649  if (explicit_selector) return explicit_selector;
650  else if (specific_pattern_selector) return specific_pattern_selector;
651  else if (fImplNo > 0) return nullptr;
652  else return selector;
653  }
654  else {
655  // for genreflex explicit Yes is stronger than implicit file No
656 
657 #ifdef SELECTION_DEBUG
658  std::cout<<"\n\tfYes = "<<fYes<<", fFileNo = "<<fFileNo<<std::endl;
659 #endif
660 
661  if (selector)
662  return selector;
663  else
664  return nullptr;
665  }
666 
667 }
668 
669 
670 const ClassSelectionRule *SelectionRules::IsClassSelected(const clang::Decl* D, const std::string& qual_name, bool includeTypedefRule) const
671 {
672  const clang::TagDecl* tagDecl = llvm::dyn_cast<clang::TagDecl> (D); //TagDecl has methods to understand of what kind is the Decl
673  const clang::TypedefNameDecl* typeDefNameDecl = llvm::dyn_cast<clang::TypedefNameDecl> (D);
674 
675  if (!tagDecl && !typeDefNameDecl) { // Ill posed
676  ROOT::TMetaUtils::Error("SelectionRules::IsClassSelected",
677  "Cannot cast Decl to TagDecl and Decl is not a typedef.\n");
678  return nullptr;
679  }
680 
681  if (!tagDecl && typeDefNameDecl){ // Let's try to fetch the underlying RecordDecl
682  clang::RecordDecl* recordDecl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(typeDefNameDecl->getUnderlyingType());
683  if (!recordDecl){
684  ROOT::TMetaUtils::Error("SelectionRules::IsClassSelected",
685  "Cannot get RecordDecl behind TypedefDecl.\n");
686  return nullptr;
687  }
688  tagDecl = recordDecl;
689  }
690 
691  // At this point tagDecl must be well defined
692  const bool isLinkDefFile = IsLinkdefFile();
693  if (!( isLinkDefFile || tagDecl->isClass() || tagDecl->isStruct() ))
694  return nullptr; // Union for Genreflex
695 
696  const ClassSelectionRule *selector = nullptr;
697  int fImplNo = 0;
698  const ClassSelectionRule *explicit_selector = nullptr;
699  const ClassSelectionRule *specific_pattern_selector = nullptr;
700  int fFileNo = 0;
701 
702  // iterate through all class selection rles
703  bool earlyReturn=false;
704  const ClassSelectionRule* retval = nullptr;
705  const clang::NamedDecl* nDecl(llvm::dyn_cast<clang::NamedDecl>(D));
706  for(auto& rule : fClassSelectionRules) {
707  if (!includeTypedefRule && rule.IsFromTypedef())
708  continue;
709  BaseSelectionRule::EMatchType match = rule.Match(nDecl, qual_name, "", isLinkDefFile);
710  if (match != BaseSelectionRule::kNoMatch) {
711  // Check if the template must have its arguments manipulated
712  if (const clang::ClassTemplateSpecializationDecl* ctsd =
713  llvm::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(D))
714  if(const clang::ClassTemplateDecl* ctd = ctsd->getSpecializedTemplate()){
715  const std::string& nArgsToKeep = rule.GetAttributeNArgsToKeep();
716  if (!nArgsToKeep.empty()){
717  fNormCtxt.AddTemplAndNargsToKeep(ctd->getCanonicalDecl(),
718  std::atoi(nArgsToKeep.c_str()));
719  }
720  }
721 
722  if (earlyReturn) continue;
723 
724  // If we have a match.
725  selector = &(rule);
726  if (rule.GetSelected() == BaseSelectionRule::kYes) {
727 
728  if (isLinkDefFile){
729  // rootcint prefers explicit rules over pattern rules
730  if (match == BaseSelectionRule::kName) {
731  explicit_selector = &(rule);
732  } else if (match == BaseSelectionRule::kPattern) {
733  // NOTE: weird ...
734  const std::string& pattern_value=rule.GetAttributePattern();
735  if (!pattern_value.empty() &&
736  pattern_value != "*" &&
737  pattern_value != "*::*") specific_pattern_selector = &(rule);
738  }
739  }
740  } else if (rule.GetSelected() == BaseSelectionRule::kNo) {
741 
742  if (!isLinkDefFile) {
743  // in genreflex - we could explicitly select classes from other source files
744  if (match == BaseSelectionRule::kFile) ++fFileNo; // if we have veto because of class defined in other source file -> implicit No
745  else {
746  retval = selector;
747  earlyReturn=true; // explicit No returned
748  }
749  }
750  if (match == BaseSelectionRule::kPattern) {
751  //this is for the Linkdef selection
752  const std::string& pattern_value=rule.GetAttributePattern();
753  if (!pattern_value.empty() &&
754  (pattern_value == "*" || pattern_value == "*::*")) ++fImplNo;
755  else
756  earlyReturn=true;
757  }
758  else
759  earlyReturn=true;
760  }
761  else if (rule.GetSelected() == BaseSelectionRule::kDontCare && !(rule.HasMethodSelectionRules()) && !(rule.HasFieldSelectionRules())) {
762  earlyReturn=true;
763  }
764  }
765  } // Loop over the rules.
766 
767  if (earlyReturn) return retval;
768 
769  if (isLinkDefFile) {
770  // for rootcint explicit (name) Yes is stronger than implicit (pattern) No which is stronger than implicit (pattern) Yes
771  if (explicit_selector) return explicit_selector;
772  else if (specific_pattern_selector) return specific_pattern_selector;
773  else if (fImplNo > 0) return nullptr;
774  else return selector;
775  }
776  else {
777  // for genreflex explicit Yes is stronger than implicit file No
778  return selector; // it can be nullptr
779  }
780 
781 }
782 
783 const BaseSelectionRule *SelectionRules::IsVarSelected(const clang::VarDecl* D, const std::string& qual_name) const
784 {
785  std::list<VariableSelectionRule>::const_iterator it = fVariableSelectionRules.begin();
786  std::list<VariableSelectionRule>::const_iterator it_end = fVariableSelectionRules.end();
787 
788  const BaseSelectionRule *selector = nullptr;
789 
790  // iterate through all the rules
791  // we call this method only for genrefex variables, functions and enums - it is simpler than the class case:
792  // if we have No - it is veto even if we have explicit yes as well
793  for(; it != it_end; ++it) {
794  if (BaseSelectionRule::kNoMatch != it->Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false)) {
795  if (it->GetSelected() == BaseSelectionRule::kNo) {
796  // The rule did explicitly request to not select this entity.
797  return nullptr;
798  } else {
799  selector = &(*it);
800  }
801  }
802  }
803 
804  return selector;
805 }
806 
807 const BaseSelectionRule *SelectionRules::IsFunSelected(const clang::FunctionDecl *D, const std::string &qual_name) const
808 {
809 
810  if (fFunctionSelectionRules.size() == 0 ||
811  D->getPrimaryTemplate() != nullptr ||
812  llvm::isa<clang::CXXMethodDecl>(D)) return nullptr;
813 
814  std::string prototype;
815  GetFunctionPrototype(D, prototype);
816  prototype = qual_name + prototype;
817 
818  const BaseSelectionRule *selector = nullptr;
819  // iterate through all the rules
820  // we call this method only for genrefex variables, functions and enums - it is simpler than the class case:
821  // if we have No - it is veto even if we have explicit yes as well
822  for (const auto & rule : fFunctionSelectionRules) {
823  if (BaseSelectionRule::kNoMatch != rule.Match(D, qual_name, prototype, false)) {
824  if (rule.GetSelected() == BaseSelectionRule::kNo) {
825  // The rule did explicitly request to not select this entity.
826  return nullptr;
827  } else {
828  selector = &(rule);
829  }
830  }
831  }
832 
833  return selector;
834 }
835 
836 const BaseSelectionRule *SelectionRules::IsEnumSelected(const clang::EnumDecl* D, const std::string& qual_name) const
837 {
838  const BaseSelectionRule *selector = nullptr;
839 
840  // iterate through all the rules
841  // we call this method only for genrefex variables, functions and enums - it is simpler than the class case:
842  // if we have No - it is veto even if we have explicit yes as well
843  for(const auto& rule: fEnumSelectionRules) {
844  if (BaseSelectionRule::kNoMatch != rule.Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false)) {
845  if (rule.GetSelected() == BaseSelectionRule::kNo) {
846  // The rule did explicitly request to not select this entity.
847  return nullptr;
848  } else {
849  selector = &rule;
850  }
851  }
852  }
853 
854  return selector;
855 }
856 
857 const BaseSelectionRule *SelectionRules::IsLinkdefVarSelected(const clang::VarDecl* D, const std::string& qual_name) const
858 {
859 
860 
861  const BaseSelectionRule *selector = nullptr;
862  int fImplNo = 0;
863  const BaseSelectionRule *explicit_selector = nullptr;
864 
865  std::string name_value;
866  std::string pattern_value;
867  for(auto& selRule: fVariableSelectionRules) {
869  = selRule.Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false);
870  if (match != BaseSelectionRule::kNoMatch) {
871  if (selRule.GetSelected() == BaseSelectionRule::kYes) {
872  // explicit rules are with stronger priority in rootcint
873  if (IsLinkdefFile()){
874  if (match == BaseSelectionRule::kName) {
875  explicit_selector = &selRule;
876  } else if (match == BaseSelectionRule::kPattern) {
877  if (selRule.GetAttributeValue("pattern", pattern_value)) {
878  explicit_selector=&selRule;
879  // NOTE: Weird ... This is a strange definition of explicit.
880  //if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = selRule;
881  }
882  }
883  }
884  }
885  else {
886  if (!IsLinkdefFile()) return nullptr;
887  else {
888  if (selRule.GetAttributeValue("pattern", pattern_value)) {
889  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
890  else
891  return nullptr;
892  }
893  else
894  return nullptr;
895  }
896  }
897  }
898  }
899 
900  if (IsLinkdefFile()) {
901 
902 #ifdef SELECTION_DEBUG
903  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
904 #endif
905 
906  if (explicit_selector) return explicit_selector;
907  else if (fImplNo > 0) return nullptr;
908  else return selector;
909  }
910  else{
911  return selector;
912  }
913 }
914 
915 const BaseSelectionRule *SelectionRules::IsLinkdefFunSelected(const clang::FunctionDecl* D, const std::string& qual_name) const
916 {
917 
918  if (fFunctionSelectionRules.size() == 0 ||
919  D->getPrimaryTemplate() != nullptr ||
920  llvm::isa<clang::CXXMethodDecl>(D)) return nullptr;
921 
922  std::string prototype;
923 
924  GetFunctionPrototype(D, prototype);
925  prototype = qual_name + prototype;
926 
927  const BaseSelectionRule *selector = nullptr;
928  int fImplNo = 0;
929  const BaseSelectionRule *explicit_selector = nullptr;
930 
931  std::string pattern_value;
932  for(auto& selRule : fFunctionSelectionRules) {
934  = selRule.Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, prototype, false);
935  if (match != BaseSelectionRule::kNoMatch) {
936  if (selRule.GetSelected() == BaseSelectionRule::kYes) {
937  // explicit rules are with stronger priority in rootcint
938  if (IsLinkdefFile()){
939  if (match == BaseSelectionRule::kName) {
940  explicit_selector = &selRule;
941  } else if (match == BaseSelectionRule::kPattern) {
942  if (selRule.GetAttributeValue("pattern", pattern_value)) {
943  explicit_selector = &selRule;
944  // NOTE: Weird ... This is a strange definition of explicit.
945  //if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &selRule;
946  }
947  }
948  }
949  }
950  else {
951  if (!IsLinkdefFile()) return nullptr;
952  else {
953  if (selRule.GetAttributeValue("pattern", pattern_value)) {
954  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
955  else
956  return nullptr;
957  }
958  else
959  return nullptr;
960  }
961  }
962  }
963  }
964 
965  if (IsLinkdefFile()) {
966  if (explicit_selector) return explicit_selector;
967  else if (fImplNo > 0) return nullptr;
968  else return selector;
969  }
970  else{
971  return selector;
972  }
973 }
974 
975 const BaseSelectionRule *SelectionRules::IsLinkdefEnumSelected(const clang::EnumDecl* D, const std::string& qual_name) const
976 {
977  std::list<VariableSelectionRule>::const_iterator it;
978  std::list<VariableSelectionRule>::const_iterator it_end;
979 
980  it = fEnumSelectionRules.begin();
981  it_end = fEnumSelectionRules.end();
982 
983  const BaseSelectionRule *selector = nullptr;
984  int fImplNo = 0;
985  const BaseSelectionRule *explicit_selector = nullptr;
986 
987  std::string name_value;
988  std::string pattern_value;
989  for(; it != it_end; ++it) {
991  it->Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false);
992  if (match != BaseSelectionRule::kNoMatch) {
993  if (it->GetSelected() == BaseSelectionRule::kYes) {
994  // explicit rules are with stronger priority in rootcint
995  if (IsLinkdefFile()){
996  if (match == BaseSelectionRule::kName){
997  explicit_selector = &(*it);
998  } else if (match == BaseSelectionRule::kPattern &&
999  it->GetAttributeValue("pattern", pattern_value)) {
1000  // Note: Weird ... This is a strange definition of explicit.
1001  if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it);
1002  }
1003  }
1004  }
1005  else {
1006  if (!IsLinkdefFile()) return nullptr;
1007  else {
1008  if (it->GetAttributeValue("pattern", pattern_value)) {
1009  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
1010  else
1011  return nullptr;
1012  }
1013  else
1014  return nullptr;
1015  }
1016  }
1017  }
1018  }
1019 
1020  if (IsLinkdefFile()) {
1021 
1022 #ifdef SELECTION_DEBUG
1023  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
1024 #endif
1025 
1026  if (explicit_selector) return explicit_selector;
1027  else if (fImplNo > 0) return nullptr;
1028  else return selector;
1029  }
1030  else{
1031  return selector;
1032  }
1033 }
1034 
1035 // In rootcint we could select and deselect methods independantly of the class/struct/union rules
1036 // That's why we first have to check the explicit rules for the functions - to see if there
1037 // is rule corresponding to our method.
1038 // Which is more - if we have (and we can have) a pattern for the parent class, than a pattern for the
1039 // nested class, than a pattern for certain methods in the nested class, than a rule for a
1040 // method (name or prototype) in the nested class - the valid rule is the last one.
1041 // This is true irrespective of the rules (select/deselect). This is not the case for genreflex -
1042 // in genreflex if there is a pattern deselecting something even if we have an explicit rule
1043 // to select it, it still will not be selected.
1044 // This method (isLinkdefMethodSelected()) might be incomplete (but I didn't have the time to think
1045 // of anything better)
1046 //
1047 
1048 const BaseSelectionRule *SelectionRules::IsLinkdefMethodSelected(const clang::Decl* D, const std::string& qual_name) const
1049 {
1050  std::list<FunctionSelectionRule>::const_iterator it = fFunctionSelectionRules.begin();
1051  std::list<FunctionSelectionRule>::const_iterator it_end = fFunctionSelectionRules.end();
1052  std::string prototype;
1053 
1054  if (const clang::FunctionDecl* F = llvm::dyn_cast<clang::FunctionDecl> (D))
1055  GetFunctionPrototype(F, prototype);
1056  prototype = qual_name + prototype;
1057 
1058 #ifdef SELECTION_DEBUG
1059  std::cout<<"\tFunction prototype = "<<prototype<<std::endl;
1060 #endif
1061 
1062  int expl_Yes = 0, impl_r_Yes = 0, impl_rr_Yes = 0;
1063  int impl_r_No = 0, impl_rr_No = 0;
1064  const BaseSelectionRule *explicit_r = nullptr;
1065  const BaseSelectionRule *implicit_r = nullptr;
1066  const BaseSelectionRule *implicit_rr = nullptr;
1067 
1068  if (D->getKind() == clang::Decl::CXXMethod){
1069  // we first check the explicit rules for the method (in case of constructors and destructors we check the parent)
1070  std::string pat_value;
1071  for(; it != it_end; ++it) {
1073  = it->Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, prototype, false);
1074 
1075  if (match == BaseSelectionRule::kName) {
1076  // here I should implement my implicit/explicit thing
1077  // I have included two levels of implicitness - "A::Get_*" is stronger than "*"
1078  explicit_r = &(*it);
1079  if (it->GetSelected() == BaseSelectionRule::kYes) ++expl_Yes;
1080  else {
1081 
1082 #ifdef SELECTION_DEBUG
1083  std::cout<<"\tExplicit rule BaseSelectionRule::kNo found"<<std::endl;
1084 #endif
1085 
1086  return nullptr; // == explicit BaseSelectionRule::kNo
1087 
1088  }
1089  } else if (match == BaseSelectionRule::kPattern) {
1090 
1091  if (it->GetAttributeValue("pattern", pat_value)) {
1092  if (pat_value == "*") continue; // we discard the global selection rules
1093 
1094  std::string par_name, par_qual_name;
1095  GetParentName(D, par_name, par_qual_name);
1096  std::string par_pat = par_qual_name + "::*";
1097 
1098  if (pat_value == par_pat) {
1099  implicit_rr = &(*it);
1100  if (it->GetSelected() == BaseSelectionRule::kYes) {
1101 
1102 #ifdef SELECTION_DEBUG
1103  std::cout<<"Implicit_rr rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1104 #endif
1105 
1106  ++impl_rr_Yes;
1107  }
1108  else {
1109 
1110 #ifdef SELECTION_DEBUG
1111  std::cout<<"Implicit_rr rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1112 #endif
1113 
1114  ++impl_rr_No;
1115  }
1116  }
1117  else {
1118  implicit_r = &(*it);
1119  if (it->GetSelected() == BaseSelectionRule::kYes) {
1120 
1121 #ifdef SELECTION_DEBUG
1122  std::cout<<"Implicit_r rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1123 #endif
1124 
1125  ++impl_r_Yes;
1126  }
1127  else {
1128 
1129 #ifdef SELECTION_DEBUG
1130  std::cout<<"Implicit_r rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1131 #endif
1132 
1133  ++impl_r_No;
1134  }
1135  }
1136  }
1137  }
1138  }
1139  }
1140  if (explicit_r /*&& expl_Yes > 0*/){
1141 
1142 #ifdef SELECTION_DEBUG
1143  std::cout<<"\tExplicit rule BaseSelectionRule::BaseSelectionRule::kYes found"<<std::endl;
1144 #endif
1145 
1146  return explicit_r; // if we have excplicit BaseSelectionRule::kYes
1147  }
1148  else if (implicit_rr) {
1149  if (impl_rr_No > 0) {
1150 
1151 #ifdef SELECTION_DEBUG
1152  std::cout<<"\tImplicit_rr rule BaseSelectionRule::kNo found"<<std::endl;
1153 #endif
1154 
1155  return nullptr;
1156  }
1157  else {
1158 
1159 #ifdef SELECTION_DEBUG
1160  std::cout<<"\tImplicit_rr rule BaseSelectionRule::kYes found"<<std::endl;
1161 #endif
1162 
1163  return implicit_rr;
1164  }
1165  }
1166  else if (implicit_r) {
1167  if (impl_r_No > 0) {
1168 
1169 #ifdef SELECTION_DEBUG
1170  std::cout<<"\tImplicit_r rule BaseSelectionRule::kNo found"<<std::endl;
1171 #endif
1172 
1173  return nullptr;
1174  }
1175  else {
1176 
1177 #ifdef SELECTION_DEBUG
1178  std::cout<<"\tImplicit_r rule BaseSelectionRule::kYes found"<<std::endl;
1179 #endif
1180 
1181  return implicit_r;
1182  }
1183  }
1184  else {
1185 
1186 #ifdef SELECTION_DEBUG
1187  std::cout<<"\tChecking parent class rules"<<std::endl;
1188 #endif
1189  // check parent
1190 
1191 
1192  std::string parent_name, parent_qual_name;
1193  if (!GetParentName(D, parent_name, parent_qual_name)) return nullptr;
1194 
1195  const BaseSelectionRule *selector = nullptr;
1196  int fImplNo = 0;
1197  const BaseSelectionRule *explicit_selector = nullptr;
1198 
1199  // the same as with isClass selected
1200  // I wanted to use GetParentDecl and then to pass is to isClassSelected because I didn't wanted to repeat
1201  // code but than GetParentDecl crashes (or returns non-sence Decl) for the built-in structs (__va_*)
1202  std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
1203  std::string name_value;
1204  std::string pattern_value;
1205  for(; it != fClassSelectionRules.end(); ++it) {
1207  = it->Match(llvm::dyn_cast<clang::NamedDecl>(D), parent_qual_name, "", true); // == BaseSelectionRule::kYes
1208 
1209  if (match != BaseSelectionRule::kNoMatch) {
1210  if (it->GetSelected() == BaseSelectionRule::kYes) {
1211  selector = &(*it);
1212 
1213  if (match == BaseSelectionRule::kName) {
1214  explicit_selector = &(*it);
1215  } else if (match == BaseSelectionRule::kPattern) {
1216  if (it->GetAttributeValue("pattern", pattern_value)) {
1217  // NOTE: weird ...
1218  if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it);
1219  }
1220  }
1221  }
1222  else { // == BaseSelectionRule::kNo
1223 
1224  if (it->GetAttributeValue("pattern", pattern_value)) {
1225  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
1226  else
1227  return nullptr;
1228  }
1229  else
1230  return nullptr;
1231  }
1232  }
1233  }
1234 
1235 #ifdef SELECTION_DEBUG
1236  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
1237 #endif
1238 
1239  if (explicit_selector) {
1240 
1241 #ifdef SELECTION_DEBUG
1242  std::cout<<"\tReturning Yes"<<std::endl;
1243 #endif
1244 
1245  return explicit_selector;
1246  }
1247  else if (fImplNo > 0) {
1248 #ifdef SELECTION_DEBUG
1249  std::cout<<"\tReturning No"<<std::endl;
1250 #endif
1251 
1252  return nullptr;
1253  }
1254  else {
1255 
1256 #ifdef SELECTION_DEBUG
1257  std::cout<<"\tReturning Yes"<<std::endl;
1258 #endif
1259 
1260  return selector;
1261  }
1262  }
1263 
1264  return nullptr;
1265 
1266 }
1267 
1268 const BaseSelectionRule *SelectionRules::IsMemberSelected(const clang::Decl* D, const std::string& str_name) const
1269 {
1270  std::string parent_name;
1271  std::string parent_qual_name;
1272 
1273  if (IsParentClass(D))
1274  {
1275  if (!GetParentName(D, parent_name, parent_qual_name)) return nullptr;
1276 
1277  const BaseSelectionRule *selector = nullptr;
1278  Int_t fImplNo = 0;
1279  const BaseSelectionRule *explicit_selector = nullptr;
1280  int fFileNo = 0;
1281 
1282  //DEBUG std::cout<<"\n\tParent is class";
1283  std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
1284  std::string name_value;
1285  std::string pattern_value;
1286  for(; it != fClassSelectionRules.end(); ++it) {
1288  = it->Match(llvm::dyn_cast<clang::NamedDecl>(D), parent_qual_name, "", false);
1289 
1290  if (match != BaseSelectionRule::kNoMatch) {
1291  if (it->GetSelected() == BaseSelectionRule::kYes) {
1292  selector = &(*it);
1293  if (IsLinkdefFile()) {
1294  if (match == BaseSelectionRule::kName) {
1295  explicit_selector = &(*it);
1296  } else if (match == BaseSelectionRule::kPattern) {
1297  if (it->GetAttributeValue("pattern", pattern_value)) {
1298  // NOTE: Weird ... This is a strange definition of explicit.
1299  if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it);
1300  }
1301  }
1302  }
1303  } else if (it->GetSelected() == BaseSelectionRule::kNo) {
1304  if (!IsLinkdefFile()) {
1305  if (match == BaseSelectionRule::kFile) ++fFileNo;
1306  else {
1307 
1308 #ifdef SELECTION_DEBUG
1309  std::cout<<"\tNo returned"<<std::endl;
1310 #endif
1311 
1312  return nullptr; // in genreflex we can't have that situation
1313  }
1314  }
1315  else {
1316  if (match == BaseSelectionRule::kPattern && it->GetAttributeValue("pattern", pattern_value)) {
1317  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
1318  else
1319  return nullptr;
1320  }
1321  else
1322  return nullptr;
1323  }
1324  }
1325  else if (it->GetSelected() == BaseSelectionRule::kDontCare) // - we check the method and field selection rules for the class
1326  {
1327  if (!it->HasMethodSelectionRules() && !it->HasFieldSelectionRules()) {
1328 
1329 #ifdef SELECTION_DEBUG
1330  std::cout<<"\tNo fields and methods"<<std::endl;
1331 #endif
1332 
1333  return nullptr; // == BaseSelectionRule::kNo
1334  }
1335  else {
1336  clang::Decl::Kind kind = D->getKind();
1337  if (kind == clang::Decl::Field || kind == clang::Decl::CXXMethod || kind == clang::Decl::CXXConstructor || kind == clang::Decl::CXXDestructor){
1338  std::list<VariableSelectionRule> members;
1339  std::list<VariableSelectionRule>::iterator mem_it;
1340  std::list<VariableSelectionRule>::iterator mem_it_end;
1341  std::string prototype;
1342 
1343  if (kind == clang::Decl::Field) {
1344  members = it->GetFieldSelectionRules();
1345  }
1346  else {
1347  if (const clang::FunctionDecl* F = llvm::dyn_cast<clang::FunctionDecl> (D)){
1348  GetFunctionPrototype(F, prototype);
1349  prototype = str_name + prototype;
1350  }
1351  else{
1352  ROOT::TMetaUtils::Warning("","Warning: could not cast Decl to FunctionDecl\n");
1353  }
1354  members = it->GetMethodSelectionRules();
1355  }
1356  mem_it = members.begin();
1357  mem_it_end = members.end();
1358  for (; mem_it != mem_it_end; ++mem_it) {
1359  if (BaseSelectionRule::kName == mem_it->Match(llvm::dyn_cast<clang::NamedDecl>(D), str_name, prototype, false)) {
1360  if (mem_it->GetSelected() == BaseSelectionRule::kNo) return nullptr;
1361  }
1362  }
1363  }
1364  }
1365  }
1366  }
1367  }
1368 
1369  if (IsLinkdefFile()) {
1370 
1371 #ifdef SELECTION_DEBUG
1372  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
1373 #endif
1374 
1375  if (explicit_selector) {
1376 #ifdef SELECTION_DEBUG
1377  std::cout<<"\tReturning Yes"<<std::endl;
1378 #endif
1379 
1380  return explicit_selector;
1381  }
1382  else if (fImplNo > 0) {
1383 
1384 #ifdef SELECTION_DEBUG
1385  std::cout<<"\tReturning No"<<std::endl;
1386 #endif
1387 
1388  return nullptr;
1389  }
1390  else {
1391 
1392 #ifdef SELECTION_DEBUG
1393  std::cout<<"\tReturning Yes"<<std::endl;
1394 #endif
1395 
1396  return selector;
1397  }
1398  }
1399  else {
1400 
1401  return selector;
1402  }
1403  }
1404  else {
1405  return nullptr;
1406  }
1407 }
1408 
1410  for(auto&& rule : fClassSelectionRules){
1411  if (BaseSelectionRule::kNo!=rule.GetSelected() && !rule.GetMatchFound() /* && !GetHasFileNameRule() */ ) {
1412  std::string name;
1413  if (rule.GetAttributeValue("pattern", name)) {
1414  // keep it
1415  } else if (rule.GetAttributeValue("name", name)) {
1416  // keept it
1417  } else {
1418  name.clear();
1419  }
1420  std::string file_name_value;
1421  if (!rule.GetAttributeValue("file_name", file_name_value)) file_name_value.clear();
1422 
1423  if (!file_name_value.empty()) {
1424  // don't complain about defined_in rules
1425  continue;
1426  }
1427 
1428  const char* attrName = "class";
1429  const char* attrVal = nullptr;
1430  if (!name.empty()) attrVal = name.c_str();
1431 
1432  ROOT::TMetaUtils::Warning(nullptr,"Unused %s rule: %s\n", attrName, attrVal);
1433  }
1434  }
1435 
1436  for(auto&& rule : fVariableSelectionRules){
1437  if (!rule.GetMatchFound() && !GetHasFileNameRule()) {
1438  std::string name;
1439  if (rule.GetAttributeValue("pattern", name)) {
1440  // keep it
1441  } else if (rule.GetAttributeValue("name", name)) {
1442  // keept it
1443  } else {
1444  name.clear();
1445  }
1446  ROOT::TMetaUtils::Warning("","Unused variable rule: %s\n",name.c_str());
1447  if (name.empty()) {
1448  rule.PrintAttributes(std::cout,3);
1449  }
1450  }
1451  }
1452 
1453 #if defined(R__MUST_REVISIT)
1454 #if R__MUST_REVISIT(6,2)
1455 ROOT::TMetaUtils::Warning("SelectionRules::AreAllSelectionRulesUsed",
1456 "Warnings concerning non matching selection rules are suppressed. An action is to be taken.\n");
1457 #endif
1458 #endif
1459 // for(const auto& selRule: fFunctionSelectionRules) {
1460 // if (!selRule.GetMatchFound() && !GetHasFileNameRule()) {
1461 // // Here the slow methods can be used
1462 // std::string name;
1463 // if (selRule.GetAttributeValue("proto_pattern", name)) {
1464 // // keep it
1465 // } else if (selRule.GetAttributeValue("proto_name", name)) {
1466 // // keep it
1467 // } else if (selRule.GetAttributeValue("pattern", name)) {
1468 // // keep it
1469 // } else if (selRule.GetAttributeValue("name", name)) {
1470 // // keept it
1471 // } else {
1472 // name.clear();
1473 // }
1474 // // Make it soft, no error - just warnings
1475 // std::cout<<"Warning - unused function rule: "<<name<<std::endl;
1476 // // if (IsSelectionXMLFile()){
1477 // // std::cout<<"Warning - unused function rule: "<<name<<std::endl;
1478 // // }
1479 // // else {
1480 // // std::cout<<"Error - unused function rule: "<<name<<std::endl;
1481 // // }
1482 // if (name.length() == 0) {
1483 // selRule.PrintAttributes(std::cout,3);
1484 // }
1485 // }
1486 //
1487 // }
1488 
1489 
1490 #if Enums_rules_becomes_useful_for_rootcling
1491  for(auto&& rule : fEnumSelectionRules){
1492  if (!rule.GetMatchFound() && !GetHasFileNameRule()) {
1493  std::string name;
1494  if (rule.GetAttributeValue("pattern", name)) {
1495  // keep it
1496  } else if (rule.GetAttributeValue("name", name)) {
1497  // keept it
1498  } else {
1499  name.clear();
1500  }
1501 
1502  ROOT::TMetaUtils::Warning("","Unused enum rule: %s\n",name.c_str());
1503 
1504  if (name.empty()){
1505  rule.PrintAttributes(std::cout,3);
1506  }
1507  }
1508  }
1509 #endif
1510  return true;
1511 }
1512 
1513 bool SelectionRules::SearchNames(cling::Interpreter &interp)
1514 {
1515  // std::cout<<"Searching Names In Selection Rules:"<<std::endl;
1516  for(std::list<ClassSelectionRule>::iterator it = fClassSelectionRules.begin(),
1517  end = fClassSelectionRules.end();
1518  it != end;
1519  ++it) {
1520  if (it->HasAttributeWithName("name")) {
1521  std::string name_value;
1522  it->GetAttributeValue("name", name_value);
1523  // In Class selection rules, we should be interested in scopes.
1524  const clang::Type *typeptr = nullptr;
1525  const clang::CXXRecordDecl *target
1526  = ROOT::TMetaUtils::ScopeSearch(name_value.c_str(), interp,
1527  true /*diag*/, &typeptr);
1528  if (target) {
1529  it->SetCXXRecordDecl(target,typeptr);
1530  }
1531  }
1532  }
1533  return true;
1534 }
1535 
1536 
1538 {
1539  // Fill the cache of every selection rule
1540  for (auto& rule : fClassSelectionRules) rule.FillCache();
1541  for (auto& rule : fFunctionSelectionRules) rule.FillCache();
1542  for (auto& rule : fVariableSelectionRules) rule.FillCache();
1543  for (auto& rule : fEnumSelectionRules) rule.FillCache();
1544 }
1545 
1546 
SelectionRules::GetDeclName
bool GetDeclName(const clang::Decl *D, std::string &name, std::string &qual_name) const
Definition: SelectionRules.cxx:425
BaseSelectionRule::EMatchType
EMatchType
Definition: BaseSelectionRule.h:48
SelectionRules::IsDeclSelected
const ClassSelectionRule * IsDeclSelected(const clang::RecordDecl *D, bool includeTypedefRule) const
Definition: SelectionRules.cxx:273
ROOT::TMetaUtils::ReplaceAll
void ReplaceAll(std::string &str, const std::string &from, const std::string &to, bool recurse=false)
Definition: TClingUtils.cxx:5038
ROOT::TMetaUtils::Warning
void Warning(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:819
F
#define F(x, y, z)
ROOT::Math::Cephes::P
static double P[]
Definition: SpecFuncCephes.cxx:285
SelectionRules::GetParentName
bool GetParentName(const clang::Decl *D, std::string &parent_name, std::string &parent_qual_name) const
Definition: SelectionRules.cxx:523
SelectionRules::AddEnumSelectionRule
void AddEnumSelectionRule(const EnumSelectionRule &enumSel)
Definition: SelectionRules.cxx:69
BaseSelectionRule::GetSelected
ESelect GetSelected() const
Definition: BaseSelectionRule.cxx:103
R__ScopeSearch
const clang::CXXRecordDecl * R__ScopeSearch(const char *name, const clang::Type **resultType=nullptr)
SelectionRules::IsNamespaceSelected
const ClassSelectionRule * IsNamespaceSelected(const clang::Decl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:571
SelectionRules::fNormCtxt
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
Definition: SelectionRules.h:243
SelectionRules.h
BaseSelectionRule::kNo
@ kNo
Definition: BaseSelectionRule.h:45
SelectionRules::IsMemberSelected
const BaseSelectionRule * IsMemberSelected(const clang::Decl *D, const std::string &str_name) const
Definition: SelectionRules.cxx:1268
ROOT::TMetaUtils::Error
void Error(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:789
N
#define N
ROOT::TMetaUtils::propNames::nArgsToKeep
static const std::string nArgsToKeep("nArgsToKeep")
SelectionRules::FillCache
void FillCache()
Definition: SelectionRules.cxx:1537
SelectionRules::IsClassSelected
const ClassSelectionRule * IsClassSelected(const clang::Decl *D, const std::string &qual_name, bool includeTypedefRule) const
Definition: SelectionRules.cxx:670
Function
Double_t(* Function)(Double_t)
Definition: Functor.C:4
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
SelectionRules::IsSelectionXMLFile
bool IsSelectionXMLFile() const
Definition: SelectionRules.h:213
ROOT::TMetaUtils::GetNormalizedName
void GetNormalizedName(std::string &norm_name, const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type name normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t,...
Definition: TClingUtils.cxx:4048
SelectionRules::IsLinkdefFunSelected
const BaseSelectionRule * IsLinkdefFunSelected(const clang::FunctionDecl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:915
SelectionRules::AreAllSelectionRulesUsed
bool AreAllSelectionRulesUsed() const
Definition: SelectionRules.cxx:1409
ROOT::TMetaUtils::TNormalizedCtxt::AddTemplAndNargsToKeep
void AddTemplAndNargsToKeep(const clang::ClassTemplateDecl *templ, unsigned int i)
Definition: TClingUtils.cxx:351
CheckDuplicatesImp
static int CheckDuplicatesImp(RULESCOLLECTION &rules)
Definition: SelectionRules.cxx:196
ROOT::TMetaUtils::Info
void Info(const char *location, const char *va_(fmt),...)
Definition: TClingUtils.h:809
BaseSelectionRule::kFile
@ kFile
Definition: BaseSelectionRule.h:51
SelectionRules::IsFunSelected
const BaseSelectionRule * IsFunSelected(const clang::FunctionDecl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:807
BaseSelectionRule::GetAttributePattern
const std::string & GetAttributePattern() const
Definition: BaseSelectionRule.h:116
SelectionRules::fEnumSelectionRules
std::list< EnumSelectionRule > fEnumSelectionRules
List of the enums selection rules.
Definition: SelectionRules.h:236
SelectionRules::fVariableSelectionRules
std::list< VariableSelectionRule > fVariableSelectionRules
List of the global variables selection rules.
Definition: SelectionRules.h:235
SelectionRules::IsLinkdefFile
bool IsLinkdefFile() const
Definition: SelectionRules.h:216
BaseSelectionRule::HasInterpreter
bool HasInterpreter() const
Definition: BaseSelectionRule.h:138
VariableSelectionRule
Definition: VariableSelectionRule.h:26
BaseSelectionRule::GetAttributes
const AttributesMap_t & GetAttributes() const
Definition: BaseSelectionRule.cxx:150
HasDuplicate
static bool HasDuplicate(RULE *rule, std::unordered_map< std::string, RULE * > &storedRules, const std::string &attrName)
Definition: SelectionRules.cxx:174
SelectionRules::PrintSelectionRules
void PrintSelectionRules() const
Definition: SelectionRules.cxx:79
BaseSelectionRule::kPattern
@ kPattern
Definition: BaseSelectionRule.h:50
SelectionRules::fFunctionSelectionRules
std::list< FunctionSelectionRule > fFunctionSelectionRules
List of the global functions selection rules.
Definition: SelectionRules.h:234
ClassSelectionRule
Definition: ClassSelectionRule.h:34
SelectionRulesUtils::areEqual
bool areEqual(const RULE *r1, const RULE *r2, bool moduloNameOrPattern=false)
Definition: SelectionRules.h:58
BaseSelectionRule::kYes
@ kYes
Definition: BaseSelectionRule.h:44
ROOT::VecOps::Var
double Var(const RVec< T > &v)
Get the variance of the elements of an RVec.
Definition: RVec.hxx:867
SelectionRules::GetFunctionPrototype
bool GetFunctionPrototype(const clang::FunctionDecl *F, std::string &prototype) const
Definition: SelectionRules.cxx:452
SelectionRules::GetDeclQualName
void GetDeclQualName(const clang::Decl *D, std::string &qual_name) const
Definition: SelectionRules.cxx:444
SelectionRules::IsLinkdefEnumSelected
const BaseSelectionRule * IsLinkdefEnumSelected(const clang::EnumDecl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:975
SelectionRules::SearchNames
bool SearchNames(cling::Interpreter &interp)
Definition: SelectionRules.cxx:1513
SelectionRules::AddFunctionSelectionRule
void AddFunctionSelectionRule(const FunctionSelectionRule &funcSel)
Definition: SelectionRules.cxx:49
RtypesCore.h
SelectionRules::IsLinkdefMethodSelected
const BaseSelectionRule * IsLinkdefMethodSelected(const clang::Decl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:1048
SelectionRules::fInterp
cling::Interpreter & fInterp
Definition: SelectionRules.h:244
SelectionRules::IsParentClass
bool IsParentClass(const clang::Decl *D) const
Definition: SelectionRules.cxx:499
SelectionRules::AddClassSelectionRule
void AddClassSelectionRule(const ClassSelectionRule &classSel)
Definition: SelectionRules.cxx:39
BaseSelectionRule::kDontCare
@ kDontCare
Definition: BaseSelectionRule.h:46
SelectionRules::Optimize
void Optimize()
Definition: SelectionRules.cxx:252
ROOT::TMetaUtils::ScopeSearch
const clang::CXXRecordDecl * ScopeSearch(const char *name, const cling::Interpreter &gInterp, bool diagnose, const clang::Type **resultType)
Return the scope corresponding to 'name' or std::'name'.
Definition: TClingUtils.cxx:785
BaseSelectionRule::GetAttributeName
const std::string & GetAttributeName() const
Definition: BaseSelectionRule.h:110
SelectionRules::fRulesCounter
long int fRulesCounter
Definition: SelectionRules.h:241
name
char name[80]
Definition: TGX11.cxx:110
SelectionRules::GetHasFileNameRule
bool GetHasFileNameRule() const
Definition: SelectionRules.h:153
SelectionRules::IsVarSelected
const BaseSelectionRule * IsVarSelected(const clang::VarDecl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:783
ROOT::Math::Chebyshev::T
double T(double x)
Definition: ChebyshevPol.h:34
I
#define I(x, y, z)
type
int type
Definition: TGX11.cxx:121
SelectionRules::CheckDuplicates
int CheckDuplicates()
Definition: SelectionRules.cxx:206
BaseSelectionRule::kNoMatch
@ kNoMatch
Definition: BaseSelectionRule.h:52
BaseSelectionRule::kName
@ kName
Definition: BaseSelectionRule.h:49
SelectionRules::IsLinkdefVarSelected
const BaseSelectionRule * IsLinkdefVarSelected(const clang::VarDecl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:857
SelectionRules::AddVariableSelectionRule
void AddVariableSelectionRule(const VariableSelectionRule &varSel)
Definition: SelectionRules.cxx:59
TMath::E
constexpr Double_t E()
Base of natural log:
Definition: TMath.h:96
BaseSelectionRule
Definition: BaseSelectionRule.h:39
Implies
static bool Implies(const ClassSelectionRule &patternRule, const ClassSelectionRule &nameRule)
Definition: SelectionRules.cxx:220
BaseSelectionRule::Match
EMatchType Match(const clang::NamedDecl *decl, const std::string &name, const std::string &prototype, bool isLinkdef) const
Definition: BaseSelectionRule.cxx:185
SelectionRules::IsEnumSelected
const BaseSelectionRule * IsEnumSelected(const clang::EnumDecl *D, const std::string &qual_name) const
Definition: SelectionRules.cxx:836
SelectionRules::ClearSelectionRules
void ClearSelectionRules()
Definition: SelectionRules.cxx:165
ROOT::TMetaUtils::propNames::pattern
static const std::string pattern("pattern")
int
BaseSelectionRule::GetIndex
long GetIndex() const
Definition: BaseSelectionRule.h:98
SelectionRules::fClassSelectionRules
std::list< ClassSelectionRule > fClassSelectionRules
List of the class selection rules.
Definition: SelectionRules.h:233