don't allow overloading of built-in functions

the functions are not versioned or scoped, so user-defined overloads would
mess up qmake's own feature files. it seems safer to break user projects
than to allow the user to break qmake.

Change-Id: I020a2e6416bbb6e2fd2ece339629d848c00c8398
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
Oswald Buddenhagen 2012-09-03 20:57:59 +02:00 committed by Qt by Nokia
parent c3c4f1eb53
commit 849f1f9efd
4 changed files with 35 additions and 20 deletions

View File

@ -398,13 +398,12 @@ void QMakeEvaluator::populateDeps(
} }
ProStringList QMakeEvaluator::evaluateBuiltinExpand( ProStringList QMakeEvaluator::evaluateBuiltinExpand(
const ProKey &func, const ProStringList &args) int func_t, const ProKey &func, const ProStringList &args)
{ {
ProStringList ret; ProStringList ret;
traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args)); traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args));
ExpandFunc func_t = ExpandFunc(statics.expands.value(func));
switch (func_t) { switch (func_t) {
case E_BASENAME: case E_BASENAME:
case E_DIRNAME: case E_DIRNAME:
@ -1023,10 +1022,6 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0))); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
} }
break; break;
case E_INVALID:
evalError(fL1S("'%1' is not a recognized replace function.")
.arg(func.toQString(m_tmp1)));
break;
default: default:
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1))); evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
break; break;
@ -1036,11 +1031,10 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
} }
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
const ProKey &function, const ProStringList &args) int func_t, const ProKey &function, const ProStringList &args)
{ {
traceMsg("calling built-in %s(%s)", dbgKey(function), dbgSepStrList(args)); traceMsg("calling built-in %s(%s)", dbgKey(function), dbgSepStrList(args));
TestFunc func_t = (TestFunc)statics.functions.value(function);
switch (func_t) { switch (func_t) {
case T_DEFINED: { case T_DEFINED: {
if (args.count() < 1 || args.count() > 2) { if (args.count() < 1 || args.count() > 2) {
@ -1634,10 +1628,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr); return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
} }
#endif #endif
case T_INVALID:
evalError(fL1S("'%1' is not a recognized test function.")
.arg(function.toQString(m_tmp1)));
return ReturnFalse;
default: default:
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1))); evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;

View File

@ -1642,6 +1642,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction( QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
const ProKey &func, const ushort *&tokPtr) const ProKey &func, const ushort *&tokPtr)
{ {
if (int func_t = statics.functions.value(func)) {
//why don't the builtin functions just use args_list? --Sam
return evaluateBuiltinConditional(func_t, func, expandVariableReferences(tokPtr, 5, true));
}
QHash<ProKey, ProFunctionDef>::ConstIterator it = QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.testFunctions.constFind(func); m_functionDefs.testFunctions.constFind(func);
if (it != m_functionDefs.testFunctions.constEnd()) { if (it != m_functionDefs.testFunctions.constEnd()) {
@ -1650,13 +1655,19 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
return evaluateBoolFunction(*it, args, func); return evaluateBoolFunction(*it, args, func);
} }
//why don't the builtin functions just use args_list? --Sam skipExpression(tokPtr);
return evaluateBuiltinConditional(func, expandVariableReferences(tokPtr, 5, true)); evalError(fL1S("'%1' is not a recognized test function.").arg(func.toQString(m_tmp1)));
return ReturnFalse;
} }
ProStringList QMakeEvaluator::evaluateExpandFunction( ProStringList QMakeEvaluator::evaluateExpandFunction(
const ProKey &func, const ushort *&tokPtr) const ProKey &func, const ushort *&tokPtr)
{ {
if (int func_t = statics.expands.value(func)) {
//why don't the builtin functions just use args_list? --Sam
return evaluateBuiltinExpand(func_t, func, expandVariableReferences(tokPtr, 5, true));
}
QHash<ProKey, ProFunctionDef>::ConstIterator it = QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.replaceFunctions.constFind(func); m_functionDefs.replaceFunctions.constFind(func);
if (it != m_functionDefs.replaceFunctions.constEnd()) { if (it != m_functionDefs.replaceFunctions.constEnd()) {
@ -1665,8 +1676,9 @@ ProStringList QMakeEvaluator::evaluateExpandFunction(
return evaluateFunction(*it, args, 0); return evaluateFunction(*it, args, 0);
} }
//why don't the builtin functions just use args_list? --Sam skipExpression(tokPtr);
return evaluateBuiltinExpand(func, expandVariableReferences(tokPtr, 5, true)); evalError(fL1S("'%1' is not a recognized replace function.").arg(func.toQString(m_tmp1)));
return ProStringList();
} }
bool QMakeEvaluator::evaluateConditional(const QString &cond, const QString &where, int line) bool QMakeEvaluator::evaluateConditional(const QString &cond, const QString &where, int line)

View File

@ -205,8 +205,8 @@ public:
ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr); ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr);
VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr); VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
ProStringList evaluateBuiltinExpand(const ProKey &function, const ProStringList &args); ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args);
VisitReturn evaluateBuiltinConditional(const ProKey &function, const ProStringList &args); VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
bool evaluateConditional(const QString &cond, const QString &where, int line = -1); bool evaluateConditional(const QString &cond, const QString &where, int line = -1);
#ifdef PROEVALUATOR_FULL #ifdef PROEVALUATOR_FULL

