From: Gabor Marton Date: Thu, 4 Jul 2019 11:39:00 +0000 (+0000) Subject: [CTU] Add support for virtual functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48feb60c74ce8448a8f85f70bb7d6e1f32445c9e;p=clang [CTU] Add support for virtual functions Reviewers: Szelethus, xazax.hun Subscribers: rnkovacs, dkrupp, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D63920 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@365133 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 81a9ee4d90..a5f7500e63 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -766,8 +766,11 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { // Does the decl that we found have an implementation? const FunctionDecl *Definition; - if (!Result->hasBody(Definition)) + if (!Result->hasBody(Definition)) { + if (!DynType.canBeASubClass()) + return AnyFunctionCall::getRuntimeDefinition(); return {}; + } // We found a definition. If we're not sure that this devirtualization is // actually what will happen at runtime, make sure to provide the region so diff --git a/test/Analysis/Inputs/ctu-other.cpp b/test/Analysis/Inputs/ctu-other.cpp index de7d064135..a9ff6b5a93 100644 --- a/test/Analysis/Inputs/ctu-other.cpp +++ b/test/Analysis/Inputs/ctu-other.cpp @@ -38,6 +38,7 @@ int embed_cls::fecl(int x) { class mycls { public: int fcl(int x); + virtual int fvcl(int x); static int fscl(int x); class embed_cls2 { @@ -49,6 +50,9 @@ public: int mycls::fcl(int x) { return x + 5; } +int mycls::fvcl(int x) { + return x + 7; +} int mycls::fscl(int x) { return x + 6; } @@ -56,6 +60,15 @@ int mycls::embed_cls2::fecl2(int x) { return x - 11; } +class derived : public mycls { +public: + virtual int fvcl(int x) override; +}; + +int derived::fvcl(int x) { + return x + 8; +} + namespace chns { int chf2(int x); diff --git a/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt b/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt index 57f4194831..3df181b29d 100644 --- a/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt +++ b/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt @@ -3,8 +3,10 @@ c:@N@myns@N@embed_ns@F@fens#I# ctu-other.cpp.ast c:@F@g#I# ctu-other.cpp.ast c:@S@mycls@F@fscl#I#S ctu-other.cpp.ast c:@S@mycls@F@fcl#I# ctu-other.cpp.ast +c:@S@mycls@F@fvcl#I# ctu-other.cpp.ast c:@N@myns@S@embed_cls@F@fecl#I# ctu-other.cpp.ast c:@S@mycls@S@embed_cls2@F@fecl2#I# ctu-other.cpp.ast +c:@S@derived@F@fvcl#I# ctu-other.cpp.ast c:@F@f#I# ctu-other.cpp.ast c:@N@myns@F@fns#I# ctu-other.cpp.ast c:@F@h#I# ctu-other.cpp.ast diff --git a/test/Analysis/ctu-main.cpp b/test/Analysis/ctu-main.cpp index a5de18bb3e..1cb0d4a9d7 100644 --- a/test/Analysis/ctu-main.cpp +++ b/test/Analysis/ctu-main.cpp @@ -45,6 +45,7 @@ public: class mycls { public: int fcl(int x); + virtual int fvcl(int x); static int fscl(int x); class embed_cls2 { @@ -53,6 +54,11 @@ public: }; }; +class derived : public mycls { +public: + virtual int fvcl(int x) override; +}; + namespace chns { int chf1(int x); } @@ -98,6 +104,14 @@ union U { }; extern U extU; +void test_virtual_functions(mycls* obj) { + // The dynamic type is known. + clang_analyzer_eval(mycls().fvcl(1) == 8); // expected-warning{{TRUE}} + clang_analyzer_eval(derived().fvcl(1) == 9); // expected-warning{{TRUE}} + // We cannot decide about the dynamic type. + clang_analyzer_eval(obj->fvcl(1) == 8); // expected-warning{{FALSE}} expected-warning{{TRUE}} +} + int main() { clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}} clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}} @@ -116,7 +130,7 @@ int main() { clang_analyzer_eval(fun_using_anon_struct(8) == 8); // expected-warning{{TRUE}} clang_analyzer_eval(other_macro_diag(1) == 1); // expected-warning{{TRUE}} - // expected-warning@Inputs/ctu-other.cpp:80{{REACHABLE}} + // expected-warning@Inputs/ctu-other.cpp:93{{REACHABLE}} MACRODIAG(); // expected-warning{{REACHABLE}} clang_analyzer_eval(extInt == 2); // expected-warning{{TRUE}}