summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp13
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp18
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp95
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp7
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;