Index: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp @@ -715,6 +715,13 @@ } return C.getNoteTag([Text, Name, ContReg](BugReport &BR) -> std::string { + const auto *PSBR = dyn_cast(&BR); + if (!PSBR) + return ""; + + if (!PSBR->isInteresting(ContReg)) + return ""; + SmallString<256> Msg; llvm::raw_svector_ostream Out(Msg); Out << "Container " << (!Name.empty() ? ("'" + Name.str() + "' ") : "" ) Index: clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp @@ -52,6 +52,9 @@ bool evalCall(const CallEvent &Call, CheckerContext &C) const; }; +bool contains(const SourceManager &SM, const SourceRange Outer, + SourceRange Inner); + } //namespace DebugContainerModeling::DebugContainerModeling() { @@ -92,7 +95,17 @@ if (Field) { State = State->BindExpr(CE, C.getLocationContext(), nonloc::SymbolVal(Field)); - C.addTransition(State); + const auto &SM = C.getSourceManager(); + const NoteTag *InterestingTag = + C.getNoteTag([Cont, CE, &SM](BugReport &BR) -> std::string { + auto *PSBR = dyn_cast(&BR); + if (PSBR && contains(SM, PSBR->getRanges()[0], + CE->getSourceRange())) { + PSBR->markInteresting(Cont); + } + return ""; + }); + C.addTransition(State, InterestingTag); return; } } @@ -129,6 +142,18 @@ return N; } +namespace { + +bool contains(const SourceManager &SM, const SourceRange Outer, + SourceRange Inner) { + SourceLocation OB = Outer.getBegin(), OE = Outer.getEnd(), + IB = Inner.getBegin(), IE = Inner.getEnd(); + return (OB == IB || SM.isBeforeInTranslationUnit(OB, IB)) && + (IE == OE || SM.isBeforeInTranslationUnit(IE, OE)); +} + +} // namespace + void ento::registerDebugContainerModeling(CheckerManager &mgr) { mgr.registerChecker(); } Index: clang/test/Analysis/container-modeling.cpp =================================================================== --- clang/test/Analysis/container-modeling.cpp +++ clang/test/Analysis/container-modeling.cpp @@ -208,7 +208,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(V1), "$V1.begin()"); - V2.push_back(n); // expected-note{{Container 'V2' extended to the right by 1 position}} FIXME: This note should not appear since `V2` is not affected in the "bug" + V2.push_back(n); // no note expected clang_analyzer_express(clang_analyzer_container_begin(V1)); // expected-warning{{$V1.begin()}} // expected-note@-1{{$V1.begin()}} @@ -223,8 +223,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(V1), "$V1.begin()"); clang_analyzer_denote(clang_analyzer_container_begin(V2), "$V2.begin()"); - V1.push_back(n); // expected-note{{Container 'V1' extended to the right by 1 position}} - // expected-note@-1{{Container 'V1' extended to the right by 1 position}} FIXME: This should appear only once since there is only one "bug" where `V1` is affected + V1.push_back(n); // expected-note{{Container 'V1' extended to the right by 1 position}} -- Only once! clang_analyzer_express(clang_analyzer_container_begin(V1)); // expected-warning{{$V1.begin()}} // expected-note@-1{{$V1.begin()}}