diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 703796682..c5981cb53 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2468,8 +2468,9 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member auto hasOverloadedMemberAccess = [](const Token* end, const Scope* scope) -> bool { if (!end || !scope || !Token::simpleMatch(end->astParent(), ".")) return false; - auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [](const Function& f) { - return f.isConst() && f.name() == "operator."; + const std::string op = "operator" + end->astParent()->originalName(); + auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [&op](const Function& f) { + return f.isConst() && f.name() == op; }); if (it == scope->functionList.end() || !it->retType || !it->retType->classScope) return false; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 41aa8456f..41d99055f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -4396,8 +4396,7 @@ const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType // check for matching return parameters while (!Token::Match(temp1, "virtual|public:|private:|protected:|{|}|;")) { if (temp1->str() != temp2->str() && - !(temp1->str() == derivedFromType->name() && - temp2->str() == baseType->name())) { + !(temp1->type() && temp2->type() && temp2->type()->isDerivedFrom(temp1->type()->name()))) { match = false; break; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 753532850..e06f58023 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9778,7 +9778,7 @@ void Tokenizer::simplifyOperatorName() if (par->str() == "," && !op.empty()) break; if (!(Token::Match(par, "<|>") && !op.empty())) { - op += par->str(); + op += par->str() == "." ? par->originalName() : par->str(); par = par->next(); done = false; } diff --git a/test/testclass.cpp b/test/testclass.cpp index c7470314d..add011fe4 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -692,6 +692,17 @@ private: " T() : S::T() {}\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + checkDuplInheritedMembers("struct S {};\n" // #11827 + "struct SPtr {\n" + " virtual S* operator->() const { return p; }\n" + " S* p = nullptr;\n" + "};\n" + "struct T : public S {};\n" + "struct TPtr : public SPtr {\n" + " T* operator->() const { return (T*)p; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } #define checkCopyConstructor(code) checkCopyConstructor_(code, __FILE__, __LINE__) @@ -8349,6 +8360,18 @@ private: " friend T f();\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + checkOverride("struct S {};\n" // #11827 + "struct SPtr {\n" + " virtual S* operator->() const { return p; }\n" + " S* p = nullptr;\n" + "};\n" + "struct T : public S {};\n" + "struct TPtr : public SPtr {\n" + " T* operator->() const { return (T*)p; }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:8]: (style) The function 'operator->' overrides a function in a base class but is not marked with a 'override' specifier.\n", + errout.str()); } void overrideCVRefQualifiers() { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 0ff011e86..8facb72b7 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -4950,7 +4950,7 @@ private: const char code[] = "void f() {" "static_cast(xResult.operator->())->GetMatrix();" "}"; - const char result[] = "void f ( ) { static_cast < ScToken * > ( xResult . operator. ( ) ) . GetMatrix ( ) ; }"; + const char result[] = "void f ( ) { static_cast < ScToken * > ( xResult . operator-> ( ) ) . GetMatrix ( ) ; }"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); }