warning about redefinition of macro must be show only on same scope 89/17489/8
Antoine ELIAS [Mon, 23 Nov 2015 13:57:04 +0000 (14:57 +0100)]
function foo(), deff("g","");foo2();endfunction
function foo2(),deff("g","j");endfunction
foo() //must not show warning

Change-Id: Ifc92944b27c8bfe6d35f83999a9b0cf4ad84a0e7

scilab/modules/ast/includes/symbol/context.hxx
scilab/modules/ast/includes/symbol/variables.hxx
scilab/modules/ast/src/cpp/ast/run_AssignExp.hpp
scilab/modules/ast/src/cpp/ast/runvisitor.cpp
scilab/modules/ast/src/cpp/symbol/context.cpp
scilab/modules/ast/src/cpp/symbol/variables.cpp
scilab/modules/core/tests/unit_tests/funcprot.dia.ref
scilab/modules/core/tests/unit_tests/funcprot.tst

index 643a777..3fce42c 100644 (file)
@@ -119,8 +119,8 @@ public:
     types::InternalType* getGlobalValue(const Symbol& _key);
 
     /*add symbol and value in the stack*/
-    void put(const Symbol& _key, types::InternalType* _pIT);
-    void put(Variable* _var, types::InternalType* _pIT);
+    bool put(const Symbol& _key, types::InternalType* _pIT);
+    bool put(Variable* _var, types::InternalType* _pIT);
     /*add symbol and value in the previous scope*/
     bool putInPreviousScope(Variable* _var, types::InternalType* _pIT);
 
index ea755a9..25b4ed6 100644 (file)
@@ -40,14 +40,15 @@ struct EXTERN_AST Variable
     Variable(const Symbol& _name) : name(_name), m_Global(false), m_GlobalValue(NULL), last(nullptr) {};
     ~Variable();
 
-    void put(types::InternalType* _pIT, int _iLevel);
+    bool put(types::InternalType* _pIT, int _iLevel);
     void setGlobalValue(types::InternalType* _pIT);
     void setGlobalVisible(int _iLevel, bool _bVisible);
 
-    inline void put(ScopedVariable* pSV)
+    inline bool put(ScopedVariable* pSV)
     {
         last = pSV;
         stack.push(last);
+        return true;
     }
 
     inline types::InternalType* get() const
index c7cb326..58b5c41 100644 (file)
@@ -96,7 +96,20 @@ void RunVisitorT<T>::visitprivate(const AssignExp  &e)
             if (e.getRightExp().isReturnExp())
             {
                 //ReturnExp so, put the value in the previous scope
-                ctx->putInPreviousScope(pVar->getStack(), pIT);
+                if (ctx->putInPreviousScope(pVar->getStack(), pIT) == false)
+                {
+                    char pstError[1024];
+                    char* pstFuncName = wide_string_to_UTF8(pVar->getSymbol().getName().data());
+                    os_sprintf(pstError, _("It is not possible to redefine the %s primitive this way (see clearfun).\n"), pstFuncName);
+                    wchar_t* pwstError = to_wide_string(pstError);
+                    std::wstring wstError(pwstError);
+                    FREE(pstFuncName);
+                    FREE(pwstError);
+                    pIT->killMe();
+                    CoverageInstance::stopChrono((void*)&e);
+                    throw InternalError(wstError, 999, e.getLocation());
+                }
+
                 ((AssignExp*)&e)->setReturn();
             }
             else
index 67491db..4bc1f51 100644 (file)
@@ -1611,42 +1611,16 @@ void RunVisitorT<T>::visitprivate(const FunctionDec & e)
                                             const_cast<SeqExp&>(static_cast<const SeqExp&>(e.getBody())), L"script");
     pMacro->setLines(e.getLocation().first_line, e.getLocation().last_line);
 
