Go to the documentation of this file.00001 #include "CommonTools/Utils/src/findMethod.h"
00002 #include "CommonTools/Utils/src/ErrorCodes.h"
00003 #include "CommonTools/Utils/interface/Exception.h"
00004 #include "FWCore/Utilities/interface/BaseWithDict.h"
00005 #include "FWCore/Utilities/interface/TypeWithDict.h"
00006 #include <cassert>
00007
00008 using namespace std;
00009 using reco::parser::AnyMethodArgument;
00010
00011
00012 static bool fatalErrorCondition(int iError)
00013 {
00014 return (reco::parser::kIsNotPublic==iError ||
00015 reco::parser::kIsStatic==iError ||
00016 reco::parser::kIsFunctionAddedByROOT==iError ||
00017 reco::parser::kIsConstructor==iError ||
00018 reco::parser::kIsDestructor==iError ||
00019 reco::parser::kIsOperator==iError);
00020
00021 }
00022 namespace reco {
00023 int checkMethod(const edm::FunctionWithDict & mem,
00024 const edm::TypeWithDict & type,
00025 const std::vector<AnyMethodArgument> &args, std::vector<AnyMethodArgument> &fixuppedArgs) {
00026 int casts = 0;
00027 if (mem.isConstructor()) return -1*parser::kIsConstructor;
00028 if (mem.isDestructor()) return -1*parser::kIsDestructor;
00029
00030 if (! mem.isPublic()) return -1*parser::kIsNotPublic;
00031 if (mem.isStatic()) return -1*parser::kIsStatic;
00032 if ( ! mem.isConst() ) return -1*parser::kIsNotConst;
00033 if (mem.name().substr(0, 2) == "__") return -1*parser::kIsFunctionAddedByROOT;
00034 if (mem.declaringType().id() != type.id()) {
00035
00036
00037
00038 return -1*parser::kOverloaded;
00039 }
00040 size_t minArgs = mem.functionParameterSize(true), maxArgs = mem.functionParameterSize(false);
00041 if ((args.size() < minArgs) || (args.size() > maxArgs)) return -1*parser::kWrongNumberOfArguments;
00042
00043
00044
00045 if (!args.empty()) {
00046 std::vector<AnyMethodArgument> tmpFixups;
00047 size_t i = 0;
00048 for (auto const& param : mem) {
00049 edm::TypeWithDict parameter(param);
00050 std::pair<AnyMethodArgument,int> fixup = boost::apply_visitor( reco::parser::AnyMethodArgumentFixup(parameter), args[i] );
00051
00052 if (fixup.second >= 0) {
00053 tmpFixups.push_back(fixup.first);
00054 casts += fixup.second;
00055 } else {
00056 return -1*parser::kWrongArgumentType;
00057 }
00058 if(++i == args.size()) {
00059 break;
00060 }
00061 }
00062 fixuppedArgs.swap(tmpFixups);
00063 }
00064
00065
00066
00067 return casts;
00068 }
00069
00070 typedef pair<int,edm::FunctionWithDict> OK;
00071 bool nCasts(OK const& a, OK const& b) {
00072 return a.first < b.first;
00073 }
00074
00075
00076 pair<edm::FunctionWithDict, bool> findMethod(const edm::TypeWithDict & t,
00077 const string & name,
00078 const std::vector<AnyMethodArgument> &args,
00079 std::vector<AnyMethodArgument> &fixuppedArgs,
00080 const char* iIterator,
00081 int& oError) {
00082 oError = parser::kNameDoesNotExist;
00083 edm::TypeWithDict type = t;
00084 if (! type)
00085 throw parser::Exception(iIterator)
00086 << "No dictionary for class \"" << type.name() << "\".";
00087 while(type.isPointer() || type.isTypedef()) type = type.toType();
00088 type = edm::TypeWithDict(type, 0L);
00089
00090 pair<edm::FunctionWithDict, bool> mem; mem.second = false;
00091
00092
00093 vector<pair<int,edm::FunctionWithDict> > oks;
00094
00095
00096 edm::TypeFunctionMembers functions(type);
00097 for(auto const& function : functions) {
00098 edm::FunctionWithDict m(function);
00099 if(m.name()==name) {
00100 int casts = checkMethod(m, type, args, fixuppedArgs);
00101 if (casts > -1) {
00102 oks.push_back( make_pair(casts,m) );
00103 } else {
00104 oError = -1*casts;
00105
00106 if(fatalErrorCondition(oError)) {
00107 return mem;
00108 }
00109 }
00110 }
00111 }
00112
00113
00114 if (!oks.empty()) {
00115 if (oks.size() > 1) {
00116
00117 sort(oks.begin(), oks.end(), nCasts);
00118
00119 if (oks[0].first == oks[1].first) {
00120 throw parser::Exception(iIterator)
00121 << "Can't resolve method \"" << name << "\" for class \"" << type.name() << "\", the two candidates "
00122 << oks[0].second.name() << " and " << oks[1].second.name()
00123 << " require the same number of integer->real conversions (" << oks[0].first << ").";
00124 }
00125
00126
00127 fixuppedArgs.clear();
00128 checkMethod(oks.front().second, type, args, fixuppedArgs);
00129 }
00130 mem.first = oks.front().second;
00131 }
00132
00133
00134 int baseError=parser::kNameDoesNotExist;
00135 if(! mem.first) {
00136 edm::TypeBases bases(type);
00137 for(auto const& base : bases) {
00138 if((mem = findMethod(edm::BaseWithDict(base).typeOf(), name, args, fixuppedArgs,iIterator,baseError)).first) break;
00139 if(fatalErrorCondition(baseError)) {
00140 oError = baseError;
00141 return mem;
00142 }
00143 }
00144 }
00145
00146
00147 if(!mem.first) {
00148
00149
00150 if(type.isTemplateInstance()) {
00151 std::string name = type.templateName();
00152 if(name.compare("edm::Ref") == 0 ||
00153 name.compare("edm::RefToBase") == 0 ||
00154 name.compare("edm::Ptr") == 0) {
00155
00156 std::vector<AnyMethodArgument> empty, empty2;
00157 int error;
00158 mem = findMethod(type, "get", empty, empty2,iIterator,error);
00159 if(!mem.first) {
00160 throw parser::Exception(iIterator)
00161 << "No member \"get\" in reference of type \"" << type.name() << "\".";
00162 }
00163 mem.second = true;
00164 }
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00173 if(mem.first) {
00174 oError = parser::kNoError;
00175 } else {
00176
00177 if(oError == parser::kNameDoesNotExist) {
00178 oError = baseError;
00179 }
00180 }
00181 return mem;
00182 }
00183 }