CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
findMethod.cc
Go to the documentation of this file.
2 
8 
9 #include <cassert>
10 
12 
15 static
16 bool
17 fatalErrorCondition(const int err)
18 {
19  return (err == reco::parser::kIsNotPublic) ||
20  (err == reco::parser::kIsStatic) ||
23  (err == reco::parser::kIsDestructor) ||
25 }
26 
27 namespace reco {
28 
29 int
31  const edm::TypeWithDict& type,
32  const std::vector<AnyMethodArgument>& args,
33  std::vector<AnyMethodArgument>& fixuppedArgs)
34 {
35  int casts = 0;
36  if (mem.isConstructor()) {
37  return -1 * parser::kIsConstructor;
38  }
39  if (mem.isDestructor()) {
40  return -1 * parser::kIsDestructor;
41  }
42  // Some operators are allowed, e.g. operator[].
43  //if (mem.isOperator()) {
44  // return -1 * parser::kIsOperator;
45  //}
46  if (!mem.isPublic()) {
47  return -1 * parser::kIsNotPublic;
48  }
49  if (mem.isStatic()) {
50  return -1 * parser::kIsStatic;
51  }
52  if (!mem.isConst()) {
53  return -1 * parser::kIsNotConst;
54  }
55  if (mem.name().substr(0, 2) == "__") {
57  }
58  // Functions from a base class are allowed.
59  //if (mem.declaringType() != type) {
60  //std::cerr <<
61  // "\nMETHOD OVERLOAD " <<
62  // mem.name() <<
63  // " by " <<
64  // type.qualifiedName() <<
65  // " from " <<
66  // mem.declaringType().qualifiedName() <<
67  // std::endl;
68  //return -1 * parser::kOverloaded;
69  //}
70 
71  size_t minArgs = mem.functionParameterSize(true);
72  size_t maxArgs = mem.functionParameterSize(false);
73  if ((args.size() < minArgs) || (args.size() > maxArgs)) {
75  }
76  //std::cerr <<
77  // "\nMETHOD " <<
78  // mem.name() <<
79  // " of " <<
80  // mem.declaringType().name() <<
81  // ", min #args = " <<
82  // minArgs <<
83  // ", max #args = " <<
84  // maxArgs <<
85  // ", args = " <<
86  // args.size() <<
87  // std::endl;
88  if (!args.empty()) {
89  std::vector<AnyMethodArgument> tmpFixups;
90  size_t i = 0;
91  for (auto const& param : mem) {
93  std::pair<AnyMethodArgument, int> fixup =
94  boost::apply_visitor(reco::parser::AnyMethodArgumentFixup(parameter),
95  args[i]);
96  //std::cerr <<
97  // "\t ARG " <<
98  // i <<
99  // " type is " <<
100  // parameter.name() <<
101  // " conversion = " <<
102  // fixup.second <<
103  // std::endl;
104  if (fixup.second >= 0) {
105  tmpFixups.push_back(fixup.first);
106  casts += fixup.second;
107  }
108  else {
109  return -1 * parser::kWrongArgumentType;
110  }
111  if (++i == args.size()) {
112  break;
113  }
114  }
115  fixuppedArgs.swap(tmpFixups);
116  }
117  //std::cerr <<
118  // "\nMETHOD " <<
119  // mem.name() <<
120  // " of " <<
121  // mem.declaringType().name() <<
122  // ", min #args = " <<
123  // minArgs <<
124  // ", max #args = " <<
125  // maxArgs <<
126  // ", args = " <<
127  // args.size() <<
128  // " fixupped args = " <<
129  // fixuppedArgs.size() <<
130  // "(" << casts <<
131  // " implicit casts)" <<
132  // std::endl;
133  return casts;
134 }
135 
136 typedef std::pair<int, edm::FunctionWithDict> OK;
137 
138 bool
139 nCasts(const OK& a, const OK& b)
140 {
141  return a.first < b.first;
142 }
143 
144 std::pair<edm::FunctionWithDict, bool>
145 findMethod(const edm::TypeWithDict& t, /*class=in*/
146  const std::string& name, /*function member name=in*/
147  const std::vector<AnyMethodArgument>& args, /*args=in*/
148  std::vector<AnyMethodArgument>& fixuppedArgs, /*args=out*/
149  const char* iIterator, /*???=out*/
150  int& oError) /*err code=out*/
151 {
152  oError = parser::kNameDoesNotExist;
154  if (!bool(type)) {
155  throw parser::Exception(iIterator) << "No dictionary for class \"" <<
156  type.name() << "\".";
157  }
158  while (type.isPointer() || type.isReference()) {
159  type = type.toType();
160  }
161  while (type.isTypedef()) {
162  edm::TypeWithDict theType = type.finalType();
163  if(theType == type) {
164  break;
165  }
166  type = theType;
167  }
168  // strip const, volatile, c++ ref, ..
169  type = type.stripConstRef();
170  // Create our return value.
171  std::pair<edm::FunctionWithDict, bool> mem;
172  //FIXME: We must initialize mem.first!
173  mem.second = false;
174  // suitable members and number of integer->real casts required to get them
175  std::vector<std::pair<int, edm::FunctionWithDict> > oks;
176  std::string theArgs;
177  for(auto const& item : args) {
178  if(!theArgs.empty()) {
179  theArgs += ',';
180  }
181  theArgs += edm::TypeID(item.type()).className();
182  }
183  edm::FunctionWithDict f = type.functionMemberByName(name, theArgs, true);
184  if(bool(f)) {
185  int casts = checkMethod(f, type, args, fixuppedArgs);
186  if (casts > -1) {
187  oks.push_back(std::make_pair(casts, f));
188  } else {
189  oError = -1 * casts;
190  //is this a show stopper error?
191  if (fatalErrorCondition(oError)) {
192  return mem;
193  }
194  }
195  } else {
196  edm::TypeFunctionMembers functions(type);
197  for (auto const& F : functions) {
199  if (f.name() != name) {
200  continue;
201  }
202  int casts = checkMethod(f, type, args, fixuppedArgs);
203  if (casts > -1) {
204  oks.push_back(std::make_pair(casts, f));
205  } else {
206  oError = -1 * casts;
207  //is this a show stopper error?
208  if (fatalErrorCondition(oError)) {
209  return mem;
210  }
211  }
212  }
213  }
214  //std::cout << "At base scope (type " << (type.name()) << ") found " <<
215  // oks.size() << " methods." << std::endl;
216  // found at least one method
217  if (!oks.empty()) {
218  if (oks.size() > 1) {
219  // sort by number of conversions needed
220  sort(oks.begin(), oks.end(), nCasts);
221  if (oks[0].first == oks[1].first) { // two methods with same ambiguity
222  throw parser::Exception(iIterator) << "Can't resolve method \"" <<
223  name << "\" for class \"" << type.name() <<
224  "\", the two candidates " << oks[0].second.name() << " and " <<
225  oks[1].second.name() <<
226  " require the same number of integer->real conversions (" <<
227  oks[0].first << ").";
228  }
229  // We must fixup the args again, as both good methods
230  // have pushed them on fixuppedArgs.
231  fixuppedArgs.clear();
232  checkMethod(oks.front().second, type, args, fixuppedArgs);
233  }
234  mem.first = oks.front().second;
235  }
236  // if nothing was found, look in parent scopes without
237  // checking for cross-scope overloading, as it is not
238  // allowed
239  int baseError = parser::kNameDoesNotExist;
240  if (!bool(mem.first)) {
241  edm::TypeBases bases(type);
242  for (auto const& B : bases) {
243  mem = findMethod(edm::BaseWithDict(B).typeOf(), name, args,
244  fixuppedArgs, iIterator, baseError);
245  if (bool(mem.first)) {
246  break;
247  }
248  if (fatalErrorCondition(baseError)) {
249  oError = baseError;
250  return mem;
251  }
252  }
253  }
254  // otherwise see if this object is just a Ref or Ptr and we should pop it out
255  if (!bool(mem.first)) {
256  // check for edm::Ref or edm::RefToBase or edm::Ptr
257  if (type.isTemplateInstance()) {
258  std::string name = type.templateName();
259  if (!name.compare("edm::Ref") || !name.compare("edm::RefToBase") ||
260  !name.compare("edm::Ptr")) {
261  // in this case i think 'get' should be taken with no arguments!
262  std::vector<AnyMethodArgument> empty;
263  std::vector<AnyMethodArgument> empty2;
264  int error = 0;
265  mem = findMethod(type, "get", empty, empty2, iIterator, error);
266  if (!bool(mem.first)) {
267  throw parser::Exception(iIterator) <<
268  "No member \"get\" in reference of type \"" <<
269  type.name() << "\".";
270  }
271  mem.second = true;
272  }
273  }
274  }
275  //if (!bool(mem.first)) {
276  // throw edm::Exception(edm::errors::Configuration) << "member \""" <<
277  // name << "\"" not found in class \"" << type.name() << "\"";
278  //}
279  if (bool(mem.first)) {
280  oError = parser::kNoError;
281  }
282  else {
283  // use error from base check if we never found function in primary class
284  if (oError == parser::kNameDoesNotExist) {
285  oError = baseError;
286  }
287  }
288  return mem;
289 }
290 
291 } // namespace reco
292 
type
Definition: HCALResponse.h:21
int i
Definition: DBlmapReader.cc:9
TypeWithDict finalType() const
bool isConstructor() const
bool isTypedef() const
reco::parser::AnyMethodArgument AnyMethodArgument
Definition: findMethod.cc:11
std::string name() const
TypeWithDict toType() const
std::string templateName() const
bool isTemplateInstance() const
static bool fatalErrorCondition(const int err)
Definition: findMethod.cc:17
std::string name() const
std::pair< edm::FunctionWithDict, bool > findMethod(const edm::TypeWithDict &t, const std::string &name, const std::vector< AnyMethodArgument > &args, std::vector< AnyMethodArgument > &fixuppedArgs, const char *iIterator, int &oError)
Definition: findMethod.cc:145
double f[11][100]
uint16_t mem[nChs][nEvts]
FunctionWithDict functionMemberByName(std::string const &) const
boost::mpl::if_< matches_another_integral_type< unsigned long >, boost::variant< int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, double, float, std::string >, boost::variant< int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, unsigned long, double, float, std::string > >::type AnyMethodArgument
std::pair< int, edm::FunctionWithDict > OK
Definition: findMethod.cc:136
bool isReference() const
int checkMethod(const edm::FunctionWithDict &mem, const edm::TypeWithDict &type, const std::vector< AnyMethodArgument > &args, std::vector< AnyMethodArgument > &fixuppedArgs)
Definition: findMethod.cc:30
TypeWithDict & stripConstRef()
double b
Definition: hdecay.h:120
size_t functionParameterSize(bool required=false) const
double a
Definition: hdecay.h:121
bool isDestructor() const
bool isPointer() const
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:281
bool nCasts(const OK &a, const OK &b)
Definition: findMethod.cc:139
std::string className(const T &t)
Definition: ClassName.h:30