Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 = 0) ;
38 
39 void SelectionRules::AddClassSelectionRule(const ClassSelectionRule& classSel)
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 
49 void SelectionRules::AddFunctionSelectionRule(const FunctionSelectionRule& funcSel)
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 
59 void SelectionRules::AddVariableSelectionRule(const VariableSelectionRule& varSel)
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 
69 void SelectionRules::AddEnumSelectionRule(const EnumSelectionRule& enumSel)
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 
79 void SelectionRules::PrintSelectionRules() const
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 
165 void SelectionRules::ClearSelectionRules()
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 
206 int SelectionRules::CheckDuplicates(){
207 
208  int nDuplicates = 0;
209  nDuplicates += CheckDuplicatesImp(fClassSelectionRules);
210  nDuplicates += CheckDuplicatesImp(fFunctionSelectionRules);
211  nDuplicates += CheckDuplicatesImp(fVariableSelectionRules);
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 
252 void SelectionRules::Optimize(){
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) const
274 {
275  std::string qual_name;
276  GetDeclQualName(D,qual_name);
277  return IsClassSelected(D, qual_name);
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);
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 0;
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 0;
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 0;
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
392  case clang::Decl::Function:
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 0;
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  const clang::NamedDecl* N = static_cast<const clang::NamedDecl*> (D);
446  llvm::raw_string_ostream stream(qual_name);
447  N->getNameForDiagnostic(stream,N->getASTContext().getPrintingPolicy(),true);
448  }
449 
450 bool SelectionRules::GetFunctionPrototype(const clang::FunctionDecl* F, std::string& prototype) const {
451 
452  if (!F) {
453  return false;
454  }
455 
456  const std::vector<std::string> quals={"*","&"};
457 
458  prototype = "";
459  // iterate through all the function parameters
460  std::string type;
461  for (auto I = F->param_begin(), E = F->param_end(); I != E; ++I) {
462 
463  clang::ParmVarDecl* P = *I;
464 
465  if (prototype != "")
466  prototype += ",";
467 
468  ROOT::TMetaUtils::GetNormalizedName(type,P->getType(),fInterp,fNormCtxt);
469 
470  // We need to get rid of the "class " string if present
471  ROOT::TMetaUtils::ReplaceAll(type,"class ", "");
472  // We need to get rid of the "restrict " string if present
473  ROOT::TMetaUtils::ReplaceAll(type,"restrict", "");
474 
475  // pointers are returned in the form "int *" and I need them in the form "int*"
476  // same for &
477  for (auto& qual : quals){
478  auto pos = type.find(" "+qual);
479  if (pos != std::string::npos)
480  type.replace( pos, 2, qual );
481  }
482 // for (auto& qual : quals){
483 // if (type.at(type.length()-1) == qual && type.at(type.length()-2) == ' ') {
484 // type.at(type.length()-2) = qual;
485 // type.erase(type.length()-1);
486 // }
487 // }
488  prototype += type;
489  }
490  prototype = "(" + prototype + ")";
491  return true;
492 
493 }
494 
495 
496 bool SelectionRules::IsParentClass(const clang::Decl* D) const
497 {
498  //TagDecl has methods to understand of what kind is the Decl - class, struct or union
499  if (const clang::TagDecl* T
500  = llvm::dyn_cast<clang::TagDecl>(D->getDeclContext()))
501  return T->isClass() || T->isStruct();
502  return false;
503 }
504 
505 
506 bool SelectionRules::IsParentClass(const clang::Decl* D, std::string& parent_name, std::string& parent_qual_name) const
507 {
508  if (const clang::TagDecl* parent
509  = llvm::dyn_cast<clang::TagDecl>(D->getDeclContext())) {
510  if (parent->isClass()|| parent->isStruct()) {
511  GetDeclName(parent, parent_name, parent_qual_name);
512  return true;
513  }
514  }
515  return false;
516 }
517 
518 bool SelectionRules::GetParentName(const clang::Decl* D, std::string& parent_name, std::string& parent_qual_name) const
519 {
520  if (const clang::RecordDecl* parent
521  = llvm::dyn_cast<clang::RecordDecl>(D->getDeclContext())) {
522  GetDeclName(parent, parent_name, parent_qual_name);
523  return true;
524  }
525  return false;
526 }
527 
528 /* This is the method that crashes
529  bool SelectionRules::GetParent(clang::Decl* D, clang::Decl* parent)
530  {
531  clang::DeclContext *ctx = D->GetDeclContext();
532 
533  if (ctx->isRecord()){
534  //DEBUG std::cout<<"\n\tDeclContext is Record";
535  parent = llvm::dyn_cast<clang::Decl> (ctx);
536  if (!parent) {
537  return false;
538  }
539  else {
540  return true;
541  }
542  }
543  else return false;
544  }
545  */
546 
547 
548 // isClassSelected checks if a class is selected or not. Thre is a difference between the
549 // behaviour of rootcint and genreflex especially with regard to class pattern processing.
550 // In genreflex if we have <class pattern = "*" /> this will select all the classes
551 // (and structs) found in the header file. In rootcint if we have something similar, i.e.
552 // #pragma link C++ class *, we will select only the outer classes - for the nested
553 // classes we have to specifie #pragma link C++ class *::*. And yet this is only valid
554 // for one level of nesting - if you need it for many levels of nesting, you will
555 // probably have to implement it yourself.
556 // Here the idea is the following - we traverse the list of class selection rules.
557 // For every class we check do we have a class selection rule. We use here the
558 // method isSelected() (defined in BaseSelectionRule.cxx). This method returns true
559 // only if we have class selection rule which says "Select". Otherwise it returns
560 // false - in which case we have to check wether we found a class selection rule
561 // which says "Veto" (noName = false and don't Care = false; OR noName = false and
562 // don't Care = true and we don't have neither method nor field selection rules -
563 // which is for the selection.xml file case). If noName is true than we just continue -
564 // this means that the current class selection rule isn't applicable for this class.
565 
566 const ClassSelectionRule *SelectionRules::IsNamespaceSelected(const clang::Decl* D, const std::string& qual_name) const
567 {
568  const clang::NamespaceDecl* N = llvm::dyn_cast<clang::NamespaceDecl> (D); //TagDecl has methods to understand of what kind is the Decl
569  if (N==0) {
570  std::cout<<"\n\tCouldn't cast Decl to NamespaceDecl";
571  return 0;
572  }
573 
574  const ClassSelectionRule *selector = 0;
575  int fImplNo = 0;
576  const ClassSelectionRule *explicit_selector = 0;
577  const ClassSelectionRule *specific_pattern_selector = 0;
578  int fFileNo = 0;
579 
580  // NOTE: should we separate namespaces from classes in the rules?
581  std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
582  // iterate through all class selection rles
583  std::string name_value;
584  std::string pattern_value;
585  BaseSelectionRule::EMatchType match;
586  for(; it != fClassSelectionRules.end(); ++it) {
587 
588  match = it->Match(N,qual_name,"",IsLinkdefFile());
589 
590  if (match != BaseSelectionRule::kNoMatch) {
591  // If we have a match.
592  if (it->GetSelected() == BaseSelectionRule::kYes) {
593  selector = &(*it);
594  if (IsLinkdefFile()){
595  // rootcint prefers explicit rules over pattern rules
596  if (match == BaseSelectionRule::kName) {
597  explicit_selector = &(*it);
598  } else if (match == BaseSelectionRule::kPattern) {
599  // NOTE: weird ...
600  if (it->GetAttributeValue("pattern", pattern_value) &&
601  pattern_value != "*" && pattern_value != "*::*") specific_pattern_selector = &(*it);
602  }
603  }
604  } else if (it->GetSelected() == BaseSelectionRule::kNo) {
605  if (!IsLinkdefFile()) {
606  // in genreflex - we could explicitly select classes from other source files
607  if (match == BaseSelectionRule::kFile) ++fFileNo; // if we have veto because of class defined in other source file -> implicit No
608  else {
609 
610 #ifdef SELECTION_DEBUG
611  std::cout<<"\tNo returned"<<std::endl;
612 #endif
613 
614  return 0; // explicit No returned
615  }
616  }
617  if (match == BaseSelectionRule::kPattern) {
618  //this is for the Linkdef selection
619  if (it->GetAttributeValue("pattern", pattern_value) &&
620  (pattern_value == "*" || pattern_value == "*::*")) ++fImplNo;
621  else
622  return 0;
623  }
624  else
625  return 0;
626  }
627  else if (it->GetSelected() == BaseSelectionRule::kDontCare && !(it->HasMethodSelectionRules()) && !(it->HasFieldSelectionRules())) {
628 
629 #ifdef SELECTION_DEBUG
630  std::cout<<"Empty dontC returned = No"<<std::endl;
631 #endif
632 
633  return 0;
634  }
635  }
636  }
637  if (IsLinkdefFile()) {
638  // for rootcint explicit (name) Yes is stronger than implicit (pattern) No which is stronger than implicit (pattern) Yes
639 
640 #ifdef SELECTION_DEBUG
641  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
642 #endif
643 
644  if (explicit_selector) return explicit_selector;
645  else if (specific_pattern_selector) return specific_pattern_selector;
646  else if (fImplNo > 0) return 0;
647  else return selector;
648  }
649  else {
650  // for genreflex explicit Yes is stronger than implicit file No
651 
652 #ifdef SELECTION_DEBUG
653  std::cout<<"\n\tfYes = "<<fYes<<", fFileNo = "<<fFileNo<<std::endl;
654 #endif
655 
656  if (selector)
657  return selector;
658  else
659  return 0;
660  }
661 
662 }
663 
664 
665 const ClassSelectionRule *SelectionRules::IsClassSelected(const clang::Decl* D, const std::string& qual_name) const
666 {
667  const clang::TagDecl* tagDecl = llvm::dyn_cast<clang::TagDecl> (D); //TagDecl has methods to understand of what kind is the Decl
668  const clang::TypedefNameDecl* typeDefNameDecl = llvm::dyn_cast<clang::TypedefNameDecl> (D);
669 
670  if (!tagDecl && !typeDefNameDecl) { // Ill posed
671  ROOT::TMetaUtils::Error("SelectionRules::IsClassSelected",
672  "Cannot cast Decl to TagDecl and Decl is not a typedef.\n");
673  return 0;
674  }
675 
676  if (!tagDecl && typeDefNameDecl){ // Let's try to fetch the underlying RecordDecl
677  clang::RecordDecl* recordDecl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(typeDefNameDecl->getUnderlyingType());
678  if (!recordDecl){
679  ROOT::TMetaUtils::Error("SelectionRules::IsClassSelected",
680  "Cannot get RecordDecl behind TypedefDecl.\n");
681  return 0;
682  }
683  tagDecl = recordDecl;
684  }
685 
686  // At this point tagDecl must be well defined
687  const bool isLinkDefFile = IsLinkdefFile();
688  if (!( isLinkDefFile || tagDecl->isClass() || tagDecl->isStruct() ))
689  return 0; // Union for Genreflex
690 
691  const ClassSelectionRule *selector = 0;
692  int fImplNo = 0;
693  const ClassSelectionRule *explicit_selector = 0;
694  const ClassSelectionRule *specific_pattern_selector = 0;
695  int fFileNo = 0;
696 
697  // iterate through all class selection rles
698  bool earlyReturn=false;
699  const ClassSelectionRule* retval = nullptr;
700  const clang::NamedDecl* nDecl(llvm::dyn_cast<clang::NamedDecl>(D));
701  for(auto& rule : fClassSelectionRules) {
702  BaseSelectionRule::EMatchType match = rule.Match(nDecl, qual_name, "", isLinkDefFile);
703  if (match != BaseSelectionRule::kNoMatch) {
704  // Check if the template must have its arguments manipulated
705  if (const clang::ClassTemplateSpecializationDecl* ctsd =
706  llvm::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(D))
707  if(const clang::ClassTemplateDecl* ctd = ctsd->getSpecializedTemplate()){
708  const std::string& nArgsToKeep = rule.GetAttributeNArgsToKeep();
709  if (!nArgsToKeep.empty()){
710  fNormCtxt.AddTemplAndNargsToKeep(ctd->getCanonicalDecl(),
711  std::atoi(nArgsToKeep.c_str()));
712  }
713  }
714 
715  if (earlyReturn) continue;
716 
717  // If we have a match.
718  selector = &(rule);
719  if (rule.GetSelected() == BaseSelectionRule::kYes) {
720 
721  if (isLinkDefFile){
722  // rootcint prefers explicit rules over pattern rules
723  if (match == BaseSelectionRule::kName) {
724  explicit_selector = &(rule);
725  } else if (match == BaseSelectionRule::kPattern) {
726  // NOTE: weird ...
727  const std::string& pattern_value=rule.GetAttributePattern();
728  if (!pattern_value.empty() &&
729  pattern_value != "*" &&
730  pattern_value != "*::*") specific_pattern_selector = &(rule);
731  }
732  }
733  } else if (rule.GetSelected() == BaseSelectionRule::kNo) {
734 
735  if (!isLinkDefFile) {
736  // in genreflex - we could explicitly select classes from other source files
737  if (match == BaseSelectionRule::kFile) ++fFileNo; // if we have veto because of class defined in other source file -> implicit No
738  else {
739  retval = selector;
740  earlyReturn=true; // explicit No returned
741  }
742  }
743  if (match == BaseSelectionRule::kPattern) {
744  //this is for the Linkdef selection
745  const std::string& pattern_value=rule.GetAttributePattern();
746  if (!pattern_value.empty() &&
747  (pattern_value == "*" || pattern_value == "*::*")) ++fImplNo;
748  else
749  earlyReturn=true;
750  }
751  else
752  earlyReturn=true;
753  }
754  else if (rule.GetSelected() == BaseSelectionRule::kDontCare && !(rule.HasMethodSelectionRules()) && !(rule.HasFieldSelectionRules())) {
755  earlyReturn=true;
756  }
757  }
758  } // Loop over the rules.
759 
760  if (earlyReturn) return retval;
761 
762  if (isLinkDefFile) {
763  // for rootcint explicit (name) Yes is stronger than implicit (pattern) No which is stronger than implicit (pattern) Yes
764  if (explicit_selector) return explicit_selector;
765  else if (specific_pattern_selector) return specific_pattern_selector;
766  else if (fImplNo > 0) return 0;
767  else return selector;
768  }
769  else {
770  // for genreflex explicit Yes is stronger than implicit file No
771  return selector; // it can be nullptr
772  }
773 
774 }
775 
776 const BaseSelectionRule *SelectionRules::IsVarSelected(const clang::VarDecl* D, const std::string& qual_name) const
777 {
778  std::list<VariableSelectionRule>::const_iterator it = fVariableSelectionRules.begin();
779  std::list<VariableSelectionRule>::const_iterator it_end = fVariableSelectionRules.end();
780 
781  const BaseSelectionRule *selector = 0;
782 
783  // iterate through all the rules
784  // we call this method only for genrefex variables, functions and enums - it is simpler than the class case:
785  // if we have No - it is veto even if we have explicit yes as well
786  for(; it != it_end; ++it) {
787  if (BaseSelectionRule::kNoMatch != it->Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false)) {
788  if (it->GetSelected() == BaseSelectionRule::kNo) {
789  // The rule did explicitly request to not select this entity.
790  return 0;
791  } else {
792  selector = &(*it);
793  }
794  }
795  }
796 
797  return selector;
798 }
799 
800 const BaseSelectionRule *SelectionRules::IsFunSelected(const clang::FunctionDecl *D, const std::string &qual_name) const
801 {
802 
803  if (fFunctionSelectionRules.size() == 0 ||
804  D->getPrimaryTemplate() != nullptr ||
805  llvm::isa<clang::CXXMethodDecl>(D)) return nullptr;
806 
807  std::string prototype;
808  GetFunctionPrototype(D, prototype);
809  prototype = qual_name + prototype;
810 
811  const BaseSelectionRule *selector = nullptr;
812  // iterate through all the rules
813  // we call this method only for genrefex variables, functions and enums - it is simpler than the class case:
814  // if we have No - it is veto even if we have explicit yes as well
815  for (const auto & rule : fFunctionSelectionRules) {
816  if (BaseSelectionRule::kNoMatch != rule.Match(D, qual_name, prototype, false)) {
817  if (rule.GetSelected() == BaseSelectionRule::kNo) {
818  // The rule did explicitly request to not select this entity.
819  return nullptr;
820  } else {
821  selector = &(rule);
822  }
823  }
824  }
825 
826  return selector;
827 }
828 
829 const BaseSelectionRule *SelectionRules::IsEnumSelected(const clang::EnumDecl* D, const std::string& qual_name) const
830 {
831  const BaseSelectionRule *selector = 0;
832 
833  // iterate through all the rules
834  // we call this method only for genrefex variables, functions and enums - it is simpler than the class case:
835  // if we have No - it is veto even if we have explicit yes as well
836  for(const auto& rule: fEnumSelectionRules) {
837  if (BaseSelectionRule::kNoMatch != rule.Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false)) {
838  if (rule.GetSelected() == BaseSelectionRule::kNo) {
839  // The rule did explicitly request to not select this entity.
840  return 0;
841  } else {
842  selector = &rule;
843  }
844  }
845  }
846 
847  return selector;
848 }
849 
850 const BaseSelectionRule *SelectionRules::IsLinkdefVarSelected(const clang::VarDecl* D, const std::string& qual_name) const
851 {
852 
853 
854  const BaseSelectionRule *selector = 0;
855  int fImplNo = 0;
856  const BaseSelectionRule *explicit_selector = 0;
857 
858  std::string name_value;
859  std::string pattern_value;
860  for(auto& selRule: fVariableSelectionRules) {
861  BaseSelectionRule::EMatchType match
862  = selRule.Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false);
863  if (match != BaseSelectionRule::kNoMatch) {
864  if (selRule.GetSelected() == BaseSelectionRule::kYes) {
865  // explicit rules are with stronger priority in rootcint
866  if (IsLinkdefFile()){
867  if (match == BaseSelectionRule::kName) {
868  explicit_selector = &selRule;
869  } else if (match == BaseSelectionRule::kPattern) {
870  if (selRule.GetAttributeValue("pattern", pattern_value)) {
871  explicit_selector=&selRule;
872  // NOTE: Weird ... This is a strange definition of explicit.
873  //if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = selRule;
874  }
875  }
876  }
877  }
878  else {
879  if (!IsLinkdefFile()) return 0;
880  else {
881  if (selRule.GetAttributeValue("pattern", pattern_value)) {
882  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
883  else
884  return 0;
885  }
886  else
887  return 0;
888  }
889  }
890  }
891  }
892 
893  if (IsLinkdefFile()) {
894 
895 #ifdef SELECTION_DEBUG
896  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
897 #endif
898 
899  if (explicit_selector) return explicit_selector;
900  else if (fImplNo > 0) return 0;
901  else return selector;
902  }
903  else{
904  return selector;
905  }
906 }
907 
908 const BaseSelectionRule *SelectionRules::IsLinkdefFunSelected(const clang::FunctionDecl* D, const std::string& qual_name) const
909 {
910 
911  if (fFunctionSelectionRules.size() == 0 ||
912  D->getPrimaryTemplate() != nullptr ||
913  llvm::isa<clang::CXXMethodDecl>(D)) return nullptr;
914 
915  std::string prototype;
916 
917  GetFunctionPrototype(D, prototype);
918  prototype = qual_name + prototype;
919 
920  const BaseSelectionRule *selector = 0;
921  int fImplNo = 0;
922  const BaseSelectionRule *explicit_selector = 0;
923 
924  std::string pattern_value;
925  for(auto& selRule : fFunctionSelectionRules) {
926  BaseSelectionRule::EMatchType match
927  = selRule.Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, prototype, false);
928  if (match != BaseSelectionRule::kNoMatch) {
929  if (selRule.GetSelected() == BaseSelectionRule::kYes) {
930  // explicit rules are with stronger priority in rootcint
931  if (IsLinkdefFile()){
932  if (match == BaseSelectionRule::kName) {
933  explicit_selector = &selRule;
934  } else if (match == BaseSelectionRule::kPattern) {
935  if (selRule.GetAttributeValue("pattern", pattern_value)) {
936  explicit_selector = &selRule;
937  // NOTE: Weird ... This is a strange definition of explicit.
938  //if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &selRule;
939  }
940  }
941  }
942  }
943  else {
944  if (!IsLinkdefFile()) return 0;
945  else {
946  if (selRule.GetAttributeValue("pattern", pattern_value)) {
947  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
948  else
949  return 0;
950  }
951  else
952  return 0;
953  }
954  }
955  }
956  }
957 
958  if (IsLinkdefFile()) {
959  if (explicit_selector) return explicit_selector;
960  else if (fImplNo > 0) return 0;
961  else return selector;
962  }
963  else{
964  return selector;
965  }
966 }
967 
968 const BaseSelectionRule *SelectionRules::IsLinkdefEnumSelected(const clang::EnumDecl* D, const std::string& qual_name) const
969 {
970  std::list<VariableSelectionRule>::const_iterator it;
971  std::list<VariableSelectionRule>::const_iterator it_end;
972 
973  it = fEnumSelectionRules.begin();
974  it_end = fEnumSelectionRules.end();
975 
976  const BaseSelectionRule *selector = 0;
977  int fImplNo = 0;
978  const BaseSelectionRule *explicit_selector = 0;
979 
980  std::string name_value;
981  std::string pattern_value;
982  for(; it != it_end; ++it) {
983  BaseSelectionRule::EMatchType match =
984  it->Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, "", false);
985  if (match != BaseSelectionRule::kNoMatch) {
986  if (it->GetSelected() == BaseSelectionRule::kYes) {
987  // explicit rules are with stronger priority in rootcint
988  if (IsLinkdefFile()){
989  if (match == BaseSelectionRule::kName){
990  explicit_selector = &(*it);
991  } else if (match == BaseSelectionRule::kPattern &&
992  it->GetAttributeValue("pattern", pattern_value)) {
993  // Note: Weird ... This is a strange definition of explicit.
994  if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it);
995  }
996  }
997  }
998  else {
999  if (!IsLinkdefFile()) return 0;
1000  else {
1001  if (it->GetAttributeValue("pattern", pattern_value)) {
1002  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
1003  else
1004  return 0;
1005  }
1006  else
1007  return 0;
1008  }
1009  }
1010  }
1011  }
1012 
1013  if (IsLinkdefFile()) {
1014 
1015 #ifdef SELECTION_DEBUG
1016  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
1017 #endif
1018 
1019  if (explicit_selector) return explicit_selector;
1020  else if (fImplNo > 0) return 0;
1021  else return selector;
1022  }
1023  else{
1024  return selector;
1025  }
1026 }
1027 
1028 // In rootcint we could select and deselect methods independantly of the class/struct/union rules
1029 // That's why we first have to check the explicit rules for the functions - to see if there
1030 // is rule corresponding to our method.
1031 // Which is more - if we have (and we can have) a pattern for the parent class, than a pattern for the
1032 // nested class, than a pattern for certain methods in the nested class, than a rule for a
1033 // method (name or prototype) in the nested class - the valid rule is the last one.
1034 // This is true irrespective of the rules (select/deselect). This is not the case for genreflex -
1035 // in genreflex if there is a pattern deselecting something even if we have an explicit rule
1036 // to select it, it still will not be selected.
1037 // This method (isLinkdefMethodSelected()) might be incomplete (but I didn't have the time to think
1038 // of anything better)
1039 //
1040 
1041 const BaseSelectionRule *SelectionRules::IsLinkdefMethodSelected(const clang::Decl* D, const std::string& qual_name) const
1042 {
1043  std::list<FunctionSelectionRule>::const_iterator it = fFunctionSelectionRules.begin();
1044  std::list<FunctionSelectionRule>::const_iterator it_end = fFunctionSelectionRules.end();
1045  std::string prototype;
1046 
1047  if (const clang::FunctionDecl* F = llvm::dyn_cast<clang::FunctionDecl> (D))
1048  GetFunctionPrototype(F, prototype);
1049  prototype = qual_name + prototype;
1050 
1051 #ifdef SELECTION_DEBUG
1052  std::cout<<"\tFunction prototype = "<<prototype<<std::endl;
1053 #endif
1054 
1055  int expl_Yes = 0, impl_r_Yes = 0, impl_rr_Yes = 0;
1056  int impl_r_No = 0, impl_rr_No = 0;
1057  const BaseSelectionRule *explicit_r = 0;
1058  const BaseSelectionRule *implicit_r = 0;
1059  const BaseSelectionRule *implicit_rr = 0;
1060 
1061  if (D->getKind() == clang::Decl::CXXMethod){
1062  // we first check the explicit rules for the method (in case of constructors and destructors we check the parent)
1063  std::string pat_value;
1064  for(; it != it_end; ++it) {
1065  BaseSelectionRule::EMatchType match
1066  = it->Match(llvm::dyn_cast<clang::NamedDecl>(D), qual_name, prototype, false);
1067 
1068  if (match == BaseSelectionRule::kName) {
1069  // here I should implement my implicit/explicit thing
1070  // I have included two levels of implicitness - "A::Get_*" is stronger than "*"
1071  explicit_r = &(*it);
1072  if (it->GetSelected() == BaseSelectionRule::kYes) ++expl_Yes;
1073  else {
1074 
1075 #ifdef SELECTION_DEBUG
1076  std::cout<<"\tExplicit rule BaseSelectionRule::kNo found"<<std::endl;
1077 #endif
1078 
1079  return 0; // == explicit BaseSelectionRule::kNo
1080 
1081  }
1082  } else if (match == BaseSelectionRule::kPattern) {
1083 
1084  if (it->GetAttributeValue("pattern", pat_value)) {
1085  if (pat_value == "*") continue; // we discard the global selection rules
1086 
1087  std::string par_name, par_qual_name;
1088  GetParentName(D, par_name, par_qual_name);
1089  std::string par_pat = par_qual_name + "::*";
1090 
1091  if (pat_value == par_pat) {
1092  implicit_rr = &(*it);
1093  if (it->GetSelected() == BaseSelectionRule::kYes) {
1094 
1095 #ifdef SELECTION_DEBUG
1096  std::cout<<"Implicit_rr rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1097 #endif
1098 
1099  ++impl_rr_Yes;
1100  }
1101  else {
1102 
1103 #ifdef SELECTION_DEBUG
1104  std::cout<<"Implicit_rr rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1105 #endif
1106 
1107  ++impl_rr_No;
1108  }
1109  }
1110  else {
1111  implicit_r = &(*it);
1112  if (it->GetSelected() == BaseSelectionRule::kYes) {
1113 
1114 #ifdef SELECTION_DEBUG
1115  std::cout<<"Implicit_r rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1116 #endif
1117 
1118  ++impl_r_Yes;
1119  }
1120  else {
1121 
1122 #ifdef SELECTION_DEBUG
1123  std::cout<<"Implicit_r rule ("<<pat_value<<"), selected = "<<selected<<std::endl;
1124 #endif
1125 
1126  ++impl_r_No;
1127  }
1128  }
1129  }
1130  }
1131  }
1132  }
1133  if (explicit_r /*&& expl_Yes > 0*/){
1134 
1135 #ifdef SELECTION_DEBUG
1136  std::cout<<"\tExplicit rule BaseSelectionRule::BaseSelectionRule::kYes found"<<std::endl;
1137 #endif
1138 
1139  return explicit_r; // if we have excplicit BaseSelectionRule::kYes
1140  }
1141  else if (implicit_rr) {
1142  if (impl_rr_No > 0) {
1143 
1144 #ifdef SELECTION_DEBUG
1145  std::cout<<"\tImplicit_rr rule BaseSelectionRule::kNo found"<<std::endl;
1146 #endif
1147 
1148  return 0;
1149  }
1150  else {
1151 
1152 #ifdef SELECTION_DEBUG
1153  std::cout<<"\tImplicit_rr rule BaseSelectionRule::kYes found"<<std::endl;
1154 #endif
1155 
1156  return implicit_rr;
1157  }
1158  }
1159  else if (implicit_r) {
1160  if (impl_r_No > 0) {
1161 
1162 #ifdef SELECTION_DEBUG
1163  std::cout<<"\tImplicit_r rule BaseSelectionRule::kNo found"<<std::endl;
1164 #endif
1165 
1166  return 0;
1167  }
1168  else {
1169 
1170 #ifdef SELECTION_DEBUG
1171  std::cout<<"\tImplicit_r rule BaseSelectionRule::kYes found"<<std::endl;
1172 #endif
1173 
1174  return implicit_r;
1175  }
1176  }
1177  else {
1178 
1179 #ifdef SELECTION_DEBUG
1180  std::cout<<"\tChecking parent class rules"<<std::endl;
1181 #endif
1182  // check parent
1183 
1184 
1185  std::string parent_name, parent_qual_name;
1186  if (!GetParentName(D, parent_name, parent_qual_name)) return 0;
1187 
1188  const BaseSelectionRule *selector = 0;
1189  int fImplNo = 0;
1190  const BaseSelectionRule *explicit_selector = 0;
1191 
1192  // the same as with isClass selected
1193  // I wanted to use GetParentDecl and then to pass is to isClassSelected because I didn't wanted to repeat
1194  // code but than GetParentDecl crashes (or returns non-sence Decl) for the built-in structs (__va_*)
1195  std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
1196  std::string name_value;
1197  std::string pattern_value;
1198  for(; it != fClassSelectionRules.end(); ++it) {
1199  BaseSelectionRule::EMatchType match
1200  = it->Match(llvm::dyn_cast<clang::NamedDecl>(D), parent_qual_name, "", true); // == BaseSelectionRule::kYes
1201 
1202  if (match != BaseSelectionRule::kNoMatch) {
1203  if (it->GetSelected() == BaseSelectionRule::kYes) {
1204  selector = &(*it);
1205 
1206  if (match == BaseSelectionRule::kName) {
1207  explicit_selector = &(*it);
1208  } else if (match == BaseSelectionRule::kPattern) {
1209  if (it->GetAttributeValue("pattern", pattern_value)) {
1210  // NOTE: weird ...
1211  if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it);
1212  }
1213  }
1214  }
1215  else { // == BaseSelectionRule::kNo
1216 
1217  if (it->GetAttributeValue("pattern", pattern_value)) {
1218  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
1219  else
1220  return 0;
1221  }
1222  else
1223  return 0;
1224  }
1225  }
1226  }
1227 
1228 #ifdef SELECTION_DEBUG
1229  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
1230 #endif
1231 
1232  if (explicit_selector) {
1233 
1234 #ifdef SELECTION_DEBUG
1235  std::cout<<"\tReturning Yes"<<std::endl;
1236 #endif
1237 
1238  return explicit_selector;
1239  }
1240  else if (fImplNo > 0) {
1241 #ifdef SELECTION_DEBUG
1242  std::cout<<"\tReturning No"<<std::endl;
1243 #endif
1244 
1245  return 0;
1246  }
1247  else {
1248 
1249 #ifdef SELECTION_DEBUG
1250  std::cout<<"\tReturning Yes"<<std::endl;
1251 #endif
1252 
1253  return selector;
1254  }
1255  }
1256 
1257  return 0;
1258 
1259 }
1260 
1261 const BaseSelectionRule *SelectionRules::IsMemberSelected(const clang::Decl* D, const std::string& str_name) const
1262 {
1263  std::string parent_name;
1264  std::string parent_qual_name;
1265 
1266  if (IsParentClass(D))
1267  {
1268  if (!GetParentName(D, parent_name, parent_qual_name)) return 0;
1269 
1270  const BaseSelectionRule *selector = 0;
1271  Int_t fImplNo = 0;
1272  const BaseSelectionRule *explicit_selector = 0;
1273  int fFileNo = 0;
1274 
1275  //DEBUG std::cout<<"\n\tParent is class";
1276  std::list<ClassSelectionRule>::const_iterator it = fClassSelectionRules.begin();
1277  std::string name_value;
1278  std::string pattern_value;
1279  for(; it != fClassSelectionRules.end(); ++it) {
1280  BaseSelectionRule::EMatchType match
1281  = it->Match(llvm::dyn_cast<clang::NamedDecl>(D), parent_qual_name, "", false);
1282 
1283  if (match != BaseSelectionRule::kNoMatch) {
1284  if (it->GetSelected() == BaseSelectionRule::kYes) {
1285  selector = &(*it);
1286  if (IsLinkdefFile()) {
1287  if (match == BaseSelectionRule::kName) {
1288  explicit_selector = &(*it);
1289  } else if (match == BaseSelectionRule::kPattern) {
1290  if (it->GetAttributeValue("pattern", pattern_value)) {
1291  // NOTE: Weird ... This is a strange definition of explicit.
1292  if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it);
1293  }
1294  }
1295  }
1296  } else if (it->GetSelected() == BaseSelectionRule::kNo) {
1297  if (!IsLinkdefFile()) {
1298  if (match == BaseSelectionRule::kFile) ++fFileNo;
1299  else {
1300 
1301 #ifdef SELECTION_DEBUG
1302  std::cout<<"\tNo returned"<<std::endl;
1303 #endif
1304 
1305  return 0; // in genreflex we can't have that situation
1306  }
1307  }
1308  else {
1309  if (match == BaseSelectionRule::kPattern && it->GetAttributeValue("pattern", pattern_value)) {
1310  if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo;
1311  else
1312  return 0;
1313  }
1314  else
1315  return 0;
1316  }
1317  }
1318  else if (it->GetSelected() == BaseSelectionRule::kDontCare) // - we check the method and field selection rules for the class
1319  {
1320  if (!it->HasMethodSelectionRules() && !it->HasFieldSelectionRules()) {
1321 
1322 #ifdef SELECTION_DEBUG
1323  std::cout<<"\tNo fields and methods"<<std::endl;
1324 #endif
1325 
1326  return 0; // == BaseSelectionRule::kNo
1327  }
1328  else {
1329  clang::Decl::Kind kind = D->getKind();
1330  if (kind == clang::Decl::Field || kind == clang::Decl::CXXMethod || kind == clang::Decl::CXXConstructor || kind == clang::Decl::CXXDestructor){
1331  std::list<VariableSelectionRule> members;
1332  std::list<VariableSelectionRule>::iterator mem_it;
1333  std::list<VariableSelectionRule>::iterator mem_it_end;
1334  std::string prototype;
1335 
1336  if (kind == clang::Decl::Field) {
1337  members = it->GetFieldSelectionRules();
1338  }
1339  else {
1340  if (const clang::FunctionDecl* F = llvm::dyn_cast<clang::FunctionDecl> (D)){
1341  GetFunctionPrototype(F, prototype);
1342  prototype = str_name + prototype;
1343  }
1344  else{
1345  ROOT::TMetaUtils::Warning("","Warning: could not cast Decl to FunctionDecl\n");
1346  }
1347  members = it->GetMethodSelectionRules();
1348  }
1349  mem_it = members.begin();
1350  mem_it_end = members.end();
1351  for (; mem_it != mem_it_end; ++mem_it) {
1352  if (BaseSelectionRule::kName == mem_it->Match(llvm::dyn_cast<clang::NamedDecl>(D), str_name, prototype, false)) {
1353  if (mem_it->GetSelected() == BaseSelectionRule::kNo) return 0;
1354  }
1355  }
1356  }
1357  }
1358  }
1359  }
1360  }
1361 
1362  if (IsLinkdefFile()) {
1363 
1364 #ifdef SELECTION_DEBUG
1365  std::cout<<"\n\tfYes = "<<fYes<<", fImplNo = "<<fImplNo<<std::endl;
1366 #endif
1367 
1368  if (explicit_selector) {
1369 #ifdef SELECTION_DEBUG
1370  std::cout<<"\tReturning Yes"<<std::endl;
1371 #endif
1372 
1373  return explicit_selector;
1374  }
1375  else if (fImplNo > 0) {
1376 
1377 #ifdef SELECTION_DEBUG
1378  std::cout<<"\tReturning No"<<std::endl;
1379 #endif
1380 
1381  return 0;
1382  }
1383  else {
1384 
1385 #ifdef SELECTION_DEBUG
1386  std::cout<<"\tReturning Yes"<<std::endl;
1387 #endif
1388 
1389  return selector;
1390  }
1391  }
1392  else {
1393 
1394  return selector;
1395  }
1396  }
1397  else {
1398  return 0;
1399  }
1400 }
1401 
1402 bool SelectionRules::AreAllSelectionRulesUsed() const {
1403  for(auto&& rule : fClassSelectionRules){
1404  if (BaseSelectionRule::kNo!=rule.GetSelected() && !rule.GetMatchFound() /* && !GetHasFileNameRule() */ ) {
1405  std::string name;
1406  if (rule.GetAttributeValue("pattern", name)) {
1407  // keep it
1408  } else if (rule.GetAttributeValue("name", name)) {
1409  // keept it
1410  } else {
1411  name.clear();
1412  }
1413  std::string file_name_value;
1414  if (!rule.GetAttributeValue("file_name", file_name_value)) file_name_value.clear();
1415 
1416  if (!file_name_value.empty()) {
1417  // don't complain about defined_in rules
1418  continue;
1419  }
1420 
1421  const char* attrName = "class";
1422  const char* attrVal = nullptr;
1423  if (!name.empty()) attrVal = name.c_str();
1424 
1425  ROOT::TMetaUtils::Warning(0,"Unused %s rule: %s\n", attrName, attrVal);
1426  }
1427  }
1428 
1429  for(auto&& rule : fVariableSelectionRules){
1430  if (!rule.GetMatchFound() && !GetHasFileNameRule()) {
1431  std::string name;
1432  if (rule.GetAttributeValue("pattern", name)) {
1433  // keep it
1434  } else if (rule.GetAttributeValue("name", name)) {
1435  // keept it
1436  } else {
1437  name.clear();
1438  }
1439  ROOT::TMetaUtils::Warning("","Unused variable rule: %s\n",name.c_str());
1440  if (name.empty()) {
1441  rule.PrintAttributes(std::cout,3);
1442  }
1443  }
1444  }
1445 
1446 #if defined(R__MUST_REVISIT)
1447 #if R__MUST_REVISIT(6,2)
1448 ROOT::TMetaUtils::Warning("SelectionRules::AreAllSelectionRulesUsed",
1449 "Warnings concerning non matching selection rules are suppressed. An action is to be taken.\n");
1450 #endif
1451 #endif
1452 // for(const auto& selRule: fFunctionSelectionRules) {
1453 // if (!selRule.GetMatchFound() && !GetHasFileNameRule()) {
1454 // // Here the slow methods can be used
1455 // std::string name;
1456 // if (selRule.GetAttributeValue("proto_pattern", name)) {
1457 // // keep it
1458 // } else if (selRule.GetAttributeValue("proto_name", name)) {
1459 // // keep it
1460 // } else if (selRule.GetAttributeValue("pattern", name)) {
1461 // // keep it
1462 // } else if (selRule.GetAttributeValue("name", name)) {
1463 // // keept it
1464 // } else {
1465 // name.clear();
1466 // }
1467 // // Make it soft, no error - just warnings
1468 // std::cout<<"Warning - unused function rule: "<<name<<std::endl;
1469 // // if (IsSelectionXMLFile()){
1470 // // std::cout<<"Warning - unused function rule: "<<name<<std::endl;
1471 // // }
1472 // // else {
1473 // // std::cout<<"Error - unused function rule: "<<name<<std::endl;
1474 // // }
1475 // if (name.length() == 0) {
1476 // selRule.PrintAttributes(std::cout,3);
1477 // }
1478 // }
1479 //
1480 // }
1481 
1482 
1483 #if Enums_rules_becomes_useful_for_rootcling
1484  for(auto&& rule : fEnumSelectionRules){
1485  if (!rule.GetMatchFound() && !GetHasFileNameRule()) {
1486  std::string name;
1487  if (rule.GetAttributeValue("pattern", name)) {
1488  // keep it
1489  } else if (rule.GetAttributeValue("name", name)) {
1490  // keept it
1491  } else {
1492  name.clear();
1493  }
1494 
1495  ROOT::TMetaUtils::Warning("","Unused enum rule: %s\n",name.c_str());
1496 
1497  if (name.empty()){
1498  rule.PrintAttributes(std::cout,3);
1499  }
1500  }
1501  }
1502 #endif
1503  return true;
1504 }
1505 
1506 bool SelectionRules::SearchNames(cling::Interpreter &interp)
1507 {
1508  // std::cout<<"Searching Names In Selection Rules:"<<std::endl;
1509  for(std::list<ClassSelectionRule>::iterator it = fClassSelectionRules.begin(),
1510  end = fClassSelectionRules.end();
1511  it != end;
1512  ++it) {
1513  if (it->HasAttributeWithName("name")) {
1514  std::string name_value;
1515  it->GetAttributeValue("name", name_value);
1516  // In Class selection rules, we should be interested in scopes.
1517  const clang::Type *typeptr = 0;
1518  const clang::CXXRecordDecl *target
1519  = ROOT::TMetaUtils::ScopeSearch(name_value.c_str(), interp,
1520  true /*diag*/, &typeptr);
1521  if (target) {
1522  it->SetCXXRecordDecl(target,typeptr);
1523  }
1524  }
1525  }
1526  return true;
1527 }
1528 
1529 
1530 void SelectionRules::FillCache()
1531 {
1532  // Fill the cache of every selection rule
1533  for (auto& rule : fClassSelectionRules) rule.FillCache();
1534  for (auto& rule : fFunctionSelectionRules) rule.FillCache();
1535  for (auto& rule : fVariableSelectionRules) rule.FillCache();
1536  for (auto& rule : fEnumSelectionRules) rule.FillCache();
1537 }
1538 
1539