Skip to content

Commit 5532f13

Browse files
Most cases implemented
1 parent fe37604 commit 5532f13

33 files changed

+586
-67
lines changed

cpp/common/src/codingstandards/cpp/standardlibrary/Memory.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
import cpp
66

7+
class DefaultAllocator extends TemplateClass {
8+
DefaultAllocator() { this.hasQualifiedName("std", "allocator") }
9+
}
10+
711
abstract class UninitializedMemoryManagementFunction extends Function {
812
UninitializedMemoryManagementFunction() {
913
this.getADeclarationLocation().getFile().getShortName() = "memory"
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import cpp
2+
3+
predicate mustBeImplicitlyDefined(Function mf) {
4+
// If it exists and its defaulted, it must be implicitly defined
5+
mf.isCompilerGenerated() or mf.isDefaulted()
6+
}
7+
8+
predicate mustNotBeImplicitlyDefined(Function mf) {
9+
// Sanity check: exclude member functions that are definitely user defined!
10+
not mustBeImplicitlyDefined(mf) and
11+
(
12+
// If the user wrote a body, it's not implicitly defined
13+
not mf.isCompilerGenerated()
14+
or
15+
// Deleted functions have no definition at all
16+
mf.isDeleted()
17+
)
18+
}
19+
20+
predicate mustBeUserDeclared(Function mf) {
21+
exists(FunctionDeclarationEntry fde | fde.getFunction() = mf and not fde.isImplicit())
22+
}
23+
24+
predicate mustNotBeUserDeclared(Function mf) {
25+
// use forex: at least one declaration must exist, and all declarations must be implicit
26+
forex(FunctionDeclarationEntry fde | fde.getFunction() = mf | fde.isImplicit())
27+
}
28+
29+
private signature class SpecialMember extends Function;
30+
31+
private signature predicate constraint(Function mf);
32+
33+
/**
34+
* Implicitly defined copy constructors are deprecated if the class has a user-declared copy
35+
* assignment operator or a user-declared destructor. The same is true for the reverse case
36+
* (implicit copy assignment operators check for copy constructors).
37+
*
38+
* Unfortunately, trivial copy constructors, assignment operators, and destructors are often missing
39+
* from the database, so we can only approximate.
40+
*
41+
* To manage all of the negatives, double negatives, musts, mays, and may nots, the problem is
42+
* broken down into sets as defined below.
43+
*
44+
* Firstly:
45+
* - CC=copy constructor, CA=copy assignment operator, D=destructor
46+
* - IDEF = implicitly defined, UDEC = user declared
47+
*
48+
* and:
49+
* - C_has{X} = set of all classes T for which "class T has a {X}"
50+
* - C_mustHave{X} = set of all classes T for which "class T must have a {X}"
51+
* - C_cannotHave{X} = set of all classes T for which "class T cannot have a {X}"
52+
* - C_mayHave{X} = not C_cannotHave{X}
53+
*
54+
* then we can find all cases we know to be deprecated via:
55+
* - Step 1: find C_mustHave{IDEF CC}, C_mustHave{IDEF CA}
56+
* - Step 2: find C_mustHave{UDEC CC}, C_mustHave{UDEC CA}, C_mustHave{UDEC D}
57+
* - Step 3: All C' are deprecated where C' in C_mustHave{IDEF CC} and (C' in C_mustHave{UDEC CA} or C' in C_mustHave{UDEC D})
58+
* - Step 4: All C' are deprecated where C' in C_mustHave{IDEF CA} and (C' in C_mustHave{UDEC CC} or C' in C_mustHave{UDEC D})
59+
*
60+
* And all cases we may consider deprecated via:
61+
* - Step 5: find C_cannotHave{IDEF CC}, C_cannotHave{IDEF CA}
62+
* - Step 6: find C_mayHave{IDEF CC}, C_mayHave{IDEF CA} (by negating the cannot sets)
63+
* - Step 7: find C_cannotHave{UDEC CC}, C_cannotHave{UDEC CA}, C_cannotHave{UDEC D}
64+
* - Step 8: find C_mayHave{UDEC CC}, C_mayHave{UDEC CA}, C_mayHave{UDEC D} (by negating the cannot sets)
65+
* - Step 9: All C' may be deprecated where C' in C_mayHave{IDEF CC} and (C' in C_mayHave{UDEC CA} or C' in C_mayHave{UDEC D})
66+
* - Step 10: All C' may be deprecated where C' in C_mayHave{IDEF CA} and (C' in C_mayHave{UDEC CC} or C' in C_mayHave{UDEC D})
67+
*
68+
* This is performed through the various instantiations of this module.
69+
*/
70+
private module ClassesWhere<constraint/1 pred, SpecialMember Member> {
71+
final class FinalClass = Class;
72+
73+
class Matching extends FinalClass {
74+
Matching() { exists(Member member | member.getDeclaringType() = this and pred(member)) }
75+
}
76+
77+
class NotMatching extends FinalClass {
78+
NotMatching() { not this instanceof Matching }
79+
}
80+
}
81+
82+
/* Step 1: find C_mustHave{IDEF CC}, C_mustHave{IDEF CA} */
83+
private class CMustHaveIdefCC = ClassesWhere<mustBeImplicitlyDefined/1, CopyConstructor>::Matching;
84+
85+
private class CMustHaveIdefCA =
86+
ClassesWhere<mustBeImplicitlyDefined/1, CopyAssignmentOperator>::Matching;
87+
88+
/* Step 2: find C_mustHave{UDEC CC}, C_mustHave{UDEC CA}, C_mustHave{UDEC D} */
89+
private class CMustHaveUdecCC = ClassesWhere<mustBeUserDeclared/1, CopyConstructor>::Matching;
90+
91+
private class CMustHaveUdecCA =
92+
ClassesWhere<mustBeUserDeclared/1, CopyAssignmentOperator>::Matching;
93+
94+
private class CMustHaveUdecD = ClassesWhere<mustBeUserDeclared/1, Destructor>::Matching;
95+
96+
/* - Step 3: All C' are deprecated where C' in C_mustHave{IDEF CC} and (C' in C_mustHave{UDEC CA} or C' in C_mustHave{UDEC D}) */
97+
class MustHaveDeprecatedCopyConstructor extends CMustHaveIdefCC {
98+
MustHaveDeprecatedCopyConstructor() {
99+
this instanceof CMustHaveUdecCA or this instanceof CMustHaveUdecD
100+
}
101+
}
102+
103+
/* - Step 4: All C' are deprecated where C' in C_mustHave{IDEF CA} and (C' in C_mustHave{UDEC CC} or C' in C_mustHave{UDEC D}) */
104+
class MustHaveDeprecatedCopyAssignmentOperator extends CMustHaveIdefCA {
105+
MustHaveDeprecatedCopyAssignmentOperator() {
106+
this instanceof CMustHaveUdecCC or this instanceof CMustHaveUdecD
107+
}
108+
}
109+
110+
/**
111+
* Step 5: find C_cannotHave{IDEF CC}, C_cannotHave{IDEF CA}
112+
* Step 6: find C_mayHave{IDEF CC}, C_mayHave{IDEF CA} (by negating the cannot sets)
113+
*
114+
* In our case, `ClassesWhere<...>` performs steps 5 and 6 together via `NotMatching`.
115+
*/
116+
private class CMayHaveIdefCC =
117+
ClassesWhere<mustNotBeImplicitlyDefined/1, CopyConstructor>::NotMatching;
118+
119+
private class CMayHaveIdefCA =
120+
ClassesWhere<mustNotBeImplicitlyDefined/1, CopyAssignmentOperator>::NotMatching;
121+
122+
/**
123+
* Step 7: find C_cannotHave{UDEC CC}, C_cannotHave{UDEC CA}, C_cannotHave{UDEC D}
124+
* Step 8: find C_mayHave{UDEC CC}, C_mayHave{UDEC CA}, C_mayHave{UDEC D} (by negating the cannot sets)
125+
*
126+
* In our case, `ClassesWhere<...>` performs steps 7 and 8 together via `NotMatching`.
127+
*/
128+
private class CMayHaveUdecCC = ClassesWhere<mustNotBeUserDeclared/1, CopyConstructor>::NotMatching;
129+
130+
private class CMayHaveUdecCA =
131+
ClassesWhere<mustNotBeUserDeclared/1, CopyAssignmentOperator>::NotMatching;
132+
133+
private class CMayHaveUdecD = ClassesWhere<mustNotBeUserDeclared/1, Destructor>::NotMatching;
134+
135+
/* - Step 9: All C' may be deprecated where C' in C_mayHave{IDEF CC} and (C' in C_mayHave{UDEC CA} or C' in C_mayHave{UDEC D}) */
136+
class MayHaveDeprecatedCopyConstructor extends CMayHaveIdefCC {
137+
MayHaveDeprecatedCopyConstructor() {
138+
this instanceof CMayHaveUdecCA or this instanceof CMayHaveUdecD
139+
}
140+
}
141+
142+
/* - Step 10: All C' may be deprecated where C' in C_mayHave{IDEF CA} and (C' in C_mayHave{UDEC CC} or C' in C_mayHave{UDEC D}) */
143+
class MayHaveDeprecatedCopyAssignmentOperator extends CMayHaveIdefCA {
144+
MayHaveDeprecatedCopyAssignmentOperator() {
145+
this instanceof CMayHaveUdecCC or this instanceof CMayHaveUdecD
146+
}
147+
}

cpp/common/test/includes/standard-library/ccomplex

Whitespace-only changes.

cpp/common/test/includes/standard-library/complex

Whitespace-only changes.

cpp/common/test/includes/standard-library/cstdalign

Whitespace-only changes.

cpp/common/test/includes/standard-library/cstdbool

Whitespace-only changes.

cpp/common/test/includes/standard-library/ctgmath

Whitespace-only changes.

cpp/common/test/includes/standard-library/functional.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern const __ph<2> _2;
1515
} // namespace placeholders
1616
template <class Fn, class... Args> class binder {
1717
public:
18+
using result_type = int; // deprecated in C++17
1819
template <class TFn, class... TArgs>
1920
constexpr binder(TFn &&f, TArgs &&...args) noexcept {}
2021

@@ -57,7 +58,18 @@ template <class T> reference_wrapper<T> ref(T &t) noexcept;
5758
template <class T> void ref(const T &&t) = delete;
5859
template <class T> reference_wrapper<T> ref(reference_wrapper<T> t) noexcept;
5960

60-
template <class Ty> struct hash { size_t operator()(Ty val) const; };
61+
template <class Ty> struct hash {
62+
using result_type = size_t; // deprecated in C++17
63+
using argument_type = Ty; // deprecated in C++17
64+
size_t operator()(Ty val) const;
65+
};
66+
67+
template <class F> class mem_fn_result {
68+
public:
69+
using result_type = int; // deprecated in C++17
70+
};
71+
72+
template <class F> mem_fn_result<F> mem_fn(F f);
6173

6274
template <class Arg, class Result>
6375
class pointer_to_unary_function : public unary_function<Arg, Result> {
@@ -103,9 +115,24 @@ template <class Predicate> class binary_negate {
103115
template <class> class function;
104116
template <class R, class... Args> class function<R(Args...)> {
105117
public:
118+
using result_type = R; // deprecated in C++17
106119
function();
107120
template <class F> function(F&& f);
108121
template <class F> function &operator=(F &&);
109122
};
123+
124+
template <class T = void> struct plus {
125+
using result_type = T; // deprecated in C++17
126+
using first_argument_type = T; // deprecated in C++17
127+
using second_argument_type = T; // deprecated in C++17
128+
T operator()(const T &x, const T &y) const;
129+
};
130+
131+
template <class T = void> struct negate {
132+
using result_type = T; // deprecated in C++17
133+
using argument_type = T; // deprecated in C++17
134+
T operator()(const T &x) const;
135+
};
136+
110137
} // namespace std
111138
#endif

cpp/common/test/includes/standard-library/memory.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef _GHLIBCPP_MEMORY
22
#define _GHLIBCPP_MEMORY
33
#include "exception.h"
4+
#include "iterator.h"
45
#include "stddef.h"
56
#include "utility.h"
67

@@ -135,6 +136,14 @@ template <typename T1> struct allocator {
135136
using value_type = T1;
136137
using size_type = std::size_t;
137138
using difference_type = std::ptrdiff_t;
139+
// deprecated in C++17:
140+
using pointer = T1 *;
141+
using const_pointer = const T1 *;
142+
using reference = T1 &;
143+
using const_reference = const T1 &;
144+
template <class T2> struct rebind {
145+
using other = allocator<T2>;
146+
};
138147

139148
constexpr allocator() noexcept = default;
140149
constexpr allocator(const allocator &) noexcept = default;
@@ -144,7 +153,14 @@ template <typename T1> struct allocator {
144153
~allocator() = default;
145154

146155
T1 *allocate(std::size_t);
156+
T1 *allocate(std::size_t, const void *);
147157
void deallocate(T1 *, std::size_t);
158+
// deprecated in C++17:
159+
pointer address(reference r) const noexcept;
160+
const_pointer address(const_reference r) const noexcept;
161+
size_type max_size() const noexcept;
162+
template <class U, class... Args> void construct(U *p, Args &&...args);
163+
template <class U> void destroy(U *p);
148164
};
149165

150166
template <> struct allocator<void> {
@@ -260,6 +276,31 @@ T2 destroy_n(T1&&, T2, T3);
260276
template <class T1>
261277
constexpr T1* launder(T1*) noexcept;
262278

279+
// get_temporary_buffer / return_temporary_buffer (deprecated in C++17)
280+
template <class T>
281+
pair<T *, ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;
282+
283+
template <class T>
284+
void return_temporary_buffer(T *p);
285+
286+
// raw_storage_iterator (deprecated in C++17)
287+
template <class OutputIterator, class T>
288+
class raw_storage_iterator {
289+
public:
290+
using iterator_category = output_iterator_tag;
291+
using value_type = void;
292+
using difference_type = void;
293+
using pointer = void;
294+
using reference = void;
295+
explicit raw_storage_iterator(OutputIterator x);
296+
raw_storage_iterator &operator*();
297+
raw_storage_iterator &operator=(const T &element);
298+
raw_storage_iterator &operator=(T &&element);
299+
raw_storage_iterator &operator++();
300+
raw_storage_iterator operator++(int);
301+
OutputIterator base() const;
302+
};
303+
263304
} // namespace std
264305

265306
#endif // _GHLIBCPP_MEMORY

cpp/common/test/includes/standard-library/strstream.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <streambuf>
55

66
namespace std {
7+
typedef basic_iostream<char> iostream;
8+
79
class strstreambuf : public basic_streambuf<char> {};
810

911
class istrstream : public istream {
@@ -18,4 +20,9 @@ class ostrstream : public ostream {
1820
public:
1921
ostrstream();
2022
};
23+
24+
class strstream : public iostream {
25+
public:
26+
strstream();
27+
};
2128
} // namespace std

0 commit comments

Comments
 (0)