-    bool bEquals = false;
-    int iFuncProt = ConfigVariable::getFuncprot();
-    if (iFuncProt != 0)
+    if (ctx->isprotected(symbol::Symbol(pMacro->getName())))
     {
-        types::InternalType* pITFunc = ctx->get(((FunctionDec&)e).getStack());
-        if (pITFunc && pITFunc->isCallable())
-        {
-            if (pITFunc->isMacroFile())
-            {
-                types::MacroFile* pMF = pITFunc->getAs<types::MacroFile>();
-                bEquals = *pMF->getMacro() == *pMacro;
-            }
-            else if (pITFunc->isMacro())
-            {
-                types::Macro* pM = pITFunc->getAs<types::Macro>();
-                bEquals = *pM == *pMacro;
-            }
-        }
-        else
-        {
-            bEquals = true; //avoid msg but keep assignation
-        }
+        delete pMacro;
+        std::wostringstream os;
+        os << _W("Redefining permanent variable.\n");
+        CoverageInstance::stopChrono((void*)&e);
+        throw InternalError(os.str(), 999, e.getLocation());
     }
 
-    if (bEquals == false && iFuncProt == 1 && ConfigVariable::getWarningMode())
-    {
-        wchar_t pwstFuncName[1024];
-        os_swprintf(pwstFuncName, 1024, L"%-24ls", e.getSymbol().getName().c_str());
-        char* pstFuncName = wide_string_to_UTF8(pwstFuncName);
-
-
-        sciprint(_("Warning : redefining function: %s. Use funcprot(0) to avoid this message"), pstFuncName);
-        sciprint("\n");
-        FREE(pstFuncName);
-    }
-    else if (bEquals == false && iFuncProt == 2)
+    if (ctx->addMacro(pMacro) == false)
     {
         char pstError[1024];
         char* pstFuncName = wide_string_to_UTF8(e.getSymbol().getName().c_str());
@@ -1655,22 +1629,11 @@ void RunVisitorT<T>::visitprivate(const FunctionDec & e)
         std::wstring wstError(pwstError);
         FREE(pstFuncName);
         FREE(pwstError);
-        delete pMacro;
+        pMacro->killMe();
         CoverageInstance::stopChrono((void*)&e);
         throw InternalError(wstError, 999, e.getLocation());
     }
 
-
-    if (ctx->isprotected(symbol::Symbol(pMacro->getName())))
-    {
-        delete pMacro;
-        std::wostringstream os;
-        os << _W("Redefining permanent variable.\n");
-        CoverageInstance::stopChrono((void*)&e);
-        throw InternalError(os.str(), 999, e.getLocation());
-    }
-
-    ctx->addMacro(pMacro);
     CoverageInstance::stopChrono((void*)&e);
 }
 
index fec2466..e5bcce8 100644 (file)
@@ -329,7 +329,7 @@ int Context::getLibrariesList(std::list<std::wstring>& lst)
     return libraries.librarieslist(lst);
 }
 
-void Context::put(Variable* _var, types::InternalType* _pIT)
+bool Context::put(Variable* _var, types::InternalType* _pIT)
 {
     if (_pIT->isLibrary())
     {
@@ -337,17 +337,23 @@ void Context::put(Variable* _var, types::InternalType* _pIT)
         lib->put((types::Library*)_pIT, m_iLevel);
     }
 
-    _var->put(_pIT, m_iLevel);
+    if (_var->put(_pIT, m_iLevel) == false)
+    {
+        return false;
+    }
+
     if (varStack.empty() == false)
     {
         (*varStack.top())[_var->getSymbol()] = _var;
     }
+
+    return true;
 }
 
-void Context::put(const Symbol& _key, types::InternalType* _pIT)
+bool Context::put(const Symbol& _key, types::InternalType* _pIT)
 {
     Variable* var = variables.getOrCreate(_key);
-    put(var, _pIT);
+    return put(var, _pIT);
 }
 
 bool Context::remove(const Symbol& _key)