View File

@ -42,11 +42,14 @@
#include "project.h" #include "project.h"
#include "option.h" #include "option.h"
#include <qmakeevaluator_p.h>
#include <qdir.h> #include <qdir.h>
#include <stdio.h> #include <stdio.h>
using namespace QMakeInternal;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QMakeProject::QMakeProject() QMakeProject::QMakeProject()
@ -83,24 +86,34 @@ bool QMakeProject::test(const ProKey &func, const QList<ProStringList> &args)
{ {
m_current.clear(); m_current.clear();
if (int func_t = statics.functions.value(func))
return evaluateBuiltinConditional(func_t, func, prepareBuiltinArgs(args)) == ReturnTrue;
QHash<ProKey, ProFunctionDef>::ConstIterator it = QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.testFunctions.constFind(func); m_functionDefs.testFunctions.constFind(func);
if (it != m_functionDefs.testFunctions.constEnd()) if (it != m_functionDefs.testFunctions.constEnd())
return evaluateBoolFunction(*it, args, func) == ReturnTrue; return evaluateBoolFunction(*it, args, func) == ReturnTrue;
return evaluateBuiltinConditional(func, prepareBuiltinArgs(args)) == ReturnTrue; evalError(QStringLiteral("'%1' is not a recognized test function.")
.arg(func.toQString(m_tmp1)));
return false;
} }
QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList> &args) QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList> &args)
{ {
m_current.clear(); m_current.clear();
if (int func_t = statics.expands.value(func))
return evaluateBuiltinExpand(func_t, func, prepareBuiltinArgs(args)).toQStringList();
QHash<ProKey, ProFunctionDef>::ConstIterator it = QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.replaceFunctions.constFind(func); m_functionDefs.replaceFunctions.constFind(func);
if (it != m_functionDefs.replaceFunctions.constEnd()) if (it != m_functionDefs.replaceFunctions.constEnd())
return evaluateFunction(*it, args, 0).toQStringList(); return evaluateFunction(*it, args, 0).toQStringList();
return evaluateBuiltinExpand(func, prepareBuiltinArgs(args)).toQStringList(); evalError(QStringLiteral("'%1' is not a recognized replace function.")
.arg(func.toQString(m_tmp1)));
return QStringList();
} }
ProString QMakeProject::expand(const QString &expr, const QString &where, int line) ProString QMakeProject::expand(const QString &expr, const QString &where, int line)