diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng
index 0dafccad9..048f6b7d5 100644
--- a/cfg/cppcheck-cfg.rng
+++ b/cfg/cppcheck-cfg.rng
@@ -154,7 +154,7 @@
- (-?[0-9]*[,:])*([-]?[0-9]+)?
+ (-?[0-9]*(\.[0-9]+)?[,:])*([-]?[0-9]+(\.[0-9]+)?)?
diff --git a/cfg/std.cfg b/cfg/std.cfg
index 5a2456bc7..8db8eb5d9 100644
--- a/cfg/std.cfg
+++ b/cfg/std.cfg
@@ -108,6 +108,7 @@
+ -1.0:1.0
@@ -119,6 +120,7 @@
+ -1.0:1.0
@@ -130,6 +132,7 @@
+ -1.0:1.0
@@ -348,6 +351,7 @@
false
+ -1.0:1.0
@@ -359,6 +363,7 @@
false
+ -1.0:1.0
@@ -370,6 +375,7 @@
false
+ -1.0:1.0
diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp
index b17541aa7..22f7570a2 100644
--- a/lib/checkfunctions.cpp
+++ b/lib/checkfunctions.cpp
@@ -32,6 +32,7 @@
#include
#include
+#include
#include
#include
@@ -119,9 +120,9 @@ void CheckFunctions::invalidFunctionUsage()
invalidFunctionArgBoolError(argtok, functionToken->str(), argnr);
// Are the values 0 and 1 valid?
- else if (!mSettings->library.isargvalid(functionToken, argnr, 0))
+ else if (!mSettings->library.isargvalid(functionToken, argnr, static_cast(0)))
invalidFunctionArgError(argtok, functionToken->str(), argnr, nullptr, mSettings->library.validarg(functionToken, argnr));
- else if (!mSettings->library.isargvalid(functionToken, argnr, 1))
+ else if (!mSettings->library.isargvalid(functionToken, argnr, static_cast(1)))
invalidFunctionArgError(argtok, functionToken->str(), argnr, nullptr, mSettings->library.validarg(functionToken, argnr));
}
}
@@ -139,7 +140,7 @@ void CheckFunctions::invalidFunctionArgError(const Token *tok, const std::string
else
errmsg << "Invalid $symbol() argument nr " << argnr << '.';
if (invalidValue)
- errmsg << " The value is " << invalidValue->intvalue << " but the valid values are '" << validstr << "'.";
+ errmsg << " The value is " << std::setprecision(10) << (invalidValue->isIntValue() ? invalidValue->intvalue : invalidValue->floatValue) << " but the valid values are '" << validstr << "'.";
else
errmsg << " The value is 0 or 1 (boolean) but the valid values are '" << validstr << "'.";
if (invalidValue)
@@ -241,11 +242,6 @@ void CheckFunctions::checkMathFunctions()
}
}
- // acos( x ), asin( x ) where x is defined for interval [-1,+1], but not beyond
- else if (Token::Match(tok, "acos|acosl|acosf|asin|asinf|asinl ( %num% )")) {
- if (std::fabs(MathLib::toDoubleNumber(tok->strAt(2))) > 1.0)
- mathfunctionCallWarning(tok);
- }
// sqrt( x ): if x is negative the result is undefined
else if (Token::Match(tok, "sqrt|sqrtf|sqrtl ( %num% )")) {
if (MathLib::isNegative(tok->strAt(2)))
diff --git a/lib/library.cpp b/lib/library.cpp
index 22cd75f62..353f3e8e4 100644
--- a/lib/library.cpp
+++ b/lib/library.cpp
@@ -43,6 +43,18 @@ static std::vector getnames(const char *names)
return ret;
}
+static void gettokenlistfromvalid(const std::string& valid, TokenList& tokenList)
+{
+ std::istringstream istr(valid + ',');
+ tokenList.createTokens(istr);
+ for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
+ if (Token::Match(tok,"- %num%")) {
+ tok->str("-" + tok->strAt(1));
+ tok->deleteNext();
+ }
+ }
+}
+
Library::Library() : mAllocId(0)
{
}
@@ -578,19 +590,33 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
const char *p = argnode->GetText();
bool error = false;
bool range = false;
+ bool has_dot = false;
+
+ if (!p)
+ return Error(BAD_ATTRIBUTE_VALUE, "\"\"");
+
+ error = *p == '.';
for (; *p; p++) {
if (std::isdigit(*p))
error |= (*(p+1) == '-');
- else if (*p == ':')
- error |= range;
+ else if (*p == ':') {
+ error |= range | (*(p+1) == '.');
+ range = true;
+ has_dot = false;
+ }
else if (*p == '-')
error |= (!std::isdigit(*(p+1)));
- else if (*p == ',')
+ else if (*p == ',') {
range = false;
+ error |= *(p+1) == '.';
+ has_dot = false;
+ }
+ else if (*p == '.') {
+ error |= has_dot | (!std::isdigit(*(p+1)));
+ has_dot = true;
+ }
else
error = true;
-
- range |= (*p == ':');
}
if (error)
return Error(BAD_ATTRIBUTE_VALUE, argnode->GetText());
@@ -705,15 +731,10 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg
const ArgumentChecks *ac = getarg(ftok, argnr);
if (!ac || ac->valid.empty())
return true;
+ else if (ac->valid.find('.') != std::string::npos)
+ return isargvalid(ftok, argnr, static_cast(argvalue));
TokenList tokenList(nullptr);
- std::istringstream istr(ac->valid + ',');
- tokenList.createTokens(istr);
- for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
- if (Token::Match(tok,"- %num%")) {
- tok->str("-" + tok->strAt(1));
- tok->deleteNext();
- }
- }
+ gettokenlistfromvalid(ac->valid, tokenList);
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
if (tok->isNumber() && argvalue == MathLib::toLongNumber(tok->str()))
return true;
@@ -727,6 +748,24 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg
return false;
}
+bool Library::isargvalid(const Token *ftok, int argnr, double argvalue) const
+{
+ const ArgumentChecks *ac = getarg(ftok, argnr);
+ if (!ac || ac->valid.empty())
+ return true;
+ TokenList tokenList(nullptr);
+ gettokenlistfromvalid(ac->valid, tokenList);
+ for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
+ if (Token::Match(tok, "%num% : %num%") && argvalue >= MathLib::toDoubleNumber(tok->str()) && argvalue <= MathLib::toDoubleNumber(tok->strAt(2)))
+ return true;
+ if (Token::Match(tok, "%num% : ,") && argvalue >= MathLib::toDoubleNumber(tok->str()))
+ return true;
+ if ((!tok->previous() || tok->previous()->str() == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toDoubleNumber(tok->strAt(1)))
+ return true;
+ }
+ return false;
+}
+
std::string Library::getFunctionName(const Token *ftok, bool *error) const
{
if (!ftok) {
diff --git a/lib/library.h b/lib/library.h
index 378075bca..6546e0718 100644
--- a/lib/library.h
+++ b/lib/library.h
@@ -301,6 +301,7 @@ public:
}
bool isargvalid(const Token *ftok, int argnr, const MathLib::bigint argvalue) const;
+ bool isargvalid(const Token *ftok, int argnr, double argvalue) const;
const std::string& validarg(const Token *ftok, int argnr) const {
const ArgumentChecks *arg = getarg(ftok, argnr);
diff --git a/lib/token.cpp b/lib/token.cpp
index d6af64e74..c4632390f 100644
--- a/lib/token.cpp
+++ b/lib/token.cpp
@@ -1497,7 +1497,8 @@ const ValueFlow::Value * Token::getInvalidValue(const Token *ftok, unsigned int
const ValueFlow::Value *ret = nullptr;
std::list::const_iterator it;
for (it = mValues->begin(); it != mValues->end(); ++it) {
- if (it->isIntValue() && !settings->library.isargvalid(ftok, argnr, it->intvalue)) {
+ if ((it->isIntValue() && !settings->library.isargvalid(ftok, argnr, it->intvalue)) ||
+ (it->isFloatValue() && !settings->library.isargvalid(ftok, argnr, it->floatValue))) {
if (!ret || ret->isInconclusive() || (ret->condition && !it->isInconclusive()))
ret = &(*it);
if (!ret->isInconclusive() && !ret->condition)
diff --git a/man/manual.docbook b/man/manual.docbook
index 4fed1f6be..c4e14108a 100644
--- a/man/manual.docbook
+++ b/man/manual.docbook
@@ -1498,7 +1498,8 @@ Checking range.c...
-10:20 => all values between -10 and 20 are valid
:0 => all values that are less or equal to 0 are valid
0: => all values that are greater or equal to 0 are valid
-0,2:32 => the value 0 and all values between 2 and 32 are valid
+0,2:32 => the value 0 and all values between 2 and 32 are valid
+-1.5:5.6 => all values between -1.5 and 5.6 are valid
diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp
index fb4936bec..cdc6cacb0 100644
--- a/test/testfunctions.cpp
+++ b/test/testfunctions.cpp
@@ -604,9 +604,9 @@ private:
" std::cout << acosf(1.1) << std::endl;\n"
" std::cout << acosl(1.1) << std::endl;\n"
"}");
- ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 1.1 to acos() leads to implementation-defined result.\n"
- "[test.cpp:4]: (warning) Passing value 1.1 to acosf() leads to implementation-defined result.\n"
- "[test.cpp:5]: (warning) Passing value 1.1 to acosl() leads to implementation-defined result.\n", errout.str());
+ ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
check("void foo()\n"
"{\n"
@@ -614,9 +614,9 @@ private:
" std::cout << acosf(-1.1) << std::endl;\n"
" std::cout << acosl(-1.1) << std::endl;\n"
"}");
- ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.1 to acos() leads to implementation-defined result.\n"
- "[test.cpp:4]: (warning) Passing value -1.1 to acosf() leads to implementation-defined result.\n"
- "[test.cpp:5]: (warning) Passing value -1.1 to acosl() leads to implementation-defined result.\n", errout.str());
+ ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
}
void mathfunctionCall_asin() {
@@ -665,9 +665,9 @@ private:
" std::cout << asinf(1.1) << std::endl;\n"
" std::cout << asinl(1.1) << std::endl;\n"
"}");
- ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 1.1 to asin() leads to implementation-defined result.\n"
- "[test.cpp:4]: (warning) Passing value 1.1 to asinf() leads to implementation-defined result.\n"
- "[test.cpp:5]: (warning) Passing value 1.1 to asinl() leads to implementation-defined result.\n", errout.str());
+ ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
check("void foo()\n"
"{\n"
@@ -675,9 +675,9 @@ private:
" std::cout << asinf(-1.1) << std::endl;\n"
" std::cout << asinl(-1.1) << std::endl;\n"
"}");
- ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.1 to asin() leads to implementation-defined result.\n"
- "[test.cpp:4]: (warning) Passing value -1.1 to asinf() leads to implementation-defined result.\n"
- "[test.cpp:5]: (warning) Passing value -1.1 to asinl() leads to implementation-defined result.\n", errout.str());
+ ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
+ "[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
}
void mathfunctionCall_pow() {
diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp
index 1fedf4393..590375bef 100644
--- a/test/testlibrary.cpp
+++ b/test/testlibrary.cpp
@@ -282,6 +282,11 @@ private:
" 1:5,8\n"
" -1,5\n"
" :1,5\n"
+ " 1.5:\n"
+ " -6.7:-5.5,-3.3:-2.7\n"
+ " 0.0:\n"
+ " :2.0\n"
+ " 0.0\n"
" \n"
"";
@@ -289,41 +294,125 @@ private:
ASSERT_EQUALS(true, Library::OK == (readLibrary(library, xmldata)).errorcode);
TokenList tokenList(nullptr);
- std::istringstream istr("foo(a,b,c,d,e);");
+ std::istringstream istr("foo(a,b,c,d,e,f,g,h,i,j);");
tokenList.createTokens(istr);
tokenList.front()->next()->astOperand1(tokenList.front());
// 1-
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, -10));
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, 0));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 1));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 10));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, static_cast(-10)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, -10.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, static_cast(0)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 1, 0.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, static_cast(1)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 1.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, static_cast(10)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 1, 10.0));
// -7-0
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -10));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -7));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -3));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, 0));
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, 1));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, static_cast(-10)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -10.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -7.5));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, -7.1));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, static_cast(-7)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -7.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, static_cast(-3)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -3.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, -3.5));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, static_cast(0)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 2, 0.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, 0.5));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, static_cast(1)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 2, 1.0));
// 1-5,8
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 0));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 1));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 3));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 5));
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 6));
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 7));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 8));
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 9));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast(0)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 0.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast(1)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 1.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast(3)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 3.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast(5)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, 5.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast(6)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 6.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast(7)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 7.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 3, static_cast(8)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 8.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, static_cast(9)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 3, 9.0));
// -1,5
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, -10));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 4, -1));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, static_cast(-10)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, -10.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 4, static_cast(-1)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, -1.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, 5.000001));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 4, 5.5));
// :1,5
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, -10));
- ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, 1));
- ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 5, 2));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, static_cast(-10)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, -10.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, static_cast(1)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 5, 1.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 5, static_cast(2)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 5, 2.0));
+
+ // 1.5:
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, static_cast(0)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, 0.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, static_cast(1)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 6, 1.499999));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 6, 1.5));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 6, static_cast(2)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 6, static_cast(10)));
+
+ // -6.7:-5.5,-3.3:-2.7
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast(-7)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -7.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -6.7000001));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -6.7));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, static_cast(-6)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -6.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -5.5));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -5.4999999));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -3.3000001));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -3.3));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, static_cast(-3)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -3.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 7, -2.7));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -2.6999999));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast(-2)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, -2.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast(0)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, 0.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast(3)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, 3.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, static_cast(6)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 7, 6.0));
+
+ // 0.0:
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 8, static_cast(-1)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 8, -1.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 8, -0.00000001));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, static_cast(0)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, 0.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, 0.000000001));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, static_cast(1)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 8, 1.0));
+
+ // :2.0
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, static_cast(-1)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, -1.0));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, static_cast(2)));
+ ASSERT_EQUALS(true, library.isargvalid(tokenList.front(), 9, 2.0));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 9, 2.00000001));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 9, static_cast(200)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 9, 200.0));
+
+ // 0.0
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 10, static_cast(0)));
+ ASSERT_EQUALS(false, library.isargvalid(tokenList.front(), 10, 0.0));
}
void function_arg_minsize() const {
@@ -724,54 +813,105 @@ private:
}
}
+ void loadLibError(const char xmldata [], Library::ErrorCode errorcode, const char* file, unsigned line) const {
+ Library library;
+ assertEquals(file, line, errorcode, readLibrary(library, xmldata).errorcode);
+ }
+
+#define LOADLIBERROR(xmldata, errorcode) loadLibError(xmldata, errorcode, __FILE__, __LINE__)
+#define LOADLIB_ERROR_INVALID_RANGE(valid) LOADLIBERROR("\n" \
+ "\n" \
+ "\n" \
+ "\n" \
+ "" valid "\n" \
+ "\n" \
+ "\n" \
+ "", \
+ Library::BAD_ATTRIBUTE_VALUE)
+
void loadLibErrors() const {
- // UNKNOWN_ELEMENT
- {
- const char xmldata [] = "\n"
- "\n"
- " \n"
- "";
- Library library;
- ASSERT_EQUALS(Library::UNKNOWN_ELEMENT, readLibrary(library, xmldata).errorcode);
- }
- // MISSING_ATTRIBUTE
- {
- // #define without attributes
- {
- const char xmldata [] = "\n"
- "\n"
- " \n" // no attributes provided at all
- "";
- Library library;
- ASSERT_EQUALS(Library::MISSING_ATTRIBUTE, readLibrary(library, xmldata).errorcode);
- }
- // #define with name but without value
- {
- const char xmldata [] = "\n"
- "\n"
- " \n" // no value provided
- "";
- Library library;
- ASSERT_EQUALS(Library::MISSING_ATTRIBUTE, readLibrary(library, xmldata).errorcode);
- }
- // #define with value but without a name
- {
- const char xmldata [] = "\n"
- "\n"
- " \n" // no name provided
- "";
- Library library;
- ASSERT_EQUALS(Library::MISSING_ATTRIBUTE, readLibrary(library, xmldata).errorcode);
- }
- }
- // UNSUPPORTED_FORMAT
- {
- const char xmldata [] = "\n"
- "\n"
- "";
- Library library;
- ASSERT_EQUALS(Library::UNSUPPORTED_FORMAT, readLibrary(library, xmldata).errorcode);
- }
+
+ LOADLIBERROR("\n"
+ "\n"
+ " \n"
+ "",
+ Library::UNKNOWN_ELEMENT);
+
+ // #define without attributes
+ LOADLIBERROR("\n"
+ "\n"
+ " \n" // no attributes provided at all
+ "",
+ Library::MISSING_ATTRIBUTE);
+
+ // #define with name but without value
+ LOADLIBERROR("\n"
+ "\n"
+ " \n" // no value provided
+ "",
+ Library::MISSING_ATTRIBUTE);
+
+ LOADLIBERROR("\n"
+ "\n"
+ " \n" // no name provided
+ "",
+ Library::MISSING_ATTRIBUTE);
+
+ LOADLIBERROR("\n"
+ "\n"
+ "",
+ Library::UNSUPPORTED_FORMAT);
+
+ // empty range
+ LOADLIB_ERROR_INVALID_RANGE("");
+
+ // letter as range
+ LOADLIB_ERROR_INVALID_RANGE("a");
+
+ // letter and number as range
+ LOADLIB_ERROR_INVALID_RANGE("1a");
+
+ // digit followed by dash
+ LOADLIB_ERROR_INVALID_RANGE("0:2-1");
+
+ // single dash
+ LOADLIB_ERROR_INVALID_RANGE("-");
+
+ // range with multiple colons
+ LOADLIB_ERROR_INVALID_RANGE("1:2:3");
+
+ // extra dot
+ LOADLIB_ERROR_INVALID_RANGE("1.0.0:10");
+
+ // consecutive dots
+ LOADLIB_ERROR_INVALID_RANGE("1..0:10");
+
+ // dot followed by dash
+ LOADLIB_ERROR_INVALID_RANGE("1.-0:10");
+
+ // dot without preceding number
+ LOADLIB_ERROR_INVALID_RANGE(".5:10");
+
+ // dash followed by dot
+ LOADLIB_ERROR_INVALID_RANGE("-.5:10");
+
+ // colon followed by dot without preceding number
+ LOADLIB_ERROR_INVALID_RANGE("0:.5");
+
+ // colon followed by dash followed by dot
+ LOADLIB_ERROR_INVALID_RANGE("-10:-.5");
+
+ // dot not followed by number
+ LOADLIB_ERROR_INVALID_RANGE("1:5.");
+
+ // dot not followed by number
+ LOADLIB_ERROR_INVALID_RANGE("1.:5");
+
+ // dot followed by comma
+ LOADLIB_ERROR_INVALID_RANGE("1:5.,6:10");
+
+ // comma followed by dot
+ LOADLIB_ERROR_INVALID_RANGE("-10:0,.5:");
}
};