@@ -371,7 +377,10 @@ bool Context::removeAll()
 bool Context::putInPreviousScope(Variable* _var, types::InternalType* _pIT)
 {
     //add variable in previous scope
-    variables.putInPreviousScope(_var, _pIT, m_iLevel - 1);
+    if (variables.putInPreviousScope(_var, _pIT, m_iLevel - 1) == false)
+    {
+        return false;
+    }
 
     //add variable in stack of using variables
     if (varStack.empty() == false)
@@ -401,14 +410,12 @@ bool Context::addFunction(types::Function *_info)
 
 bool Context::addMacro(types::Macro *_info)
 {
-    put(Symbol(_info->getName()), _info);
-    return true;
+    return put(Symbol(_info->getName()), _info);
 }
 
 bool Context::addMacroFile(types::MacroFile *_info)
 {
-    put(Symbol(_info->getName()), _info);
-    return true;
+    return put(Symbol(_info->getName()), _info);
 }
 
 bool Context::isGlobalVisible(const Symbol& _key)
index 03a25f4..7ece052 100644 (file)
 
 #include <algorithm>
 #include "variables.hxx"
+#include "configvariable.hxx"
+#include "macro.hxx"
+#include "macrofile.hxx"
+
+extern "C"
+{
+#include "sciprint.h"
+}
 
 namespace symbol
 {
@@ -64,12 +72,12 @@ void Variable::setGlobalVisible(int _iLevel, bool _bVisible)
 }
 
 
-void Variable::put(types::InternalType* _pIT, int _iLevel)
+bool Variable::put(types::InternalType* _pIT, int _iLevel)
 {
     if (isGlobal() && isGlobalVisible(_iLevel))
     {
         setGlobalValue(_pIT);
-        return;
+        return true;
     }
 
     if (empty() || top()->m_iLevel < _iLevel)
@@ -85,6 +93,45 @@ void Variable::put(types::InternalType* _pIT, int _iLevel)
         types::InternalType* pIT = top()->m_pIT;
         if (pIT != _pIT)
         {
+            //check macro redefinition
+            if (_pIT->isMacro())
+            {
+                int iFuncProt = ConfigVariable::getFuncprot();
+                if (iFuncProt != 0)
+                {
+                    bool bEquals = false;
+                    if (pIT && pIT->isCallable())
+                    {
+                        if (pIT->isMacroFile())
+                        {
+                            types::MacroFile* pMF = pIT->getAs<types::MacroFile>();
+                            bEquals = *pMF->getMacro() == *_pIT;
+                        }
+                        else if (pIT->isMacro())
+                        {
+                            types::Macro* pM = pIT->getAs<types::Macro>();
+                            bEquals = *pM == *_pIT;
+                        }
+                    }
+
+                    if (bEquals == false)
+                    {
+                        if (iFuncProt == 2)
+                        {
+                            return false;
+                        }
+
+                        wchar_t pwstFuncName[1024];
+                        os_swprintf(pwstFuncName, 1024, L"%-24ls", name.getName().c_str());
+                        char* pstFuncName = wide_string_to_UTF8(pwstFuncName);
+
+                        sciprint(_("Warning : redefining function: %s. Use funcprot(0) to avoid this message"), pstFuncName);
+                        sciprint("\n");
+                        FREE(pstFuncName);
+                    }
+                }
+            }
+
             // _pIT may contained in pIT
             // so increases ref of _pIT before kill pIT
             top()->m_pIT = _pIT;
@@ -93,6 +140,8 @@ void Variable::put(types::InternalType* _pIT, int _iLevel)
             pIT->killMe();
         }
     }
+
+    return true;
 }
 
 Variable* Variables::getOrCreate(const Symbol& _key)
