diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporter.cpp | 12 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 13 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 18 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 95 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 7 |
5 files changed, 133 insertions, 12 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 4a5d25fc56345..dc284888eb032 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -885,8 +885,12 @@ static bool GenerateMinimalPathDiagnostic( if (NextNode) { // Add diagnostic pieces from custom visitors. BugReport *R = PDB.getBugReport(); + llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet; for (auto &V : visitors) { if (auto p = V->VisitNode(N, NextNode, PDB, *R)) { + if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) + continue; + updateStackPiecesWithMessage(*p, CallStack); PD.getActivePath().push_front(std::move(p)); } @@ -1584,8 +1588,12 @@ static bool GenerateExtensivePathDiagnostic( // Add pieces from custom visitors. BugReport *R = PDB.getBugReport(); + llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet; for (auto &V : visitors) { if (auto p = V->VisitNode(N, NextNode, PDB, *R)) { + if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) + continue; + const PathDiagnosticLocation &Loc = p->getLocation(); EB.addEdge(Loc, true); updateStackPiecesWithMessage(*p, CallStack); @@ -1879,8 +1887,12 @@ static bool GenerateAlternateExtensivePathDiagnostic( continue; // Add pieces from custom visitors. + llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet; for (auto &V : visitors) { if (auto p = V->VisitNode(N, NextNode, PDB, *report)) { + if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) + continue; + addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); updateStackPiecesWithMessage(*p, CallStack); PD.getActivePath().push_front(std::move(p)); diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 7304d789431ee..972f4c5f3da2e 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -985,12 +985,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, if (!S || !N) return false; - if (const Expr *Ex = dyn_cast<Expr>(S)) { - Ex = Ex->IgnoreParenCasts(); - const Expr *PeeledEx = peelOffOuterExpr(Ex, N); - if (Ex != PeeledEx) - S = PeeledEx; - } + if (const Expr *Ex = dyn_cast<Expr>(S)) + S = peelOffOuterExpr(Ex, N); const Expr *Inner = nullptr; if (const Expr *Ex = dyn_cast<Expr>(S)) { @@ -1142,9 +1138,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, else RVal = state->getSVal(L->getRegion()); - const MemRegion *RegionRVal = RVal.getAsRegion(); report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion())); + if (Optional<KnownSVal> KV = RVal.getAs<KnownSVal>()) + report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>( + *KV, L->getRegion(), EnableNullFPSuppression)); + const MemRegion *RegionRVal = RVal.getAsRegion(); if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { report.markInteresting(RegionRVal); report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>( diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 03e0095d0e837..dad93111966f4 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -14,6 +14,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/ParentMap.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" @@ -267,6 +268,23 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, } // FALLTHROUGH case CXXConstructExpr::CK_NonVirtualBase: + // In C++17, classes with non-virtual bases may be aggregates, so they would + // be initialized as aggregates without a constructor call, so we may have + // a base class constructed directly into an initializer list without + // having the derived-class constructor call on the previous stack frame. + // Initializer lists may be nested into more initializer lists that + // correspond to surrounding aggregate initializations. + // FIXME: For now this code essentially bails out. We need to find the + // correct target region and set it. + // FIXME: Instead of relying on the ParentMap, we should have the + // trigger-statement (InitListExpr in this case) passed down from CFG or + // otherwise always available during construction. + if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) { + MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); + Target = MRMgr.getCXXTempObjectRegion(CE, LCtx); + break; + } + // FALLTHROUGH case CXXConstructExpr::CK_Delegating: { const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 9b820e81e374f..ebf1487d4bfc1 100644 --- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -91,6 +91,9 @@ public: // Rewrite the file specified by FID with HTML formatting. void RewriteFile(Rewriter &R, const SourceManager& SMgr, const PathPieces& path, FileID FID); + + /// \return Javascript for navigating the HTML report using j/k keys. + std::string generateKeyboardNavigationJavascript(); }; } // end anonymous namespace @@ -337,6 +340,9 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R, int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber(); int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber(); + R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), + generateKeyboardNavigationJavascript()); + // Add the name of the file as an <h1> tag. { std::string s; @@ -378,8 +384,14 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R, os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n"; } - os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n" - "<h3>Annotated Source Code</h3>\n"; + os << R"<<<( +</table> +<!-- REPORTSUMMARYEXTRA --> +<h3>Annotated Source Code</h3> +<p><span class='macro'>[?] + <span class='expansion'>Use j/k keys for keyboard navigation</span> +</span></p> +)<<<"; R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str()); } @@ -777,3 +789,82 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID, html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd); } + +std::string HTMLDiagnostics::generateKeyboardNavigationJavascript() { + return R"<<<( +<script type='text/javascript'> +var digitMatcher = new RegExp("[0-9]+"); + +document.addEventListener("DOMContentLoaded", function() { + document.querySelectorAll(".PathNav > a").forEach( + function(currentValue, currentIndex) { + var hrefValue = currentValue.getAttribute("href"); + currentValue.onclick = function() { + scrollTo(document.querySelector(hrefValue)); + return false; + }; + }); +}); + +var findNum = function() { + var s = document.querySelector(".selected"); + if (!s || s.id == "EndPath") { + return 0; + } + var out = parseInt(digitMatcher.exec(s.id)[0]); + return out; +}; + +var scrollTo = function(el) { + document.querySelectorAll(".selected").forEach(function(s) { + s.classList.remove("selected"); + }); + el.classList.add("selected"); + window.scrollBy(0, el.getBoundingClientRect().top - + (window.innerHeight / 2)); +} + +var move = function(num, up, numItems) { + if (num == 1 && up || num == numItems - 1 && !up) { + return 0; + } else if (num == 0 && up) { + return numItems - 1; + } else if (num == 0 && !up) { + return 1 % numItems; + } + return up ? num - 1 : num + 1; +} + +var numToId = function(num) { + if (num == 0) { + return document.getElementById("EndPath") + } + return document.getElementById("Path" + num); +}; + +var navigateTo = function(up) { + var numItems = document.querySelectorAll(".line > .msg").length; + var currentSelected = findNum(); + var newSelected = move(currentSelected, up, numItems); + var newEl = numToId(newSelected, numItems); + + // Scroll element into center. + scrollTo(newEl); +}; + +window.addEventListener("keydown", function (event) { + if (event.defaultPrevented) { + return; + } + if (event.key == "j") { + navigateTo(/*up=*/false); + } else if (event.key == "k") { + navigateTo(/*up=*/true); + } else { + return; + } + event.preventDefault(); +}, true); +</script> + )<<<"; +} diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 7f2a481c6b0d3..e2e69bb28ec22 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2132,9 +2132,10 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B, NewB = bind(NewB, loc::MemRegionVal(ER), *VI); } - // If the init list is shorter than the array length, set the - // array default value. - if (Size.hasValue() && i < Size.getValue()) + // If the init list is shorter than the array length (or the array has + // variable length), set the array default value. Values that are already set + // are not overwritten. + if (!Size.hasValue() || i < Size.getValue()) NewB = setImplicitDefaultValue(NewB, R, ElementTy); return NewB; |