From: Benjamin Kramer Date: Thu, 21 Aug 2014 10:25:03 +0000 (+0000) Subject: [analyzer] Don't warn on virtual calls in ctors to final methods. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ab704bc4c73b7638b08d7d539b116bbeffb3373a;p=clang [analyzer] Don't warn on virtual calls in ctors to final methods. The call will never go to a more derived class, but that's intentional in those cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216167 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp index f8f5cf93ca..7e1fc1eb54 100644 --- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -146,15 +146,22 @@ void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) { if (CME->getQualifier()) callIsNonVirtual = true; - // Elide analyzing the call entirely if the base pointer is not 'this'. - if (Expr *base = CME->getBase()->IgnoreImpCasts()) + if (Expr *base = CME->getBase()->IgnoreImpCasts()) { + // Elide analyzing the call entirely if the base pointer is not 'this'. if (!isa(base)) return; + + // If the most derived class is marked final, we know that now subclass + // can override this member. + if (base->getBestDynamicClassType()->hasAttr()) + callIsNonVirtual = true; + } } // Get the callee. const CXXMethodDecl *MD = dyn_cast(CE->getDirectCallee()); - if (MD && MD->isVirtual() && !callIsNonVirtual) + if (MD && MD->isVirtual() && !callIsNonVirtual && !MD->hasAttr() && + !MD->getParent()->hasAttr()) ReportVirtualCall(CE, MD->isPure()); Enqueue(CE); diff --git a/test/Analysis/virtualcall.cpp b/test/Analysis/virtualcall.cpp index c3319b0ac5..8ce1d4103b 100644 --- a/test/Analysis/virtualcall.cpp +++ b/test/Analysis/virtualcall.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.VirtualCall -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.VirtualCall -analyzer-store region -verify -std=c++11 %s class A { public: @@ -46,10 +46,31 @@ C::C() { f(foo()); // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}} } +class D : public B { +public: + D() { + foo(); // no-warning + } + ~D() { bar(); } + int foo() final; + void bar() final { foo(); } // no-warning +}; + +class E final : public B { +public: + E() { + foo(); // no-warning + } + ~E() { bar(); } + int foo() override; +}; + int main() { A *a; B *b; C *c; + D *d; + E *e; } #include "virtualcall.h"