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);
  }
}
Beispiel #3
0
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;
        }
    }
}
Beispiel #4
0
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));
    }
}