Skip to content

Commit e0476b5

Browse files
authored
Merge pull request #15934 from MathiasVP/ir-models-for-iterators
C++: Add alias and side-effect models to `begin` and `end` functions
2 parents a13391b + 0be329d commit e0476b5

File tree

7 files changed

+28488
-28084
lines changed

7 files changed

+28488
-28084
lines changed

cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import cpp
99
import semmle.code.cpp.models.interfaces.Taint
1010
import semmle.code.cpp.models.interfaces.DataFlow
1111
import semmle.code.cpp.models.interfaces.Iterator
12+
import semmle.code.cpp.models.interfaces.Alias
13+
import semmle.code.cpp.models.interfaces.SideEffect
1214

1315
/**
1416
* An instantiation of the `std::iterator_traits` template.
@@ -438,7 +440,9 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
438440
* A `begin` or `end` member function, or a related member function, that
439441
* returns an iterator.
440442
*/
441-
private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction {
443+
private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction,
444+
AliasFunction, SideEffectFunction
445+
{
442446
BeginOrEndFunction() {
443447
this.hasName([
444448
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
@@ -456,6 +460,22 @@ private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetItera
456460
input.isQualifierObject() and
457461
output.isReturnValue()
458462
}
463+
464+
override predicate parameterNeverEscapes(int index) { index = -1 }
465+
466+
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
467+
468+
override predicate hasOnlySpecificReadSideEffects() { any() }
469+
470+
override predicate hasOnlySpecificWriteSideEffects() { any() }
471+
472+
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
473+
none()
474+
}
475+
476+
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
477+
i = -1 and buffer = false
478+
}
459479
}
460480

461481
/**

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 8233 additions & 8050 deletions
Large diffs are not rendered by default.

cpp/ql/test/library-tests/ir/ir/aliased_ir.expected

Lines changed: 7235 additions & 7186 deletions
Large diffs are not rendered by default.

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,28 +1055,75 @@ void Lambda(int x, const String& s) {
10551055
lambda_inits(6);
10561056
}
10571057

1058-
template<typename T>
1059-
struct vector {
1058+
namespace std {
1059+
template<class T>
1060+
struct remove_const { typedef T type; };
1061+
1062+
template<class T>
1063+
struct remove_const<const T> { typedef T type; };
1064+
1065+
// `remove_const_t<T>` removes any `const` specifier from `T`
1066+
template<class T>
1067+
using remove_const_t = typename remove_const<T>::type;
1068+
1069+
struct ptrdiff_t;
1070+
1071+
template<class I> struct iterator_traits;
1072+
1073+
template <class Category,
1074+
class value_type,
1075+
class difference_type = ptrdiff_t,
1076+
class pointer_type = value_type*,
1077+
class reference_type = value_type&>
10601078
struct iterator {
1061-
T* p;
1062-
iterator& operator++();
1063-
T& operator*() const;
1079+
typedef Category iterator_category;
1080+
1081+
iterator();
1082+
iterator(iterator<Category, remove_const_t<value_type> > const &other); // non-const -> const conversion constructor
1083+
1084+
iterator &operator++();
1085+
iterator operator++(int);
1086+
iterator &operator--();
1087+
iterator operator--(int);
1088+
bool operator==(iterator other) const;
1089+
bool operator!=(iterator other) const;
1090+
reference_type operator*() const;
1091+
pointer_type operator->() const;
1092+
iterator operator+(int);
1093+
iterator operator-(int);
1094+
iterator &operator+=(int);
1095+
iterator &operator-=(int);
1096+
int operator-(iterator);
1097+
reference_type operator[](int);
1098+
};
1099+
1100+
struct input_iterator_tag {};
1101+
struct forward_iterator_tag : public input_iterator_tag {};
1102+
struct bidirectional_iterator_tag : public forward_iterator_tag {};
1103+
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
1104+
1105+
struct output_iterator_tag {};
10641106

1065-
bool operator!=(iterator right) const;
1107+
template<typename T>
1108+
struct vector {
1109+
vector(T);
1110+
~vector();
1111+
1112+
using iterator = std::iterator<random_access_iterator_tag, T>;
1113+
using const_iterator = std::iterator<random_access_iterator_tag, const T>;
1114+
1115+
iterator begin() const;
1116+
iterator end() const;
10661117
};
10671118

1068-
vector(T);
1069-
~vector();
1070-
iterator begin() const;
1071-
iterator end() const;
1072-
};
1119+
template<typename T>
1120+
bool operator==(typename vector<T>::iterator left, typename vector<T>::iterator right);
1121+
template<typename T>
1122+
bool operator!=(typename vector<T>::iterator left, typename vector<T>::iterator right);
10731123

1074-
template<typename T>
1075-
bool operator==(typename vector<T>::iterator left, typename vector<T>::iterator right);
1076-
template<typename T>
1077-
bool operator!=(typename vector<T>::iterator left, typename vector<T>::iterator right);
1124+
}
10781125

1079-
void RangeBasedFor(const vector<int>& v) {
1126+
void RangeBasedFor(const std::vector<int>& v) {
10801127
for (int e : v) {
10811128
if (e > 0) {
10821129
continue;
@@ -2151,21 +2198,21 @@ void initialization_with_destructor(bool b, char c) {
21512198
}
21522199

21532200
ClassWithDestructor x;
2154-
for(vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys)
2201+
for(std::vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys)
21552202
y.set_x('a');
21562203

2157-
for(vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys) {
2204+
for(std::vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys) {
21582205
y.set_x('a');
21592206
if (y.get_x() == 'b')
21602207
return;
21612208
}
21622209

2163-
for(vector<int> ys(1); int y : ys) {
2210+
for(std::vector<int> ys(1); int y : ys) {
21642211
if (y == 1)
21652212
return;
21662213
}
21672214

2168-
for(vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys) {
2215+
for(std::vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys) {
21692216
ClassWithDestructor z1;
21702217
ClassWithDestructor z2;
21712218
}
@@ -2243,7 +2290,7 @@ void ForDestructors() {
22432290
String s2;
22442291
}
22452292

2246-
for(String s : vector<String>(String("hello"))) {
2293+
for(String s : std::vector<String>(String("hello"))) {
22472294
String s2;
22482295
}
22492296

0 commit comments

Comments
 (0)