Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/Iterator.h
Line
Count
Source (jump to first uncovered line)
1
//=== Iterator.h - Common functions for iterator checkers. ---------*- C++ -*-//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Defines common functions to be used by the itertor checkers .
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
14
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
15
16
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
17
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
18
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
19
20
namespace clang {
21
namespace ento {
22
namespace iterator {
23
24
// Abstract position of an iterator. This helps to handle all three kinds
25
// of operators in a common way by using a symbolic position.
26
struct IteratorPosition {
27
private:
28
29
  // Container the iterator belongs to
30
  const MemRegion *Cont;
31
32
  // Whether iterator is valid
33
  const bool Valid;
34
35
  // Abstract offset
36
  const SymbolRef Offset;
37
38
  IteratorPosition(const MemRegion *C, bool V, SymbolRef Of)
39
5.69k
      : Cont(C), Valid(V), Offset(Of) {}
40
41
public:
42
14.2k
  const MemRegion *getContainer() const { return Cont; }
43
1.27k
  bool isValid() const { return Valid; }
44
70.4k
  SymbolRef getOffset() const { return Offset; }
45
46
1.13k
  IteratorPosition invalidate() const {
47
1.13k
    return IteratorPosition(Cont, false, Offset);
48
1.13k
  }
49
50
3.09k
  static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) {
51
3.09k
    return IteratorPosition(C, true, Of);
52
3.09k
  }
53
54
1.42k
  IteratorPosition setTo(SymbolRef NewOf) const {
55
1.42k
    return IteratorPosition(Cont, Valid, NewOf);
56
1.42k
  }
57
58
42
  IteratorPosition reAssign(const MemRegion *NewCont) const {
59
42
    return IteratorPosition(NewCont, Valid, Offset);
60
42
  }
61
62
10.2k
  bool operator==(const IteratorPosition &X) const {
63
10.2k
    return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
64
10.2k
  }
65
66
0
  bool operator!=(const IteratorPosition &X) const {
67
0
    return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset;
68
0
  }
69
70
25.5k
  void Profile(llvm::FoldingSetNodeID &ID) const {
71
25.5k
    ID.AddPointer(Cont);
72
25.5k
    ID.AddInteger(Valid);
73
25.5k
    ID.Add(Offset);
74
25.5k
  }
75
};
76
77
// Structure to record the symbolic begin and end position of a container
78
struct ContainerData {
79
private:
80
  const SymbolRef Begin, End;
81
82
2.36k
  ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {}
83
84
public:
85
1.12k
  static ContainerData fromBegin(SymbolRef B) {
86
1.12k
    return ContainerData(B, nullptr);
87
1.12k
  }
88
89
270
  static ContainerData fromEnd(SymbolRef E) {
90
270
    return ContainerData(nullptr, E);
91
270
  }
92
93
97.5k
  SymbolRef getBegin() const { return Begin; }
94
71.8k
  SymbolRef getEnd() const { return End; }
95
96
109
  ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); }
97
98
867
  ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); }
99
100
233
  bool operator==(const ContainerData &X) const {
101
233
    return Begin == X.Begin && End == X.End;
102
233
  }
103
104
0
  bool operator!=(const ContainerData &X) const {
105
0
    return Begin != X.Begin || End != X.End;
106
0
  }
107
108
2.58k
  void Profile(llvm::FoldingSetNodeID &ID) const {
109
2.58k
    ID.Add(Begin);
110
2.58k
    ID.Add(End);
111
2.58k
  }
112
};
113
114
class IteratorSymbolMap {};
115
class IteratorRegionMap {};
116
class ContainerMap {};
117
118
using IteratorSymbolMapTy =
119
  CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, IteratorPosition);
120
using IteratorRegionMapTy =
121
  CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, IteratorPosition);
122
using ContainerMapTy =
123
  CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, ContainerData);
124
125
} // namespace iterator
126
127
template<>
128
struct ProgramStateTrait<iterator::IteratorSymbolMap>
129
  : public ProgramStatePartialTrait<iterator::IteratorSymbolMapTy> {
130
84.2k
  static void *GDMIndex() { static int Index; return &Index; }
131
};
132
133
template<>
134
struct ProgramStateTrait<iterator::IteratorRegionMap>
135
  : public ProgramStatePartialTrait<iterator::IteratorRegionMapTy> {
136
167k
  static void *GDMIndex() { static int Index; return &Index; }
137
};
138
139
template<>
140
struct ProgramStateTrait<iterator::ContainerMap>
141
  : public ProgramStatePartialTrait<iterator::ContainerMapTy> {
142
99.4k
  static void *GDMIndex() { static int Index; return &Index; }
143
};
144
145
namespace iterator {
146
147
bool isIteratorType(const QualType &Type);
148
bool isIterator(const CXXRecordDecl *CRD);
149
bool isComparisonOperator(OverloadedOperatorKind OK);
150
bool isInsertCall(const FunctionDecl *Func);
151
bool isEraseCall(const FunctionDecl *Func);
152
bool isEraseAfterCall(const FunctionDecl *Func);
153
bool isEmplaceCall(const FunctionDecl *Func);
154
bool isAccessOperator(OverloadedOperatorKind OK);
155
bool isAccessOperator(UnaryOperatorKind OK);
156
bool isAccessOperator(BinaryOperatorKind OK);
157
bool isDereferenceOperator(OverloadedOperatorKind OK);
158
bool isDereferenceOperator(UnaryOperatorKind OK);
159
bool isDereferenceOperator(BinaryOperatorKind OK);
160
bool isIncrementOperator(OverloadedOperatorKind OK);
161
bool isIncrementOperator(UnaryOperatorKind OK);
162
bool isDecrementOperator(OverloadedOperatorKind OK);
163
bool isDecrementOperator(UnaryOperatorKind OK);
164
bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
165
bool isRandomIncrOrDecrOperator(BinaryOperatorKind OK);
166
const ContainerData *getContainerData(ProgramStateRef State,
167
                                      const MemRegion *Cont);
168
const IteratorPosition *getIteratorPosition(ProgramStateRef State,
169
                                            const SVal &Val);
170
ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
171
                                    const IteratorPosition &Pos);
172
ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val,
173
                                       const MemRegion *Cont, const Stmt* S,
174
                                       const LocationContext *LCtx,
175
                                       unsigned blockCount);
176
ProgramStateRef advancePosition(ProgramStateRef State,
177
                                const SVal &Iter,
178
                                OverloadedOperatorKind Op,
179
                                const SVal &Distance);
180
ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym,
181
                                 long Scale);
182
bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
183
             BinaryOperator::Opcode Opc);
184
bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
185
             BinaryOperator::Opcode Opc);
186
187
} // namespace iterator
188
} // namespace ento
189
} // namespace clang
190
191
#endif