@@ -389,23 +438,26 @@ bool Variables::putInPreviousScope(Variable* _var, types::InternalType* _pIT, in
 {
     if (_var->empty())
     {
-        _var->put(_pIT, _iLevel);
+        return _var->put(_pIT, _iLevel);
     }
     else if (_var->top()->m_iLevel > _iLevel)
     {
         ScopedVariable* pVar = _var->top();
         _var->pop();
-        putInPreviousScope(_var, _pIT, _iLevel);
+        if (putInPreviousScope(_var, _pIT, _iLevel) == false)
+        {
+            return false;
+        }
         //decresef ref before, increase it in put
         //pVar->m_pIT->DecreaseRef();
-        _var->put(pVar);
+        return _var->put(pVar);
     }
     else
     {
-        _var->put(_pIT, _iLevel);
+        return _var->put(_pIT, _iLevel);
     }
 
-    return true;
+    return false;
 }
 
 //globals
index 5626b84..2cfbfa8 100644 (file)
@@ -1,24 +1,36 @@
 //<-- CLI SHELL MODE -->
 // =============================================================================
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Paul Bignier
 // Copyright (C) ????-2008 - INRIA
 //
 //  This file is distributed under the same license as the Scilab package.
 // =============================================================================
 // <-- ENGLISH IMPOSED -->
-//funcprot
-deff("foo()","a=1");
+// funcprot
+deff("foo()", "a = 1");
 funcprot(0);
-if funcprot() <> 0 then bugmes();quit;end
-if execstr("deff(""foo()"",""a=1"");","errcatch") <> 0 then bugmes();quit;end
-deff("foo()","a=2");
+assert_checkequal(funcprot(), 0);
+assert_checkequal(execstr("deff(""foo()"", ""a = 1"");", "errcatch"), 0);
+deff("foo()", "a = 2");
 funcprot(1);
-if funcprot() <> 1 then bugmes();quit;end
-if execstr("deff(""foo()"",""a=3"");","errcatch") <> 0 then bugmes();quit;end
+assert_checkequal(funcprot(), 1);
+assert_checkequal(execstr("deff(""foo()"", ""a = 3"");", "errcatch"), 0);
 Warning : redefining function: foo                     . Use funcprot(0) to avoid this message
-deff("foo()","a=4")
+deff("foo()", "a = 4")
 Warning : redefining function: foo                     . Use funcprot(0) to avoid this message
 funcprot(2);
-if funcprot() <> 2 then bugmes();quit;end
-if execstr("deff(""foo()"",""a=5"");","errcatch") == 0 then bugmes();quit;end
-if execstr("deff(""foo()"",""a=4"");","errcatch") <> 0 then bugmes();quit;end
+assert_checkequal(funcprot(), 2);
+assert_checkfalse(execstr("deff(""foo()"", ""a = 5"");", "errcatch") == 0);
+assert_checkequal(execstr("deff(""foo()"", ""a = 4"");", "errcatch"), 0);
+// No warning in new scope
+funcprot(1);
+clear foo;
+function foo()
+    deff("g", "j");
+endfunction
+function foo2()
+    deff("g", "");
+    foo();
+endfunction
+foo2() // Must not show a warning
index ba261d8..762f562 100644 (file)
@@ -1,6 +1,7 @@
 //<-- CLI SHELL MODE -->
 // =============================================================================
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Paul Bignier
 // Copyright (C) ????-2008 - INRIA
 //
 //  This file is distributed under the same license as the Scilab package.
@@ -8,21 +9,35 @@
 
 // <-- ENGLISH IMPOSED -->
 
-//funcprot
+// funcprot
 
-deff("foo()","a=1");
+deff("foo()", "a = 1");
 
 funcprot(0);
-if funcprot() <> 0 then pause,end
-if execstr("deff(""foo()"",""a=1"");","errcatch") <> 0 then pause,end
-deff("foo()","a=2");
+assert_checkequal(funcprot(), 0);
+assert_checkequal(execstr("deff(""foo()"", ""a = 1"");", "errcatch"), 0);
+deff("foo()", "a = 2");
 
 funcprot(1);
-if funcprot() <> 1 then pause,end
-if execstr("deff(""foo()"",""a=3"");","errcatch") <> 0 then pause,end
-deff("foo()","a=4")
+assert_checkequal(funcprot(), 1);
+assert_checkequal(execstr("deff(""foo()"", ""a = 3"");", "errcatch"), 0);
+deff("foo()", "a = 4")
 
 funcprot(2);
-if funcprot() <> 2 then pause,end
-if execstr("deff(""foo()"",""a=5"");","errcatch") == 0 then pause,end
-if execstr("deff(""foo()"",""a=4"");","errcatch") <> 0 then pause,end
+assert_checkequal(funcprot(), 2);
+assert_checkfalse(execstr("deff(""foo()"", ""a = 5"");", "errcatch") == 0);
+assert_checkequal(execstr("deff(""foo()"", ""a = 4"");", "errcatch"), 0);
+
+
+// No warning in new scope
+funcprot(1);
+clear foo;
+function foo()
+    deff("g", "j");
+endfunction
+function foo2()
+    deff("g", "");
+    foo();
+endfunction
+
+foo2() // Must not show a warning