2018-08-30 04:29:17 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-output=plist-multi-file -o %t.plist -verify -analyzer-config eagerly-assume=false %s
|
[analyzer][tests] Use normalize_plist in place of diff_plist (`cat` cases)
Summary:
The `%diff_plist` lit substitution invokes `diff` with a non-portable
`-I` option. The intended effect can be achieved by normalizing the
inputs to `diff` beforehand. Such normalization can be done with
`grep -Ev`, which is also used by other tests.
This patch applies the change (adjusted for review comments) described
in http://lists.llvm.org/pipermail/cfe-dev/2019-April/061904.html
mechanically to the cases where the output file is piped to
`%diff_plist` via `cat`.
The changes were applied via a script, except that
`clang/test/Analysis/NewDelete-path-notes.cpp` and
`clang/test/Analysis/plist-macros-with-expansion.cpp` were each adjusted
for the line-continuation on the relevant `RUN` step.
Reviewers: NoQ, sfertile, xingxue, jasonliu, daltenty
Subscribers: xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, Charusso, jsji, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62950
llvm-svn: 362996
2019-06-11 06:37:31 +08:00
|
|
|
// RUN: %normalize_plist <%t.plist | diff -u %S/Inputs/expected-plists/cxx-for-range.cpp.plist -
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
|
|
|
extern void work();
|
|
|
|
|
|
|
|
void testLoop() {
|
|
|
|
int z[] = {1,2};
|
|
|
|
for (int y : z) {
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
if (y == 2)
|
|
|
|
*(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
(void)y;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(volatile int *)0 = 1; // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
class MagicVector {
|
|
|
|
public:
|
|
|
|
MagicVector();
|
|
|
|
|
|
|
|
using iterator = int *;
|
|
|
|
|
|
|
|
iterator begin() const;
|
|
|
|
iterator end() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
MagicVector get(bool fail = false) {
|
|
|
|
if (fail)
|
|
|
|
*(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
return MagicVector{};
|
|
|
|
}
|
|
|
|
|
|
|
|
void testLoopOpaqueCollection() {
|
|
|
|
for (int y : get()) {
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
if (y == 2)
|
|
|
|
*(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
(void)y;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class MagicVector2 {
|
|
|
|
public:
|
|
|
|
MagicVector2();
|
|
|
|
|
|
|
|
class iterator {
|
|
|
|
public:
|
|
|
|
int operator*() const;
|
|
|
|
iterator &operator++();
|
|
|
|
bool operator==(const iterator &);
|
|
|
|
bool operator!=(const iterator &);
|
|
|
|
};
|
|
|
|
|
|
|
|
iterator begin() const;
|
|
|
|
iterator end() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
MagicVector2 get2() {
|
|
|
|
return MagicVector2{};
|
|
|
|
}
|
|
|
|
|
|
|
|
void testLoopOpaqueIterator() {
|
|
|
|
for (int y : get2()) {
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
if (y == 2)
|
|
|
|
*(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
(void)y;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void testLoopErrorInRange() {
|
|
|
|
for (int y : get(true)) { // error inside get()
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
if (y == 2)
|
|
|
|
*(volatile int *)0 = 1; // no-warning
|
|
|
|
work();
|
|
|
|
work();
|
|
|
|
(void)y;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(volatile int *)0 = 1; // no-warning
|
|
|
|
}
|
2018-09-29 02:44:09 +08:00
|
|
|
|
|
|
|
void testForRangeInit() {
|
|
|
|
for (int *arr[3] = {nullptr, nullptr, nullptr}; int *p : arr) // expected-warning {{extension}}
|
|
|
|
*p = 1; // expected-warning {{Dereference of null pointer}}
|
|
|
|
}
|