// @(#)root/core/utils:$Id: SelectionRules.cxx 41697 2011-11-01 21:03:41Z pcanal $ // Author: Velislava Spasova September 2010 /************************************************************************* * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ ////////////////////////////////////////////////////////////////////////// // // // SelectionRules // // // // the class representing all selection rules // // // ////////////////////////////////////////////////////////////////////////// #include "SelectionRules.h" #include #include "TString.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "cling/Interpreter/Interpreter.h" const clang::CXXRecordDecl *R__SlowRawTypeSearch(const char *input_name, const clang::DeclContext *ctxt = 0); void SelectionRules::AddClassSelectionRule(const ClassSelectionRule& classSel) { fClassSelectionRules.push_back(classSel); } bool SelectionRules::HasClassSelectionRules() const { return !fClassSelectionRules.empty(); } const std::list& SelectionRules::GetClassSelectionRules() const { return fClassSelectionRules; } void SelectionRules::AddFunctionSelectionRule(const FunctionSelectionRule& funcSel) { fFunctionSelectionRules.push_back(funcSel); } bool SelectionRules::HasFunctionSelectionRules() const { return !fFunctionSelectionRules.empty(); } const std::list& SelectionRules::GetFunctionSelectionRules() const { return fFunctionSelectionRules; } void SelectionRules::AddVariableSelectionRule(const VariableSelectionRule& varSel) { fVariableSelectionRules.push_back(varSel); } bool SelectionRules::HasVariableSelectionRules() const { return !fVariableSelectionRules.empty(); } const std::list& SelectionRules::GetVariableSelectionRules() const { return fVariableSelectionRules; } void SelectionRules::AddEnumSelectionRule(const EnumSelectionRule& enumSel) { fEnumSelectionRules.push_back(enumSel); } bool SelectionRules::HasEnumSelectionRules() const { return !fEnumSelectionRules.empty(); } const std::list& SelectionRules::GetEnumSelectionRules() const { return fEnumSelectionRules; } void SelectionRules::PrintSelectionRules() const { std::cout<<"Printing Selection Rules:"<::const_iterator it = fClassSelectionRules.begin(); it != fClassSelectionRules.end(); ++it, ++i) { std::cout<<"\tClass sel rule "<GetSelected()){ case BaseSelectionRule::kYes: std::cout<<"Yes"<PrintAttributes(2); if (it->HasFieldSelectionRules()) { //std::cout<<"\t\tHas field entries"< fields = it->GetFieldSelectionRules(); std::list::iterator fit = fields.begin(); int j = 0; for (; fit != fields.end(); ++fit, ++j) { std::cout<<"\t\tField "<GetSelected()){ case BaseSelectionRule::kYes: std::cout<<"Yes"<PrintAttributes(3); } } else { std::cout<<"\t\tNo field sel rules"<HasMethodSelectionRules()) { //std::cout<<"\t\tHas method entries"< methods = it->GetMethodSelectionRules(); std::list::iterator mit = methods.begin(); int k = 0; for (; mit != methods.end(); ++mit, ++k) { std::cout<<"\t\tMethod "<GetSelected()){ case BaseSelectionRule::kYes: std::cout<<"Yes"<PrintAttributes(3); } } else { std::cout<<"\t\tNo method sel rules"<::const_iterator it2; int i = 0; for (it2 = fFunctionSelectionRules.begin(); it2 != fFunctionSelectionRules.end(); ++it2, ++i) { std::cout<<"\tFunction sel rule "<GetSelected()){ case BaseSelectionRule::kYes: std::cout<<"Yes"<PrintAttributes(2); } } else { std::cout<<"\tNo function sel rules"<::const_iterator it3; int i = 0; for (it3 = fVariableSelectionRules.begin(); it3 != fVariableSelectionRules.end(); ++it3, ++i) { std::cout<<"\tVariable sel rule "<GetSelected()){ case BaseSelectionRule::kYes: std::cout<<"Yes"<PrintAttributes(2); } } else { std::cout<<"\tNo variable sel rules"<::const_iterator it4; int i = 0; for (it4 = fEnumSelectionRules.begin(); it4 != fEnumSelectionRules.end(); ++it4, ++i) { std::cout<<"\tEnum sel rule "<GetSelected()){ case BaseSelectionRule::kYes: std::cout<<"Yes"<PrintAttributes(2); } } else { std::cout<<"\tNo enum sel rules"<GetIndex() + 1; } ClassSelectionRule csr(count++); csr.SetAttributeValue("pattern", "*"); csr.SetSelected(BaseSelectionRule::kYes); AddClassSelectionRule(csr); ClassSelectionRule csr2(count++); csr2.SetAttributeValue("pattern", "*::*"); csr2.SetSelected(BaseSelectionRule::kYes); AddClassSelectionRule(csr2); // Should I disable the built-in (automatically generated) structs/classes? ClassSelectionRule csr3(count++); csr3.SetAttributeValue("pattern", "__va_*"); // csr3.SetSelected(BaseSelectionRule::kNo); AddClassSelectionRule(csr3); //HasFileNameRule = true; //SetSelectionXMLFile(true); } } bool SelectionRules::GetDeep() const { if (fIsDeep) return true; else return false; } const BaseSelectionRule *SelectionRules::IsDeclSelected(clang::Decl *D) const { std::string str_name; // name of the Decl std::string kind; // kind of the Decl std::string qual_name; // fully qualified name of the Decl if (!D) { return 0; } kind = D->getDeclKindName(); GetDeclName(D, str_name, qual_name); // fprintf(stderr,"IsDeclSelected: %s %s\n", str_name.c_str(), qual_name.c_str()); if (kind == "CXXRecord") { // structs, unions and classes are all CXXRecords return IsClassSelected(D, qual_name); } if (kind == "ClassTemplateSpecialization") { // structs, unions and classes are all CXXRecords return IsClassSelected(D, qual_name); } if (kind == "ClassTemplatePartialSpecialization") { // structs, unions and classes are all CXXRecords fprintf(stderr,"ClassTemplatePartialSpecialization: %s %s\n",llvm::dyn_cast(D)->getNameAsString().c_str(),qual_name.c_str()); return IsClassSelected(D, qual_name); } if (kind == "Namespace") { // structs, unions and classes are all CXXRecords return IsNamespaceSelected(D, qual_name); } if (kind == "Var" || kind == "Function") { if (!IsLinkdefFile()) return IsVarFunEnumSelected(D, kind, qual_name); else return IsLinkdefVarFunEnumSelected(D, kind, qual_name); } if (kind == "Enum"){ // Enum is part of a class if (IsParentClass(D)) { const BaseSelectionRule *selector = IsMemberSelected(D, kind, str_name); if (!selector) // if the parent class is deselected, we could still select the enum return IsVarFunEnumSelected(D, kind, qual_name); else // if the parent class is selected so are all nested enums return selector; } // Enum is not part of a class else { if (IsLinkdefFile()) return IsLinkdefVarFunEnumSelected(D, kind, qual_name); return IsVarFunEnumSelected(D, kind, qual_name); } } if (kind == "CXXMethod" || kind == "CXXConstructor" || kind == "CXXDestructor" || kind == "Field") { /* DEBUG if(kind != "Field"){ std::string proto; if (GetFunctionPrototype(D,proto)) std::cout<<"\n\tFunction prototype: "< (D); if (N) { // the identifier is NULL for some special methods like constructors, destructors and operators if (N->getIdentifier()) { name = N->getNameAsString(); } else if (N->isCXXClassMember()) { // for constructors, destructors, operator=, etc. methods name = N->getNameAsString(); // we use this (unefficient) method to Get the name in that case } N->getNameForDiagnostic(qual_name,N->getASTContext().getPrintingPolicy(),true); return true; } else { return false; } } bool SelectionRules::GetDeclSourceFileName(clang::Decl* D, std::string& file_name) const { clang::SourceLocation SL = D->getLocation(); clang::ASTContext& ctx = D->getASTContext(); clang::SourceManager& SM = ctx.getSourceManager(); if (SL.isValid() && SL.isFileID()) { clang::PresumedLoc PLoc = SM.getPresumedLoc(SL); file_name = PLoc.getFilename(); return true; } else { file_name = "invalid"; return false; } } bool SelectionRules::GetFunctionPrototype(clang::Decl* D, std::string& prototype) const { if (!D) { return false; } clang::FunctionDecl* F = llvm::dyn_cast (D); // cast the Decl to FunctionDecl if (F) { prototype = ""; // iterate through all the function parameters for (clang::FunctionDecl::param_iterator I = F->param_begin(), E = F->param_end(); I != E; ++I) { clang::ParmVarDecl* P = *I; if (prototype != "") prototype += ","; std::string type = P->getType().getAsString(); // pointers are returned in the form "int *" and I need them in the form "int*" if (type.at(type.length()-1) == '*') { type.at(type.length()-2) = '*'; type.erase(type.length()-1); } prototype += type; } prototype = "(" + prototype + ")"; return true; } else { std::cout<<"Warning - can't convert Decl to FunctionDecl"<getDeclContext(); if (ctx->isRecord()){ clang::Decl *parent = llvm::dyn_cast (ctx); if (!parent) { return false; } else { //TagDecl has methods to understand of what kind is the Decl - class, struct or union clang::TagDecl* T = llvm::dyn_cast (parent); if (T) { if (T->isClass()||T->isStruct()) { return true; } else { return false; } } else { return false; } } } else { return false; } } bool SelectionRules::IsParentClass(clang::Decl* D, std::string& parent_name, std::string& parent_qual_name) const { clang::DeclContext *ctx = D->getDeclContext(); if (ctx->isRecord()){ clang::Decl *parent = llvm::dyn_cast (ctx); if (!parent) { return false; } else { //TagDecl has methods to understand of what kind is the Decl clang::TagDecl* T = llvm::dyn_cast (parent); if (T) { if (T->isClass()|| T->isStruct()) { GetDeclName(parent, parent_name, parent_qual_name); return true; } else { return false; } } else { return false; } } } else { return false; } } bool SelectionRules::GetParentName(clang::Decl* D, std::string& parent_name, std::string& parent_qual_name) const { clang::DeclContext *ctx = D->getDeclContext(); if (ctx->isRecord()){ //DEBUG std::cout<<"\n\tDeclContext is Record"; clang::Decl *parent = llvm::dyn_cast (ctx); if (!parent) { return false; } else { GetDeclName(parent, parent_name, parent_qual_name); return true; } } else { return false; } } /* This is the method that crashes bool SelectionRules::GetParent(clang::Decl* D, clang::Decl* parent) { clang::DeclContext *ctx = D->GetDeclContext(); if (ctx->isRecord()){ //DEBUG std::cout<<"\n\tDeclContext is Record"; parent = llvm::dyn_cast (ctx); if (!parent) { return false; } else { return true; } } else return false; } */ // isClassSelected checks if a class is selected or not. Thre is a difference between the // behaviour of rootcint and genreflex especially with regard to class pattern processing. // In genreflex if we have this will select all the classes // (and structs) found in the header file. In rootcint if we have something similar, i.e. // #pragma link C++ class *, we will select only the outer classes - for the nested // classes we have to specifie #pragma link C++ class *::*. And yet this is only valid // for one level of nesting - if you need it for many levels of nesting, you will // probably have to implement it yourself. // Here the idea is the following - we traverse the list of class selection rules. // For every class we check do we have a class selection rule. We use here the // method isSelected() (defined in BaseSelectionRule.cxx). This method returns true // only if we have class selection rule which says "Select". Otherwise it returns // false - in which case we have to check wether we found a class selection rule // which says "Veto" (noName = false and don't Care = false; OR noName = false and // don't Care = true and we don't have neither method nor field selection rules - // which is for the selection.xml file case). If noName is true than we just continue - // this means that the current class selection rule isn't applicable for this class. const BaseSelectionRule *SelectionRules::IsNamespaceSelected(clang::Decl* D, const std::string& qual_name) const { clang::NamespaceDecl* N = llvm::dyn_cast (D); //TagDecl has methods to understand of what kind is the Decl if (N==0) { std::cout<<"\n\tCouldn't cast Decl to NamespaceDecl"; return 0; } std::string file_name; if (GetHasFileNameRule()){ if (!GetDeclSourceFileName(N, file_name)){ } } const BaseSelectionRule *selector = 0; int fImplNo = 0; const BaseSelectionRule *explicit_selector = 0; int fFileNo = 0; bool file; // NOTE: should we separate namespaces from classes in the rules? std::list::const_iterator it = fClassSelectionRules.begin(); // iterate through all class selection rles for(; it != fClassSelectionRules.end(); ++it) { bool dontC, noName; bool yes; if (IsLinkdefFile()){ yes = it->IsSelected(N, qual_name, "", file_name, dontC, noName, file, true); } else { yes = it->IsSelected(N, qual_name, "", file_name, dontC, noName, file, false); } if (yes) { selector = &(*it); if (IsLinkdefFile()){ // rootcint prefers explicit rules over pattern rules if (it->HasAttributeWithName("name")) { std::string name_value; it->GetAttributeValue("name", name_value); if (name_value == qual_name) explicit_selector = &(*it); } if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it); } } } else if (!noName && !dontC) { // = BaseSelectionRule::kNo (noName = false <=> we have named rule for this class) // dontC = false <=> we are not in the exclusion part (for genreflex) if (!IsLinkdefFile()) { // in genreflex - we could explicitly select classes from other source files if (file) ++fFileNo; // if we have veto because of class defined in other source file -> implicit No else { #ifdef SELECTION_DEBUG std::cout<<"\tNo returned"<HasAttributeWithName("pattern")) { //this is for the Linkdef selection std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo; else return 0; } else return 0; } else if (dontC && !(it->HasMethodSelectionRules()) && !(it->HasFieldSelectionRules())) { #ifdef SELECTION_DEBUG std::cout<<"Empty dontC returned = No"<IsSelected(llvm::dyn_cast(D), qual_name, "", file_name, dontC, noName, file, false); } if (yes) { selector = &(*it); if (IsLinkdefFile()){ // rootcint prefers explicit rules over pattern rules if (it->HasAttributeWithName("name")) { std::string name_value; it->GetAttributeValue("name", name_value); if (name_value == qual_name) explicit_selector = &(*it); else { // Try a real match! // fprintf(stderr,"TRYING MATCH: %s %s\n",name_value.c_str(),qual_name.c_str()); const clang::CXXRecordDecl *target = R__SlowRawTypeSearch(name_value.c_str()); if ( target == llvm::dyn_cast( D ) ) { explicit_selector = &(*it); } } } if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it); } } } else if (!noName && !dontC) { // = BaseSelectionRule::kNo (noName = false <=> we have named rule for this class) // dontC = false <=> we are not in the exclusion part (for genreflex) if (!IsLinkdefFile()) { // in genreflex - we could explicitly select classes from other source files if (file) ++fFileNo; // if we have veto because of class defined in other source file -> implicit No else { #ifdef SELECTION_DEBUG std::cout<<"\tNo returned"<HasAttributeWithName("pattern")) { //this is for the Linkdef selection std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo; else return 0; } else return 0; } else if (dontC && !(it->HasMethodSelectionRules()) && !(it->HasFieldSelectionRules())) { #ifdef SELECTION_DEBUG std::cout<<"Empty dontC returned = No"<::const_iterator it; std::list::const_iterator it_end; std::string prototype; if (kind == "Var") { it = fVariableSelectionRules.begin(); it_end = fVariableSelectionRules.end(); } else if (kind == "Function") { GetFunctionPrototype(D, prototype); prototype = qual_name + prototype; #ifdef SELECTION_DEBUG std::cout<<"\tIn isVarFunEnumSelected()"<IsSelected(llvm::dyn_cast(D), qual_name, "", file_name, d, noMatch, file, false); else selected = it->IsSelected(llvm::dyn_cast(D), qual_name, prototype, file_name, d, noMatch, file, false); if (selected) { selector = &(*it); } else if (!noMatch) { // The rule did explicitly request to not select this entity. return 0; } } return selector; } const BaseSelectionRule *SelectionRules::IsLinkdefVarFunEnumSelected(clang::Decl* D, const std::string& kind, const std::string& qual_name) const { std::list::const_iterator it; std::list::const_iterator it_end; std::string prototype; if (kind == "Var") { it = fVariableSelectionRules.begin(); it_end = fVariableSelectionRules.end(); } else if (kind == "Function") { GetFunctionPrototype(D, prototype); prototype = qual_name + prototype; it = fFunctionSelectionRules.begin(); it_end = fFunctionSelectionRules.end(); } else { it = fEnumSelectionRules.begin(); it_end = fEnumSelectionRules.end(); } std::string file_name; if (GetHasFileNameRule()){ if (GetDeclSourceFileName(D, file_name)) { #ifdef SELECTION_DEBUG std::cout<<"\tSource file name: "<IsSelected(llvm::dyn_cast(D), qual_name, "", file_name, d, n, file, false); else selected = it->IsSelected(llvm::dyn_cast(D), qual_name, prototype, file_name, d, n, file, false); if(selected) { // explicit rules are with stronger priority in rootcint if (IsLinkdefFile()){ if (it->HasAttributeWithName("name")) { std::string name_value; it->GetAttributeValue("name", name_value); if (name_value == qual_name) explicit_selector = &(*it); } if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it); } } } else if (!n) { if (!IsLinkdefFile()) return 0; else { if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo; else return 0; } else return 0; } } } if (IsLinkdefFile()) { #ifdef SELECTION_DEBUG std::cout<<"\n\tfYes = "<IsSelected(llvm::dyn_cast(D), qual_name, prototype, "", d, n, file, false); if (selected || !n){ // here I should implement my implicit/explicit thing // I have included two levels of implicitness - "A::Get_*" is stronger than "*" if (it->HasAttributeWithName("name") || it->HasAttributeWithName("proto_name")) { explicit_r = &(*it); if (selected) ++expl_Yes; else { #ifdef SELECTION_DEBUG std::cout<<"\tExplicit rule BaseSelectionRule::kNo found"<HasAttributeWithName("pattern")) { std::string pat_value; it->GetAttributeValue("pattern", pat_value); if (pat_value == "*") continue; // we discard the global selection rules std::string par_name, par_qual_name; GetParentName(D, par_name, par_qual_name); std::string par_pat = par_qual_name + "::*"; if (pat_value == par_pat) { implicit_rr = &(*it); if (selected) { #ifdef SELECTION_DEBUG std::cout<<"Implicit_rr rule ("< 0) { #ifdef SELECTION_DEBUG std::cout<<"\tImplicit_rr rule BaseSelectionRule::kNo found"< 0) { #ifdef SELECTION_DEBUG std::cout<<"\tImplicit_r rule BaseSelectionRule::kNo found"<::const_iterator it = fClassSelectionRules.begin(); for(; it != fClassSelectionRules.end(); ++it) { bool yes; yes = it->IsSelected(llvm::dyn_cast(D), parent_qual_name, "", file_name, dontC, noName, file, true); // == BaseSelectionRule::kYes if (yes) { selector = &(*it); if (it->HasAttributeWithName("name")) { std::string name_value; it->GetAttributeValue("name", name_value); if (name_value == parent_qual_name) explicit_selector = &(*it); } if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it); } } else if (!noName) { // == BaseSelectionRule::kNo if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo; else return 0; } else return 0; } } #ifdef SELECTION_DEBUG std::cout<<"\n\tfYes = "< 0) { #ifdef SELECTION_DEBUG std::cout<<"\tReturning No"<::const_iterator it = fClassSelectionRules.begin(); for(; it != fClassSelectionRules.end(); ++it) { bool yes; yes = it->IsSelected(llvm::dyn_cast(D), parent_qual_name, "", file_name, dontC, noName, file, false); // == BaseSelectionRule::kYes if (yes) { selector = &(*it); if (IsLinkdefFile()) { if (it->HasAttributeWithName("name")) { std::string name_value; it->GetAttributeValue("name", name_value); if (name_value == parent_qual_name) explicit_selector = &(*it); } if (it->HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value != "*" && pattern_value != "*::*") explicit_selector = &(*it); } } } else if (!noName && !dontC) { // == BaseSelectionRule::kNo if (!IsLinkdefFile()) { if (file) ++fFileNo; else { #ifdef SELECTION_DEBUG std::cout<<"\tNo returned"<HasAttributeWithName("pattern")) { std::string pattern_value; it->GetAttributeValue("pattern", pattern_value); if (pattern_value == "*" || pattern_value == "*::*") ++fImplNo; else return 0; } else return 0; } } else if (dontC ) { // == BaseSelectionRule::kDontCare - we check the method and field selection rules for the class if (!it->HasMethodSelectionRules() && !it->HasFieldSelectionRules()) { #ifdef SELECTION_DEBUG std::cout<<"\tNo fields and methods"< members; std::list::iterator mem_it; std::list::iterator mem_it_end; std::string prototype; if (kind == "Field") { members = it->GetFieldSelectionRules(); } else { GetFunctionPrototype(D, prototype); prototype = str_name + prototype; #ifdef SELECTION_DEBUG std::cout<<"\tIn isMemberSelected (DC)"<GetMethodSelectionRules(); } mem_it = members.begin(); mem_it_end = members.end(); for (; mem_it != mem_it_end; ++mem_it) { if (!mem_it->IsSelected(llvm::dyn_cast(D), str_name, prototype, file_name, dontC, noName, file, false)) { if (!noName) return 0; } } } } } } if (IsLinkdefFile()) { #ifdef SELECTION_DEBUG std::cout<<"\n\tfYes = "< 0) { #ifdef SELECTION_DEBUG std::cout<<"\tReturning No"<::const_iterator it = fClassSelectionRules.begin(); it != fClassSelectionRules.end(); ++it) { if (!it->GetMatchFound() && !GetHasFileNameRule()) { std::string name; if (it->HasAttributeWithName("name")) it->GetAttributeValue("name", name); if (it->HasAttributeWithName("pattern")) it->GetAttributeValue("pattern", name); if (IsSelectionXMLFile()){ std::cout<<"Warning - unused class rule: "; } else { std::cout<<"Error - unused class rule: "; //return false; } if (name.length() > 0) { std::cout << name << '\n'; } else { it->PrintAttributes(29); } } } } if (!fVariableSelectionRules.empty()) { for(std::list::const_iterator it = fVariableSelectionRules.begin(); it != fVariableSelectionRules.end(); ++it) { if (!it->GetMatchFound() && !GetHasFileNameRule()) { std::string name; if (it->HasAttributeWithName("name")) it->GetAttributeValue("name", name); if (it->HasAttributeWithName("pattern")) it->GetAttributeValue("pattern", name); if (IsSelectionXMLFile()){ std::cout<<"Warning - unused variable rule: "<PrintAttributes(3); } } } } if (!fFunctionSelectionRules.empty()) { for(std::list::const_iterator it = fFunctionSelectionRules.begin(); it != fFunctionSelectionRules.end(); ++it) { if (!it->GetMatchFound() && !GetHasFileNameRule()) { std::string name; if (it->HasAttributeWithName("name")) it->GetAttributeValue("name", name); if (it->HasAttributeWithName("pattern")) it->GetAttributeValue("pattern", name); if (it->HasAttributeWithName("proto_name")) it->GetAttributeValue("proto_name", name); if (it->HasAttributeWithName("proto_pattern")) it->GetAttributeValue("proto_pattern", name); if (IsSelectionXMLFile()){ std::cout<<"Warning - unused function rule: "<PrintAttributes(3); } } } } if (!fEnumSelectionRules.empty()) { for(std::list::const_iterator it = fEnumSelectionRules.begin(); it != fEnumSelectionRules.end(); ++it) { if (!it->GetMatchFound() && !GetHasFileNameRule()) { std::string name; if (it->HasAttributeWithName("name")) it->GetAttributeValue("name", name); if (it->HasAttributeWithName("pattern")) it->GetAttributeValue("pattern", name); if (IsSelectionXMLFile()){ std::cout<<"Warning - unused enum rule: "<PrintAttributes(3); } } } } return true; } bool SelectionRules::SearchNames(cling::Interpreter &interp) { std::cout<<"Searching Names In Selection Rules:"<::iterator it = fClassSelectionRules.begin(), end = fClassSelectionRules.end(); it != end; ++it) { if (it->HasAttributeWithName("name")) { std::string name_value; it->GetAttributeValue("name", name_value); const clang::CXXRecordDecl *target = R__SlowRawTypeSearch(name_value.c_str()); bool needinstantiation = false; if (!target) { needinstantiation = strchr(name_value.c_str(),'<') != 0; } else if (! target->isCompleteDefinition() ) { // In case we got the target via a typedef, let's use it's final name. name_value.clear(); target->getNameForDiagnostic(name_value,target->getASTContext().getPrintingPolicy(),true); needinstantiation = true; } if (needinstantiation) { // Force instantiation std::string instantiate("template class "); instantiate += name_value; instantiate += " ;"; interp.declare(instantiate.c_str()); target = R__SlowRawTypeSearch(name_value.c_str()); } if (target) { it->SetCXXRecordDecl(target); } } } } return true; }