Merge pull request #834 from melex750/dev
Implicit cast and null when passing argumentsdev-new-models
commit
89bf0da30c
|
@ -1730,6 +1730,9 @@ msgstr ""
|
|||
msgid "Expression expected after ="
|
||||
msgstr ""
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dividing by zero"
|
||||
msgstr ""
|
||||
|
||||
|
|
3
po/de.po
3
po/de.po
|
@ -86,6 +86,9 @@ msgstr "Trägt schon etwas"
|
|||
msgid "Alternative camera mode\\Move sideways instead of rotating (in free camera)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analysis already performed"
|
||||
msgstr "Analyse schon durchgeführt"
|
||||
|
||||
|
|
3
po/fr.po
3
po/fr.po
|
@ -81,6 +81,9 @@ msgstr "Porte déjà quelque chose"
|
|||
msgid "Alternative camera mode\\Move sideways instead of rotating (in free camera)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analysis already performed"
|
||||
msgstr "Analyse déjà effectuée"
|
||||
|
||||
|
|
3
po/pl.po
3
po/pl.po
|
@ -84,6 +84,9 @@ msgstr "Nie można nieść więcej przedmiotów"
|
|||
msgid "Alternative camera mode\\Move sideways instead of rotating (in free camera)"
|
||||
msgstr "Alternatywny tryb kamery\\Poruszaj na boki zamiast obracać (w kamerze swobodnej)"
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr "Niejednoznaczne wywołanie przeciążonej funkcji"
|
||||
|
||||
msgid "Analysis already performed"
|
||||
msgstr "Analiza została już wykonana"
|
||||
|
||||
|
|
3
po/ru.po
3
po/ru.po
|
@ -84,6 +84,9 @@ msgstr "Уже что-то несу"
|
|||
msgid "Alternative camera mode\\Move sideways instead of rotating (in free camera)"
|
||||
msgstr "Альтернативный режим камеры\\Движение в стороны вместо поворачивания (в режиме свободной камеры)"
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analysis already performed"
|
||||
msgstr "Анализ уже выполнен"
|
||||
|
||||
|
|
|
@ -639,7 +639,6 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
{
|
||||
// return a method precompiled in pass 1
|
||||
CBotFunction* pf = m_pMethod;
|
||||
CBotFunction* prev = nullptr;
|
||||
CBotToken* ppp = p;
|
||||
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
|
||||
CBotDefParam* params = CBotDefParam::Compile(p, pStk );
|
||||
|
@ -648,7 +647,6 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
while ( pf != nullptr ) // search by name and parameters
|
||||
{
|
||||
if (pf->GetName() == pp && pf->CheckParam( params )) break;
|
||||
prev = pf;
|
||||
pf = pf->Next();
|
||||
}
|
||||
|
||||
|
@ -684,6 +682,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
initType = CBotVar::InitType::DEF;
|
||||
pcopy->SetInit(initType);
|
||||
pcopy->SetUniqNum(pv->GetUniqNum());
|
||||
pcopy->SetPrivate(pv->GetPrivate());
|
||||
pile->AddVar(pcopy);
|
||||
pv = pv->GetNext();
|
||||
}
|
||||
|
@ -693,18 +692,12 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
// compiles a method
|
||||
p = pBase;
|
||||
CBotFunction* f =
|
||||
CBotFunction::Compile(p, pile, nullptr/*, false*/);
|
||||
CBotFunction::Compile(p, pile, pf/*, false*/);
|
||||
|
||||
if ( f != nullptr )
|
||||
{
|
||||
f->m_pProg = pStack->GetProgram();
|
||||
f->m_bSynchro = bSynchro;
|
||||
// replaces the element in the chain
|
||||
f->m_next = pf->m_next;
|
||||
pf->m_next = nullptr;
|
||||
delete pf;
|
||||
if (prev == nullptr) m_pMethod = f;
|
||||
else prev->m_next = f;
|
||||
}
|
||||
pStack->Return(nullptr, pile);
|
||||
}
|
||||
|
|
|
@ -236,6 +236,7 @@ enum CBotError : int
|
|||
CBotErrPrivate = 5041, //!< protected item
|
||||
CBotErrNoPublic = 5042, //!< missing word "public"
|
||||
CBotErrNoExpression = 5043, //!< expression expected after =
|
||||
CBotErrAmbiguousCall = 5044, //!< ambiguous call to overloaded function
|
||||
|
||||
// Runtime errors
|
||||
CBotErrZeroDiv = 6000, //!< division by zero
|
||||
|
|
|
@ -105,12 +105,12 @@ CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMeth
|
|||
CBotFieldExpr* i = new CBotFieldExpr();
|
||||
i->SetToken(pp);
|
||||
inst->AddNext3(i);
|
||||
CBotVar* preVar = var;
|
||||
var = var->GetItem(p->GetString());
|
||||
if (var != nullptr)
|
||||
{
|
||||
i->SetUniqNum(var->GetUniqNum());
|
||||
if ( var->IsPrivate() &&
|
||||
!pStk->GetProgram()->m_bCompileClass)
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, pp);
|
||||
goto err;
|
||||
|
|
|
@ -67,8 +67,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
|||
|
||||
if (ident > 0 && ident < 9000)
|
||||
{
|
||||
if ( var->IsPrivate(privat) &&
|
||||
!pStk->GetProgram()->m_bCompileClass)
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, privat))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, p);
|
||||
goto err;
|
||||
|
@ -133,12 +132,12 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
|||
CBotFieldExpr* i = new CBotFieldExpr(); // new element
|
||||
i->SetToken(pp); // keeps the name of the token
|
||||
inst->AddNext3(i); // add after
|
||||
CBotVar* preVar = var;
|
||||
var = var->GetItem(p->GetString()); // get item correspondent
|
||||
if (var != nullptr)
|
||||
{
|
||||
i->SetUniqNum(var->GetUniqNum());
|
||||
if ( var->IsPrivate() &&
|
||||
!pStk->GetProgram()->m_bCompileClass)
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, privat))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, pp);
|
||||
goto err;
|
||||
|
|
|
@ -134,4 +134,57 @@ std::string CBotFieldExpr::GetDebugData()
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar,
|
||||
CBotVar::ProtectionLevel privat)
|
||||
{
|
||||
CBotVar::ProtectionLevel varPriv = pVar->GetPrivate();
|
||||
|
||||
if (privat == CBotVar::ProtectionLevel::ReadOnly && varPriv == privat)
|
||||
return true;
|
||||
|
||||
if (varPriv == CBotVar::ProtectionLevel::Public) return false;
|
||||
|
||||
std::string prevName = (pPrev == nullptr) ? "" : pPrev->GetName();
|
||||
|
||||
// implicit 'this.'var, this.var, or super.var
|
||||
if (pPrev == nullptr || prevName == "this" || prevName == "super") // member of the current class
|
||||
{
|
||||
if (varPriv == CBotVar::ProtectionLevel::Private) // var is private ?
|
||||
{
|
||||
CBotToken token("this");
|
||||
CBotVar* pThis = pStack->FindVar(token);
|
||||
CBotClass* pClass = pThis->GetClass(); // the current class
|
||||
|
||||
CBotVar* pVarList = pClass->GetVar();
|
||||
|
||||
int ident = pVar->GetUniqNum();
|
||||
// check if var is inherited from a parent class
|
||||
if (pVarList == nullptr || ident < pVarList->GetUniqNum())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else // any other context
|
||||
{
|
||||
if (pVar->IsPrivate()) // var is protected or private ?
|
||||
{
|
||||
CBotToken token("this");
|
||||
CBotVar* pThis = pStack->FindVar(token);
|
||||
|
||||
if (pThis == nullptr) return true; // inside a function ?
|
||||
if (pThis->GetType() != CBotTypPointer) return true;
|
||||
|
||||
CBotClass* pClass = pThis->GetClass(); // the current class
|
||||
|
||||
if (!pClass->IsChildOf(pPrev->GetClass())) // var is member of some other class ?
|
||||
return true;
|
||||
|
||||
if (varPriv == CBotVar::ProtectionLevel::Private && // private member of a parent class
|
||||
pClass != pPrev->GetClass()) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace CBot
|
||||
|
|
|
@ -65,6 +65,21 @@ public:
|
|||
*/
|
||||
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
|
||||
|
||||
/*!
|
||||
* \brief Check if access to a variable is allowed or not depending on public/private/protected setting
|
||||
*
|
||||
* If this function returns true, the caller is responsible for failing the compilation with ::CBotErrPrivate error.
|
||||
* This function doesn't set the error flag itself.
|
||||
*
|
||||
* \param pStack Current compilation stack frame
|
||||
* \param pPrev Class instance which variable to check is part of, or nullptr if not part of a class
|
||||
* \param pVar Variable to check
|
||||
* \param privat CBotVar::ProtectionLevel::ReadOnly if requesting read-only access, anything else otherwise
|
||||
* \return true if pVar is inaccessible in the current context, false if access should be allowed
|
||||
*/
|
||||
static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar,
|
||||
CBotVar::ProtectionLevel privat = CBotVar::ProtectionLevel::Protected);
|
||||
|
||||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotFieldExpr"; }
|
||||
virtual std::string GetDebugData() override;
|
||||
|
|
|
@ -224,10 +224,6 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
func->m_closeblk = (p != nullptr && p->GetPrev() != nullptr) ? *(p->GetPrev()) : CBotToken();
|
||||
if ( pStk->IsOk() )
|
||||
{
|
||||
if ( func->m_bPublic ) // public function, return known for all
|
||||
{
|
||||
CBotFunction::AddPublic(func);
|
||||
}
|
||||
return pStack->ReturnFunc(func, pStk);
|
||||
}
|
||||
}
|
||||
|
@ -466,8 +462,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
|||
|
||||
if ( name.empty() ) return nullptr;
|
||||
|
||||
int delta = 99999; // seeks the lowest signature
|
||||
CBotFunction* pFunc = nullptr; // the best function found
|
||||
std::map<CBotFunction*, int> funcMap;
|
||||
|
||||
if ( this != nullptr )
|
||||
{
|
||||
|
@ -482,44 +477,48 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
|||
CBotVar* pw = ppVars[i++]; // provided list parameter
|
||||
while ( pv != nullptr && pw != nullptr)
|
||||
{
|
||||
if (!TypesCompatibles(pv->GetTypResult(), pw->GetTypResult()))
|
||||
CBotTypResult paramType = pv->GetTypResult();
|
||||
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
|
||||
if (!TypesCompatibles(paramType, argType))
|
||||
{
|
||||
if ( pFunc == nullptr ) TypeOrError = CBotErrBadParam;
|
||||
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
|
||||
break;
|
||||
}
|
||||
|
||||
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
|
||||
{
|
||||
CBotClass* c1 = paramType.GetClass();
|
||||
CBotClass* c2 = argType.GetClass();
|
||||
while (c2 != c1 && c2 != nullptr) // implicit cast
|
||||
{
|
||||
alpha += 10;
|
||||
c2 = c2->GetParent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
||||
|
||||
}
|
||||
pv = pv->GetNext();
|
||||
pw = ppVars[i++];
|
||||
}
|
||||
if ( pw != nullptr )
|
||||
{
|
||||
if ( pFunc != nullptr ) continue;
|
||||
if ( !funcMap.empty() ) continue;
|
||||
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
||||
continue; // too many parameters
|
||||
}
|
||||
if ( pv != nullptr )
|
||||
{
|
||||
if ( pFunc != nullptr ) continue;
|
||||
if ( !funcMap.empty() ) continue;
|
||||
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
||||
continue; // not enough parameters
|
||||
}
|
||||
|
||||
if (alpha == 0) // perfect signature
|
||||
{
|
||||
nIdent = pt->m_nFuncIdent;
|
||||
TypeOrError = pt->m_retTyp;
|
||||
return pt;
|
||||
}
|
||||
|
||||
if ( alpha < delta ) // a better signature?
|
||||
{
|
||||
pFunc = pt;
|
||||
delta = alpha;
|
||||
}
|
||||
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -537,50 +536,72 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
|||
CBotVar* pw = ppVars[i++]; // list of provided parameters
|
||||
while ( pv != nullptr && pw != nullptr)
|
||||
{
|
||||
if (!TypesCompatibles(pv->GetTypResult(), pw->GetTypResult()))
|
||||
CBotTypResult paramType = pv->GetTypResult();
|
||||
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
|
||||
if (!TypesCompatibles(paramType, argType))
|
||||
{
|
||||
if ( pFunc == nullptr ) TypeOrError = CBotErrBadParam;
|
||||
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
|
||||
break;
|
||||
}
|
||||
|
||||
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
|
||||
{
|
||||
CBotClass* c1 = paramType.GetClass();
|
||||
CBotClass* c2 = argType.GetClass();
|
||||
while (c2 != c1 && c2 != nullptr) // implicit cast
|
||||
{
|
||||
alpha += 10;
|
||||
c2 = c2->GetParent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
||||
|
||||
}
|
||||
pv = pv->GetNext();
|
||||
pw = ppVars[i++];
|
||||
}
|
||||
if ( pw != nullptr )
|
||||
{
|
||||
if ( pFunc != nullptr ) continue;
|
||||
if ( !funcMap.empty() ) continue; // previous useable function
|
||||
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
||||
continue; // to many parameters
|
||||
}
|
||||
if ( pv != nullptr )
|
||||
{
|
||||
if ( pFunc != nullptr ) continue;
|
||||
if ( !funcMap.empty() ) continue; // previous useable function
|
||||
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
||||
continue; // not enough parameters
|
||||
}
|
||||
|
||||
if (alpha == 0) // perfect signature
|
||||
{
|
||||
nIdent = pt->m_nFuncIdent;
|
||||
TypeOrError = pt->m_retTyp;
|
||||
return pt;
|
||||
}
|
||||
|
||||
if ( alpha < delta ) // a better signature?
|
||||
{
|
||||
pFunc = pt;
|
||||
delta = alpha;
|
||||
}
|
||||
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( pFunc != nullptr )
|
||||
if ( !funcMap.empty() )
|
||||
{
|
||||
auto it = funcMap.begin();
|
||||
CBotFunction* pFunc = it->first; // the best function found
|
||||
signed int delta = it->second; // seeks the lowest signature
|
||||
|
||||
for (++it ; it != funcMap.end() ; it++)
|
||||
{
|
||||
if (it->second < delta) // a better signature?
|
||||
{
|
||||
TypeOrError.SetType(CBotNoErr);
|
||||
pFunc = it->first;
|
||||
delta = it->second;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (it->second == delta) TypeOrError.SetType(CBotErrAmbiguousCall);
|
||||
}
|
||||
|
||||
if (TypeOrError.Eq(CBotErrAmbiguousCall)) return nullptr;
|
||||
nIdent = pFunc->m_nFuncIdent;
|
||||
TypeOrError = pFunc->m_retTyp;
|
||||
return pFunc;
|
||||
|
|
|
@ -149,12 +149,20 @@ bool TypesCompatibles(const CBotTypResult& type1, const CBotTypResult& type2)
|
|||
|
||||
if (max >= CBotTypBoolean)
|
||||
{
|
||||
if (t1 == CBotTypPointer && t2 == CBotTypNullPointer) return true;
|
||||
if (t2 != t1) return false;
|
||||
|
||||
if (max == CBotTypPointer)
|
||||
{
|
||||
CBotClass* c1 = type1.GetClass();
|
||||
CBotClass* c2 = type2.GetClass();
|
||||
return c2->IsChildOf(c1);
|
||||
}
|
||||
|
||||
if (max == CBotTypArrayPointer)
|
||||
return TypesCompatibles(type1.GetTypElem(), type2.GetTypElem());
|
||||
|
||||
if (max == CBotTypClass || max == CBotTypPointer)
|
||||
if (max == CBotTypClass)
|
||||
return type1.GetClass() == type2.GetClass() ;
|
||||
|
||||
return true ;
|
||||
|
|
|
@ -64,8 +64,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
inst->m_nIdent = var->GetUniqNum();
|
||||
if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
|
||||
{
|
||||
if ( var->IsPrivate(CBotVar::ProtectionLevel::ReadOnly) &&
|
||||
!pStk->GetProgram()->m_bCompileClass)
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, CBotVar::ProtectionLevel::ReadOnly))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, p);
|
||||
goto err;
|
||||
|
@ -125,11 +124,12 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
|
||||
if (p->GetType() == TokenTypVar) // must be a name
|
||||
{
|
||||
CBotVar* preVar = var;
|
||||
var = var->GetItem(p->GetString()); // get item correspondent
|
||||
if (var != nullptr)
|
||||
{
|
||||
if ( var->IsPrivate(CBotVar::ProtectionLevel::ReadOnly) &&
|
||||
!pStk->GetProgram()->m_bCompileClass)
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var,
|
||||
CBotVar::ProtectionLevel::ReadOnly))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, pp);
|
||||
goto err;
|
||||
|
|
|
@ -124,14 +124,13 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
|||
if ( p->GetType() == ID_CLASS ||
|
||||
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
|
||||
{
|
||||
m_bCompileClass = true;
|
||||
CBotClass::Compile(p, pStack.get()); // completes the definition of the class
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bCompileClass = false;
|
||||
CBotFunction::Compile(p, pStack.get(), next);
|
||||
if (next->IsExtern()) functions.push_back(next->GetName()/* + next->GetParams()*/);
|
||||
if (next->IsPublic()) CBotFunction::AddPublic(next);
|
||||
next->m_pProg = this; // keeps pointers to the module
|
||||
next = next->Next();
|
||||
}
|
||||
|
|
|
@ -332,13 +332,6 @@ public:
|
|||
*/
|
||||
CBotFunction* GetFunctions();
|
||||
|
||||
/**
|
||||
* \brief true while compiling class
|
||||
*
|
||||
* TODO: refactor this
|
||||
*/
|
||||
bool m_bCompileClass;
|
||||
|
||||
/**
|
||||
* \brief Returns static list of all registered external calls
|
||||
*/
|
||||
|
|
|
@ -106,7 +106,7 @@ public:
|
|||
|
||||
/**
|
||||
* \brief Returns ::CBotType or ::CBotError stored in this object
|
||||
* \param mode Mode, see ::GetTypeMode enum
|
||||
* \param mode Mode, see GetTypeMode enum
|
||||
*/
|
||||
int GetType(GetTypeMode mode = GetTypeMode::NORMAL) const;
|
||||
|
||||
|
|
|
@ -717,6 +717,7 @@ void InitializeRestext()
|
|||
stringsCbot[CBot::CBotErrPrivate] = TR("Private element");
|
||||
stringsCbot[CBot::CBotErrNoPublic] = TR("Public required");
|
||||
stringsCbot[CBot::CBotErrNoExpression] = TR("Expression expected after =");
|
||||
stringsCbot[CBot::CBotErrAmbiguousCall] = TR("Ambiguous call to overloaded function");
|
||||
|
||||
stringsCbot[CBot::CBotErrZeroDiv] = TR("Dividing by zero");
|
||||
stringsCbot[CBot::CBotErrNotInit] = TR("Variable not initialized");
|
||||
|
|
|
@ -1786,3 +1786,270 @@ TEST_F(CBotUT, ClassNewConstructorMethodChain)
|
|||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, PassNullAsArgument)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class BaseClass {}\n"
|
||||
"public class SubClass extends BaseClass {}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"bool Test(BaseClass b) {\n"
|
||||
" return (b == null);\n"
|
||||
"}\n"
|
||||
"extern void PassNullAsArgument() {\n"
|
||||
" ASSERT(true == Test(null));\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"void Test(BaseClass b) {}\n"
|
||||
"void Test(SubClass s) {}\n"
|
||||
"\n"
|
||||
"extern void AmbiguousCallArgumentNull() {\n"
|
||||
" Test(null);\n"
|
||||
"}\n",
|
||||
CBotErrAmbiguousCall
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassImplicitCastArguments)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class BaseClass { int a = 360; }\n"
|
||||
"public class SubClass extends BaseClass {}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"bool Test(BaseClass b) {\n"
|
||||
" SubClass s = b;\n"
|
||||
" return (360 == s.a);\n"
|
||||
"}\n"
|
||||
"extern void UpcastPassingArguments() {\n"
|
||||
" ASSERT(true == Test(new SubClass()));\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"void Test(BaseClass b, SubClass s) {}\n"
|
||||
"void Test(SubClass s, BaseClass b) {}\n"
|
||||
"\n"
|
||||
"extern void UpcastAmbiguousCall() {\n"
|
||||
" Test(new SubClass(), new SubClass());\n"
|
||||
"}\n",
|
||||
CBotErrAmbiguousCall
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"bool Test(BaseClass b, SubClass s) { return false; }\n"
|
||||
"bool Test(SubClass s, BaseClass b) { return false; }\n"
|
||||
"bool Test(SubClass s, SubClass s2) { return true; }\n"
|
||||
"\n"
|
||||
"extern void NoErrorMoreSpecific() {\n"
|
||||
" ASSERT(true == Test(new SubClass(), new SubClass()));\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, AmbiguousCallWithNumbers)
|
||||
{
|
||||
ExecuteTest(
|
||||
"void Test(int i, float f) {}\n"
|
||||
"void Test(float f, int i) {}\n"
|
||||
"\n"
|
||||
"extern void AmbiguousCallNumbers() {\n"
|
||||
" Test(1, 2);\n"
|
||||
"}\n",
|
||||
CBotErrAmbiguousCall
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"bool Test(int i, float f) { return false; }\n"
|
||||
"bool Test(float f, int i) { return false; }\n"
|
||||
"bool Test(int i, int ii) { return true; }\n"
|
||||
"\n"
|
||||
"extern void NoErrorMoreSpecific() {\n"
|
||||
" ASSERT(true == Test(1, 2));\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassMethodWithPublicKeyword)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" public int Test() { return 1; }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"int Test() { return 2; }\n"
|
||||
"\n"
|
||||
"extern void DontCallMethodInTestClass()\n"
|
||||
"{\n"
|
||||
" ASSERT(2 == Test());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"int Test() { return 2; }\n"
|
||||
"\n"
|
||||
"public class OtherClass {}\n"
|
||||
"\n"
|
||||
"extern void OtherClass::TestCallWithThis()\n"
|
||||
"{\n"
|
||||
" this.Test();\n"
|
||||
"}\n",
|
||||
CBotErrUndefCall
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassTestProtectedMember)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class BaseClass {\n"
|
||||
" protected int a_protected = 1;\n"
|
||||
" bool test() {\n"
|
||||
" a_protected = 1;\n"
|
||||
" int a = a_protected;\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"extern void Test() {\n"
|
||||
" BaseClass b();\n"
|
||||
" ASSERT(true == b.test());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {\n"
|
||||
" bool testProtected() {\n"
|
||||
" a_protected = 1;\n"
|
||||
" int a = a_protected;\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"extern void TestSubClassAccessProtected() {\n"
|
||||
" SubClass s();\n"
|
||||
" ASSERT(true == s.test());\n"
|
||||
" ASSERT(true == s.testProtected());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void TestErrorProtected() {\n"
|
||||
" BaseClass b();\n"
|
||||
" int i = b.a_protected;\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void ErrorProtectedAssignment() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.a_protected = 1;\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SomeOtherClass {\n"
|
||||
" void testErrorProtected() {\n"
|
||||
" BaseClass b();\n"
|
||||
" int i = b.a_protected;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SomeOtherClass {\n"
|
||||
" void testErrorProtectedAssignment() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.a_protected = 1;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassTestPrivateMember)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class BaseClass {\n"
|
||||
" private int a_private = 2;\n"
|
||||
"\n"
|
||||
" bool test() {\n"
|
||||
" a_private = 2;\n"
|
||||
" int a = a_private;\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
" bool NoErrorPrivateSameClass() {\n"
|
||||
" BaseClass b = new BaseClass();\n"
|
||||
" int a = b.a_private;\n"
|
||||
" b.a_private = 2;\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"extern void Test() {\n"
|
||||
" BaseClass b();\n"
|
||||
" ASSERT(true == b.test());\n"
|
||||
" ASSERT(true == b.NoErrorPrivateSameClass());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {\n"
|
||||
" void testErrorPrivate() {\n"
|
||||
" int a = a_private;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {\n"
|
||||
" void testErrorPrivateAssignment() {\n"
|
||||
" a_private = 2;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void TestErrorPrivate() {\n"
|
||||
" BaseClass b();\n"
|
||||
" int i = b.a_private;\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void ErrorPrivateAssignment() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.a_private = 2;\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SomeOtherClass {\n"
|
||||
" void testErrorPrivate() {\n"
|
||||
" BaseClass b();\n"
|
||||
" int i = b.a_private;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SomeOtherClass {\n"
|
||||
" void testErrorPrivateAssignment() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.a_private = 1;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue