Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -2429,11 +2429,62 @@ return CombinedResult; } + // This can help producing more detailed warning messages. + if (const auto *ILE = dyn_cast(E)) { + + // FIXME: We can't reason about the individual members of + // the initializer list. What we know is that if it only has + // 1 element, we want to track that element for sure. + // + // E.g.: + // struct S { int *p1, *p2; }; + // + // void foo() { + // int *x = nullptr, *y = nullptr; + // S s{x, y}; <-- We want to track 'x' here and not 'y'. + // At this point the tracked region is 's', + // so the analyzer doesn't know which + // element of the initializer list to track. + // As a result we either track all of them + // or none. + // S s2 = s; + // int i = *s.p1; + // } + if (ILE->getNumInits() == 1) { + track(ILE->getInit(0)); + + return CombinedResult; + } + } + if (const auto *CE = dyn_cast(E)) { - for (auto &&arg : CE->arguments()) - track(arg); - return CombinedResult; + // FIXME: We can't reason about the individual arguments of + // the constructor. What we know is that if it only has + // 1 element, we want to track that element for sure. + // + // E.g.: + // struct S { + // int *p1, *p2; + // S(int *a, int *b) : p1(a), p2(b) {} + // }; + // + // void foo() { + // int *x = nullptr, *y = nullptr; + // S s = S(x, y); <-- We want to track 'x' here and not 'y'. + // At this point the tracked region is 's', + // so the analyzer doesn't know which + // argument of the constructor to track. + // As a result we either track all of them + // or none. + // S s2 = s; + // int i = *s2.p1; + // } + if (CE->getNumArgs() == 1) { + track(CE->getArg(0)); + + return CombinedResult; + } } return {};