diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -504,6 +504,29 @@ if (VisitedAsTopLevel.count(D)) return true; + // Skip analysis of inheriting constructors as top-level functions. These + // constructors don't even have a body written down in the code, so even if + // we find a bug, we won't be able to display it. + // + // Also, we cannot model the parameters. CXXInheritedCtorInitExpr doesn't + // take arguments and doesn't model parameter initialization because there is + // none: the arguments in the outer CXXConstructExpr directly initialize the + // parameters of the base class constructor, and no copies are made. (Making + // a copy of the parameter is incorrect, at least if it's done in an + // observable way.) The derived class constructor doesn't even exist in the + // formal model. + // E.g., in: + // + // struct X { X *p = this; ~X() {} }; + // struct A { A(X x) : b(x.p == &x) {} bool b; }; + // struct B : A { using A::A; }; + // B b = X{}; + // + // ... b.b is initialized to true. + if (const auto *CD = dyn_cast(D)) + if (CD->isInheritingConstructor()) + return true; + // We want to re-analyse the functions as top level in the following cases: // - The 'init' methods should be reanalyzed because // ObjCNonNilReturnValueChecker assumes that '[super init]' never returns diff --git a/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp b/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp --- a/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp +++ b/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp @@ -57,3 +57,19 @@ clang_analyzer_eval(b.z == 3); // expected-warning{{TRUE}} } } // namespace arguments_with_constructors + +namespace inherited_constructor_crash { +class a { +public: + a(int); +}; +struct b : a { + using a::a; // Ihnerited ctor. +}; +void c() { + int d; + // This construct expr utilizes the inherited ctor. + // Note that d must be uninitialized to cause the crash. + (b(d)); // expected-warning{{1st function call argument is an uninitialized value}} +} +} // namespace inherited_constructor_crash diff --git a/clang/test/Analysis/cxx-inherited-ctor-is-skipped-as-top-level.cpp b/clang/test/Analysis/cxx-inherited-ctor-is-skipped-as-top-level.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Analysis/cxx-inherited-ctor-is-skipped-as-top-level.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-display-progress %s 2>&1 | FileCheck %s + +// Test that inheriting constructors are not analyzed as top-level functions. + +// CHECK: ANALYZE (Path, Inline_Regular): {{.*}} c() +// CHECK: ANALYZE (Path, Inline_Regular): {{.*}} a::a(int) +// CHECK-NOT: ANALYZE (Path, Inline_Regular): {{.*}} b::a(int) + +class a { +public: + a(int) {} +}; +struct b : a { + using a::a; // Ihnerited ctor. +}; +void c() { + int d; + (b(d)); + (a(d)); +}