From 168db82fd63140b8016d89dad2b1f2b1f43907ce Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 25 Mar 2011 23:02:13 -0400 Subject: [PATCH] better checking of assignment to array element in CheckClass::checkConstFunc --- lib/checkclass.cpp | 9 +-- test/testclass.cpp | 152 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 4 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 9bacbb615..7adcbb623 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1504,10 +1504,11 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Token *tok) } else if (tok1->previous()->str() == "]") { - // TODO: I assume that the assigned variable is a member variable - // don't assume it - isconst = false; - break; + if (isMemberVar(scope, tok1->previous()->link()->previous())) + { + isconst = false; + break; + } } else if (tok1->next()->str() == "this") { diff --git a/test/testclass.cpp b/test/testclass.cpp index 36cfd0069..e34b4ee69 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -176,7 +176,9 @@ private: TEST_CASE(constoperator3); TEST_CASE(constoperator4); TEST_CASE(constincdec); // increment/decrement => non-const + TEST_CASE(constassign); TEST_CASE(constincdecarray); // increment/decrement array element => non-const + TEST_CASE(constassignarray); TEST_CASE(constReturnReference); TEST_CASE(constDelete); // delete member variable => not const TEST_CASE(constLPVOID); // a function that returns LPVOID can't be const @@ -5376,6 +5378,39 @@ private: "};\n"); ASSERT_EQUALS("", errout.str()); + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return ++a; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return --a; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a++; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a--; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + } + + void constassign() + { + checkConst("class Fred {\n" + " int a;\n" + " void nextA() { return a=1; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + checkConst("class Fred {\n" " int a;\n" " void nextA() { return a-=1; }\n" @@ -5399,6 +5434,36 @@ private: " void nextA() { return a/=-2; }\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a=1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a-=1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a+=1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a*=-1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a;\n" + "class Fred {\n" + " void nextA() { return a/=-2; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); } // increment/decrement array element => not const @@ -5427,6 +5492,93 @@ private: " void nextA() { return a[0]--; }\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return ++a[0]; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return --a[0]; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]++; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]--; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + } + + void constassignarray() + { + checkConst("class Fred {\n" + " int a[2];\n" + " void nextA() { return a[0]=1; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + checkConst("class Fred {\n" + " int a[2];\n" + " void nextA() { return a[0]-=1; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + checkConst("class Fred {\n" + " int a[2];\n" + " void nextA() { return a[0]+=1; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + checkConst("class Fred {\n" + " int a[2];\n" + " void nextA() { return a[0]*=-1; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + checkConst("class Fred {\n" + " int a[2];\n" + " void nextA() { return a[0]/=-2; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]=1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]-=1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]+=1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]*=-1; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + + checkConst("int a[2];\n" + "class Fred {\n" + " void nextA() { return a[0]/=-2; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); } // return pointer/reference => not const