r361664 - [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers
Mandeep Singh Grang via cfe-commits
cfe-commits at lists.llvm.org
Fri May 24 12:24:08 PDT 2019
Author: mgrang
Date: Fri May 24 12:24:08 2019
New Revision: 361664
URL: http://llvm.org/viewvc/llvm-project?rev=361664&view=rev
Log:
[Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers
Summary: Added a checker for non-determinism caused by iterating unordered containers like std::unordered_set containing pointer elements.
Reviewers: NoQ, george.karpenkov, whisperity, Szelethus, baloghadamsoftware
Reviewed By: Szelethus
Subscribers: mgorny, xazax.hun, baloghadamsoftware, szepet, rnkovacs, a.sidorin, mikhail.ramalho, donat.nagy, dkrupp, jdoerfert, Charusso, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59279
Added:
cfe/trunk/lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
cfe/trunk/test/Analysis/ptr-iter.cpp
Modified:
cfe/trunk/docs/analyzer/checkers.rst
cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/www/analyzer/alpha_checks.html
Modified: cfe/trunk/docs/analyzer/checkers.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/checkers.rst?rev=361664&r1=361663&r2=361664&view=diff
==============================================================================
--- cfe/trunk/docs/analyzer/checkers.rst (original)
+++ cfe/trunk/docs/analyzer/checkers.rst Fri May 24 12:24:08 2019
@@ -211,8 +211,8 @@ Check for uninitialized values being ret
.. _cplusplus-checkers:
-cpluslus
-^^^^^^^^
+cplusplus
+^^^^^^^^^
C++ Checkers.
@@ -1951,6 +1951,20 @@ Check for out-of-bounds access in string
int y = strlen((char *)&test); // warn
}
+alpha.nondeterminism.PointerIteration (C++)
+"""""""""""""""""""""""""""""""""""""""""""
+Check for non-determinism caused by iterating unordered containers of pointers.
+
+.. code-block:: c
+
+ void test() {
+ int a = 1, b = 2;
+ std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
+
+ for (auto i : UnorderedPtrSet) // warn
+ f(i);
+ }
+
alpha.nondeterminism.PointerSorting (C++)
"""""""""""""""""""""""""""""""""""""""""
Check for non-determinism caused by sorting of pointers.
Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=361664&r1=361663&r2=361664&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Fri May 24 12:24:08 2019
@@ -1340,6 +1340,10 @@ def UnixAPIPortabilityChecker : Checker<
let ParentPackage = NonDeterminismAlpha in {
+def PointerIterationChecker : Checker<"PointerIteration">,
+ HelpText<"Checks for non-determinism caused by iteration of unordered containers of pointers">,
+ Documentation<HasDocumentation>;
+
def PointerSortingChecker : Checker<"PointerSorting">,
HelpText<"Check for non-determinism caused by sorting of pointers">,
Documentation<HasDocumentation>;
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=361664&r1=361663&r2=361664&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Fri May 24 12:24:08 2019
@@ -75,6 +75,7 @@ add_clang_library(clangStaticAnalyzerChe
OSObjectCStyleCast.cpp
PaddingChecker.cpp
PointerArithChecker.cpp
+ PointerIterationChecker.cpp
PointerSortingChecker.cpp
PointerSubChecker.cpp
PthreadLockChecker.cpp
Added: cfe/trunk/lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp?rev=361664&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp Fri May 24 12:24:08 2019
@@ -0,0 +1,100 @@
+//== PointerIterationChecker.cpp ------------------------------- -*- C++ -*--=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines PointerIterationChecker which checks for non-determinism
+// caused due to iteration of unordered containers of pointer elements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+// ID of a node at which the diagnostic would be emitted.
+constexpr llvm::StringLiteral WarnAtNode = "iter";
+
+class PointerIterationChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const;
+};
+
+static void emitDiagnostics(const BoundNodes &Match, const Decl *D,
+ BugReporter &BR, AnalysisManager &AM,
+ const PointerIterationChecker *Checker) {
+ auto *ADC = AM.getAnalysisDeclContext(D);
+
+ const auto *MarkedStmt = Match.getNodeAs<Stmt>(WarnAtNode);
+ assert(MarkedStmt);
+
+ auto Range = MarkedStmt->getSourceRange();
+ auto Location = PathDiagnosticLocation::createBegin(MarkedStmt,
+ BR.getSourceManager(),
+ ADC);
+ std::string Diagnostics;
+ llvm::raw_string_ostream OS(Diagnostics);
+ OS << "Iteration of pointer-like elements "
+ << "can result in non-deterministic ordering";
+
+ BR.EmitBasicReport(ADC->getDecl(), Checker,
+ "Iteration of pointer-like elements", "Non-determinism",
+ OS.str(), Location, Range);
+}
+
+// Assumption: Iteration of ordered containers of pointers is deterministic.
+
+// TODO: Currently, we only check for std::unordered_set. Other unordered
+// containers like std::unordered_map also need to be handled.
+
+// TODO: Currently, we do not check what the for loop does with the iterated
+// pointer values. Not all iterations may cause non-determinism. For example,
+// counting or summing up the elements should not be non-deterministic.
+
+auto matchUnorderedIterWithPointers() -> decltype(decl()) {
+
+ auto UnorderedContainerM = declRefExpr(to(varDecl(hasType(
+ recordDecl(hasName("std::unordered_set")
+ )))));
+
+ auto PointerTypeM = varDecl(hasType(hasCanonicalType(pointerType())));
+
+ auto PointerIterM = stmt(cxxForRangeStmt(
+ hasLoopVariable(PointerTypeM),
+ hasRangeInit(UnorderedContainerM)
+ )).bind(WarnAtNode);
+
+ return decl(forEachDescendant(PointerIterM));
+}
+
+void PointerIterationChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+ auto MatcherM = matchUnorderedIterWithPointers();
+
+ auto Matches = match(MatcherM, *D, AM.getASTContext());
+ for (const auto &Match : Matches)
+ emitDiagnostics(Match, D, BR, AM, this);
+}
+
+} // end of anonymous namespace
+
+void ento::registerPointerIterationChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<PointerIterationChecker>();
+}
+
+bool ento::shouldRegisterPointerIterationChecker(const LangOptions &LO) {
+ return LO.CPlusPlus;
+}
Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h?rev=361664&r1=361663&r2=361664&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h Fri May 24 12:24:08 2019
@@ -846,3 +846,64 @@ namespace std {
template<class BidirIt, class UnaryPredicate>
BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
}
+
+namespace std {
+
+template< class T = void >
+struct less;
+
+template< class T >
+struct allocator;
+
+template< class Key >
+struct hash;
+
+template<
+ class Key,
+ class Compare = std::less<Key>,
+ class Alloc = std::allocator<Key>
+> class set {
+ public:
+ set(initializer_list<Key> __list) {}
+
+ class iterator {
+ public:
+ iterator(Key *key): ptr(key) {}
+ iterator operator++() { ++ptr; return *this; }
+ bool operator!=(const iterator &other) const { return ptr != other.ptr; }
+ const Key &operator*() const { return *ptr; }
+ private:
+ Key *ptr;
+ };
+
+ public:
+ Key *val;
+ iterator begin() const { return iterator(val); }
+ iterator end() const { return iterator(val + 1); }
+};
+
+template<
+ class Key,
+ class Hash = std::hash<Key>,
+ class Compare = std::less<Key>,
+ class Alloc = std::allocator<Key>
+> class unordered_set {
+ public:
+ unordered_set(initializer_list<Key> __list) {}
+
+ class iterator {
+ public:
+ iterator(Key *key): ptr(key) {}
+ iterator operator++() { ++ptr; return *this; }
+ bool operator!=(const iterator &other) const { return ptr != other.ptr; }
+ const Key &operator*() const { return *ptr; }
+ private:
+ Key *ptr;
+ };
+
+ public:
+ Key *val;
+ iterator begin() const { return iterator(val); }
+ iterator end() const { return iterator(val + 1); }
+};
+}
Added: cfe/trunk/test/Analysis/ptr-iter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ptr-iter.cpp?rev=361664&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/ptr-iter.cpp (added)
+++ cfe/trunk/test/Analysis/ptr-iter.cpp Fri May 24 12:24:08 2019
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 %s -analyzer-output=text -verify \
+// RUN: -analyzer-checker=core,alpha.nondeterminism.PointerIteration
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+template<class T>
+void f(T x);
+
+void PointerIteration() {
+ int a = 1, b = 2;
+ std::set<int> OrderedIntSet = {a, b};
+ std::set<int *> OrderedPtrSet = {&a, &b};
+ std::unordered_set<int> UnorderedIntSet = {a, b};
+ std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
+
+ for (auto i : OrderedIntSet) // no-warning
+ f(i);
+
+ for (auto i : OrderedPtrSet) // no-warning
+ f(i);
+
+ for (auto i : UnorderedIntSet) // no-warning
+ f(i);
+
+ for (auto i : UnorderedPtrSet) // expected-warning {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+// expected-note at -1 {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+ f(i);
+}
Modified: cfe/trunk/www/analyzer/alpha_checks.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/alpha_checks.html?rev=361664&r1=361663&r2=361664&view=diff
==============================================================================
--- cfe/trunk/www/analyzer/alpha_checks.html (original)
+++ cfe/trunk/www/analyzer/alpha_checks.html Fri May 24 12:24:08 2019
@@ -1068,6 +1068,24 @@ void test(char *y) {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
+<tr><td><a id="alpha.nondeterminism.PointerIteration"><div class="namedescr expandable"><span class="name">
+alpha.nondeterminism.PointerIteration</span><span class="lang">
+(C++)</span><div class="descr">
+Check for non-determinism caused by iterating unordered containers of pointers.</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
+
+ for (auto i : UnorderedPtrSet) // warn
+ f(i);
+}
+</pre></div></div></td></tr>
+</tbody></table>
+
+<tbody>
<tr><td><a id="alpha.nondeterminism.PointerSorting"><div class="namedescr expandable"><span class="name">
alpha.nondeterminism.PointerSorting</span><span class="lang">
(C++)</span><div class="descr">
More information about the cfe-commits
mailing list