CMS 3D CMS Logo

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