don't allow overloading of built-in functions
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>
Mon, 3 Sep 2012 18:57:59 +0000 (20:57 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 18 Sep 2012 05:47:14 +0000 (07:47 +0200)
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>
qmake/library/qmakebuiltins.cpp
qmake/library/qmakeevaluator.cpp
qmake/library/qmakeevaluator.h
qmake/project.cpp

index b285265..5140ed5 100644 (file)
@@ -398,13 +398,12 @@ void QMakeEvaluator::populateDeps(
 }
 
 ProStringList QMakeEvaluator::evaluateBuiltinExpand(
-        const ProKey &func, const ProStringList &args)
+        int func_t, const ProKey &func, const ProStringList &args)
 {
     ProStringList ret;
 
     traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args));
 
-    ExpandFunc func_t = ExpandFunc(statics.expands.value(func));
     switch (func_t) {
     case E_BASENAME:
     case E_DIRNAME:
@@ -1023,10 +1022,6 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
             ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
         }
         break;
-    case E_INVALID:
-        evalError(fL1S("'%1' is not a recognized replace function.")
-                  .arg(func.toQString(m_tmp1)));
-        break;
     default:
         evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
         break;
@@ -1036,11 +1031,10 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
 }
 
 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));
 
-    TestFunc func_t = (TestFunc)statics.functions.value(function);
     switch (func_t) {
     case T_DEFINED: {
         if (args.count() < 1 || args.count() > 2) {
@@ -1634,10 +1628,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
         return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
     }
 #endif
-    case T_INVALID:
-        evalError(fL1S("'%1' is not a recognized test function.")
-                  .arg(function.toQString(m_tmp1)));
-        return ReturnFalse;
     default:
         evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
         return ReturnFalse;
index 8bb4fdd..8fad206 100644 (file)
@@ -1642,6 +1642,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
 QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
         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 =
             m_functionDefs.testFunctions.constFind(func);
     if (it != m_functionDefs.testFunctions.constEnd()) {
@@ -1650,13 +1655,19 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
         return evaluateBoolFunction(*it, args, func);
     }
 
-    //why don't the builtin functions just use args_list? --Sam
-    return evaluateBuiltinConditional(func, expandVariableReferences(tokPtr, 5, true));
+    skipExpression(tokPtr);
+    evalError(fL1S("'%1' is not a recognized test function.").arg(func.toQString(m_tmp1)));
+    return ReturnFalse;
 }
 
 ProStringList QMakeEvaluator::evaluateExpandFunction(
         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 =
             m_functionDefs.replaceFunctions.constFind(func);
     if (it != m_functionDefs.replaceFunctions.constEnd()) {
@@ -1665,8 +1676,9 @@ ProStringList QMakeEvaluator::evaluateExpandFunction(
         return evaluateFunction(*it, args, 0);
     }
 
-    //why don't the builtin functions just use args_list? --Sam
-    return evaluateBuiltinExpand(func, expandVariableReferences(tokPtr, 5, true));
+    skipExpression(tokPtr);
+    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)
index 5904c08..312b02c 100644 (file)
@@ -205,8 +205,8 @@ public:
     ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr);
     VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
 
-    ProStringList evaluateBuiltinExpand(const ProKey &function, const ProStringList &args);
-    VisitReturn evaluateBuiltinConditional(const ProKey &function, const ProStringList &args);
+    ProStringList evaluateBuiltinExpand(int func_t, 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);
 #ifdef PROEVALUATOR_FULL
index e369ce1..478693f 100644 (file)
 #include "project.h"
 
 #include "option.h"
+#include <qmakeevaluator_p.h>
 
 #include <qdir.h>
 
 #include <stdio.h>
 
+using namespace QMakeInternal;
+
 QT_BEGIN_NAMESPACE
 
 QMakeProject::QMakeProject()
@@ -83,24 +86,34 @@ bool QMakeProject::test(const ProKey &func, const QList<ProStringList> &args)
 {
     m_current.clear();
 
+    if (int func_t = statics.functions.value(func))
+        return evaluateBuiltinConditional(func_t, func, prepareBuiltinArgs(args)) == ReturnTrue;
+
     QHash<ProKey, ProFunctionDef>::ConstIterator it =
             m_functionDefs.testFunctions.constFind(func);
     if (it != m_functionDefs.testFunctions.constEnd())
         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)
 {
     m_current.clear();
 
+    if (int func_t = statics.expands.value(func))
+        return evaluateBuiltinExpand(func_t, func, prepareBuiltinArgs(args)).toQStringList();
+
     QHash<ProKey, ProFunctionDef>::ConstIterator it =
             m_functionDefs.replaceFunctions.constFind(func);
     if (it != m_functionDefs.replaceFunctions.constEnd())
         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)