QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclarativePropertyCache::Data &data, QScriptContext *ctxt) { if (data.flags & QDeclarativePropertyCache::Data::HasArguments) { QMetaMethod m = object->metaObject()->method(data.coreIndex); QList<QByteArray> argTypeNames = m.parameterTypes(); QVarLengthArray<int, 9> argTypes(argTypeNames.count()); // ### Cache for (int ii = 0; ii < argTypeNames.count(); ++ii) { argTypes[ii] = QMetaType::type(argTypeNames.at(ii)); if (argTypes[ii] == QVariant::Invalid) argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii))); if (argTypes[ii] == QVariant::Invalid) return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii))))); } if (argTypes.count() > ctxt->argumentCount()) return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments"))); return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt); } else { return callMethod(object, data.coreIndex, data.propType, 0, 0, ctxt); } }
void MultiwayPathsCoveredCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( switchStmt( hasCondition(allOf( // Match on switch statements that have either a bit-field or // an integer condition. The ordering in 'anyOf()' is // important because the last condition is the most general. anyOf(ignoringImpCasts(memberExpr(hasDeclaration( fieldDecl(isBitField()).bind("bitfield")))), ignoringImpCasts(declRefExpr().bind("non-enum-condition"))), // 'unless()' must be the last match here and must be bound, // otherwise the matcher does not work correctly, because it // will not explicitly ignore enum conditions. unless(ignoringImpCasts( declRefExpr(hasType(enumType())).bind("enum-condition")))))) .bind("switch"), this); // This option is noisy, therefore matching is configurable. if (WarnOnMissingElse) { Finder->addMatcher( ifStmt(allOf(hasParent(ifStmt()), unless(hasElse(anything())))) .bind("else-if"), this); } }
static void installGlobals(ModulePtr m) { m->env = new Env(m); vector<TopLevelItemPtr>::iterator i, end; for (i = m->topLevelItems.begin(), end = m->topLevelItems.end(); i != end; ++i) { TopLevelItem *x = i->ptr(); x->env = m->env; switch (x->objKind) { case ENUMERATION : { Enumeration *enumer = (Enumeration *)x; TypePtr t = enumType(enumer); addGlobal(m, enumer->name, enumer->visibility, t.ptr()); for (unsigned i = 0 ; i < enumer->members.size(); ++i) { EnumMember *member = enumer->members[i].ptr(); member->index = (int)i; member->type = t; addGlobal(m, member->name, enumer->visibility, member); } break; } case PROCEDURE : { Procedure *proc = (Procedure *)x; if (proc->interface != NULL) proc->interface->env = m->env; // fallthrough } default : if (x->name.ptr()) addGlobal(m, x->name, x->visibility, x); break; } } }
void addGlobals(ModulePtr m, llvm::ArrayRef<TopLevelItemPtr> toplevels) { TopLevelItemPtr const *i, *end; for (i = toplevels.begin(), end = toplevels.end(); i != end; ++i) { m->topLevelItems.push_back(*i); TopLevelItem *x = i->ptr(); x->env = m->env; switch (x->objKind) { case ENUM_DECL : { EnumDecl *enumer = (EnumDecl *)x; TypePtr t = enumType(enumer); addGlobal(m, enumer->name, enumer->visibility, t.ptr()); for (unsigned i = 0 ; i < enumer->members.size(); ++i) { EnumMember *member = enumer->members[i].ptr(); member->index = (int)i; member->type = t; addGlobal(m, member->name, enumer->visibility, member); } break; } case PROCEDURE : { Procedure *proc = (Procedure *)x; if (proc->interface != NULL) proc->interface->env = m->env; // fallthrough } default : if (x->name.ptr()) addGlobal(m, x->name, x->visibility, x); break; } } llvm::ArrayRef<TopLevelItemPtr> items = m->topLevelItems; for (size_t i = items.size() - toplevels.size(); i < items.size(); ++i) { Object *obj = items[i].ptr(); switch (obj->objKind) { case OVERLOAD : initOverload((Overload *)obj); break; case INSTANCE_DECL : initVariantInstance((InstanceDecl *)obj); break; case STATIC_ASSERT_TOP_LEVEL: checkStaticAssert((StaticAssertTopLevel *)obj); break; default: break; } } }
/*! Resolve the overloaded method to call. The algorithm works conceptually like this: 1. Resolve the set of overloads it is *possible* to call. Impossible overloads include those that have too many parameters or have parameters of unknown type. 2. Filter the set of overloads to only contain those with the closest number of parameters. For example, if we are called with 3 parameters and there are 2 overloads that take 2 parameters and one that takes 3, eliminate the 2 parameter overloads. 3. Find the best remaining overload based on its match score. If two or more overloads have the same match score, call the last one. The match score is constructed by adding the matchScore() result for each of the parameters. */ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::callOverloaded(MethodData *method, QScriptContext *ctxt) { int argumentCount = ctxt->argumentCount(); QDeclarativePropertyCache::Data *best = 0; int bestParameterScore = INT_MAX; int bestMatchScore = INT_MAX; QDeclarativePropertyCache::Data dummy; QDeclarativePropertyCache::Data *attempt = &method->data; do { QList<QByteArray> methodArgTypeNames; if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments) methodArgTypeNames = method->object->metaObject()->method(attempt->coreIndex).parameterTypes(); int methodArgumentCount = methodArgTypeNames.count(); if (methodArgumentCount > argumentCount) continue; // We don't have sufficient arguments to call this method int methodParameterScore = argumentCount - methodArgumentCount; if (methodParameterScore > bestParameterScore) continue; // We already have a better option int methodMatchScore = 0; QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount); bool unknownArgument = false; for (int ii = 0; ii < methodArgumentCount; ++ii) { methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii)); if (methodArgTypes[ii] == QVariant::Invalid) methodArgTypes[ii] = enumType(method->object->metaObject(), QString::fromLatin1(methodArgTypeNames.at(ii))); if (methodArgTypes[ii] == QVariant::Invalid) { unknownArgument = true; break; } methodMatchScore += matchScore(ctxt->argument(ii), methodArgTypes[ii], methodArgTypeNames.at(ii)); } if (unknownArgument) continue; // We don't understand all the parameters if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) { best = attempt; bestParameterScore = methodParameterScore; bestMatchScore = methodMatchScore; } if (bestParameterScore == 0 && bestMatchScore == 0) break; // We can't get better than that } while((attempt = relatedMethod(method->object, attempt, dummy)) != 0); if (best) { return callPrecise(method->object, *best, ctxt); } else { QString error = QLatin1String("Unable to determine callable overload. Candidates are:"); QDeclarativePropertyCache::Data *candidate = &method->data; while (candidate) { error += QLatin1String("\n ") + QString::fromUtf8(method->object->metaObject()->method(candidate->coreIndex).signature()); candidate = relatedMethod(method->object, candidate, dummy); } return Value(ctxt, ctxt->throwError(error)); } }