Whitelist comparison operators and their equivalent functors in <functional>

Reviewed By: akotulski

Differential Revision: D5449231

fbshipit-source-id: b6a946d
master
Jia Chen 7 years ago committed by Facebook Github Bot
parent 6c874957d0
commit 217363f5d6

@ -76,7 +76,14 @@ module Match = struct
(* Fail if we detect templates in the fuzzy name. Template instantiations are not taken into (* Fail if we detect templates in the fuzzy name. Template instantiations are not taken into
account when fuzzy matching, and templates may produce wrong results when parsing qualified account when fuzzy matching, and templates may produce wrong results when parsing qualified
names. *) names. *)
if String.contains qual_name '<' then let filtered_qual_name =
(* Filter out the '<' in operator< and operator<= *)
let operator_less_length = 14 in
if String.is_prefix qual_name ~prefix:"std::operator<" then
String.drop_prefix qual_name operator_less_length
else qual_name
in
if String.contains filtered_qual_name '<' then
failwithf "Unexpected template in fuzzy qualified name %s." qual_name ; failwithf "Unexpected template in fuzzy qualified name %s." qual_name ;
of_qual_string qual_name of_qual_string qual_name

@ -257,6 +257,12 @@ let whitelisted_cpp_methods =
; "std::max" ; "std::max"
; "std::min" ; "std::min"
; "std::move" ; "std::move"
; "std::operator!="
; "std::operator<"
; "std::operator<="
; "std::operator=="
; "std::operator>"
; "std::operator>="
; "std::swap" ] ; "std::swap" ]
let whitelisted_cpp_classes = let whitelisted_cpp_classes =
@ -265,6 +271,12 @@ let whitelisted_cpp_classes =
; "std::__wrap_iter" (* libc++ internal name of vector iterator *) ; "std::__wrap_iter" (* libc++ internal name of vector iterator *)
; "std::__get_pair" (* libc++ internal support class for std::get<std::pair> *) ; "std::__get_pair" (* libc++ internal support class for std::get<std::pair> *)
; "std::__pair_get" (* libstdc++ internal support class for std::get<std::pair> *) ; "std::__pair_get" (* libstdc++ internal support class for std::get<std::pair> *)
; "std::equal_to"
; "std::greater"
; "std::greater_equal"
; "std::less"
; "std::less_equal"
; "std::not_equal_to"
; "std::pair" ] ; "std::pair" ]
type dynamic_dispatch_policy = [`None | `Interface | `Sound | `Lazy] type dynamic_dispatch_policy = [`None | `Interface | `Sound | `Lazy]

@ -16,6 +16,18 @@ codetoanalyze/cpp/errors/include_header/header2.h, header2::div0_templ<int>, 1,
codetoanalyze/cpp/errors/memory_leaks/array_leak.cpp, leak, 4, MEMORY_LEAK, [start of procedure leak()] codetoanalyze/cpp/errors/memory_leaks/array_leak.cpp, leak, 4, MEMORY_LEAK, [start of procedure leak()]
codetoanalyze/cpp/errors/memory_leaks/object_leak.cpp, object_leak, 0, MEMORY_LEAK, [start of procedure object_leak(),start of procedure Rectangle,return from a call to Rectangle_Rectangle] codetoanalyze/cpp/errors/memory_leaks/object_leak.cpp, object_leak, 0, MEMORY_LEAK, [start of procedure object_leak(),start of procedure Rectangle,return from a call to Rectangle_Rectangle]
codetoanalyze/cpp/errors/memory_leaks/raii_malloc.cpp, memory_leak, 0, MEMORY_LEAK, [start of procedure memory_leak()] codetoanalyze/cpp/errors/memory_leaks/raii_malloc.cpp, memory_leak, 0, MEMORY_LEAK, [start of procedure memory_leak()]
codetoanalyze/cpp/errors/models/cmp.cpp, operator_eq_bad, 4, NULL_DEREFERENCE, [start of procedure operator_eq_bad(),start of procedure operator==(),Condition is true,Condition is true,return from a call to operator==,Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, operator_ge_bad, 4, NULL_DEREFERENCE, [start of procedure operator_ge_bad(),start of procedure operator>=(),start of procedure operator<(),Condition is false,Condition is false,Condition is false,return from a call to operator<,Condition is false,return from a call to operator>=,Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, operator_gt_bad, 4, NULL_DEREFERENCE, [start of procedure operator_gt_bad(),start of procedure operator>(),start of procedure operator<(),Condition is false,Condition is false,Condition is true,return from a call to operator<,return from a call to operator>,Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, operator_le_bad, 4, NULL_DEREFERENCE, [start of procedure operator_le_bad(),start of procedure operator<=(),start of procedure operator<(),Condition is false,Condition is false,Condition is false,return from a call to operator<,Condition is false,return from a call to operator<=,Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, operator_lt_bad, 4, NULL_DEREFERENCE, [start of procedure operator_lt_bad(),start of procedure operator<(),Condition is false,Condition is false,Condition is true,return from a call to operator<,Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, operator_neq_bad, 4, NULL_DEREFERENCE, [start of procedure operator_neq_bad(),start of procedure operator!=(),start of procedure operator==(),Condition is true,Condition is true,return from a call to operator==,Condition is true,return from a call to operator!=,Condition is false,Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, std_equal_to_bad, 4, NULL_DEREFERENCE, [start of procedure std_equal_to_bad(),Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, std_greater_bad, 4, NULL_DEREFERENCE, [start of procedure std_greater_bad(),Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, std_greater_equal_bad, 4, NULL_DEREFERENCE, [start of procedure std_greater_equal_bad(),Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, std_less_bad, 4, NULL_DEREFERENCE, [start of procedure std_less_bad(),Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, std_less_equal_bad, 4, NULL_DEREFERENCE, [start of procedure std_less_equal_bad(),Condition is true]
codetoanalyze/cpp/errors/models/cmp.cpp, std_not_equal_to_bad, 4, NULL_DEREFERENCE, [start of procedure std_not_equal_to_bad(),Condition is false,Condition is true]
codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_from, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_from(),start of procedure X,return from a call to move::X_X,start of procedure X,return from a call to move::X_X] codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_from, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_from(),start of procedure X,return from a call to move::X_X,start of procedure X,return from a call to move::X_X]
codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_to, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_to(),start of procedure X,return from a call to move::X_X,start of procedure X,return from a call to move::X_X] codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_to, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_to(),start of procedure X,return from a call to move::X_X,start of procedure X,return from a call to move::X_X]
codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null0_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null0_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull] codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null0_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null0_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull]

@ -0,0 +1,197 @@
/*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include <functional>
struct A {
int x, y;
};
bool operator==(const A& lhs, const A& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y;
}
bool operator!=(const A& lhs, const A& rhs) { return !(lhs == rhs); }
bool operator<(const A& lhs, const A& rhs) {
if (lhs.x < rhs.x)
return true;
else if (lhs.x > rhs.x)
return false;
else
return lhs.y < rhs.y;
}
bool operator>(const A& lhs, const A& rhs) { return rhs < lhs; }
bool operator>=(const A& lhs, const A& rhs) { return !(lhs < rhs); }
bool operator<=(const A& lhs, const A& rhs) { return !(rhs < lhs); }
void operator_eq_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (!(a == b))
*p = 42;
}
void operator_eq_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (a == b)
*p = 42;
}
void operator_neq_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (a != b)
*p = 42;
}
void operator_neq_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (!(a != b))
*p = 42;
}
void std_equal_to_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (!(std::equal_to<A>()(a, b)))
*p = 42;
}
void std_not_equal_to_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (std::not_equal_to<A>()(a, b))
*p = 42;
}
void std_equal_to_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (std::equal_to<A>()(a, b))
*p = 42;
}
void std_not_equal_to_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y};
if (!(std::not_equal_to<A>()(a, b)))
*p = 42;
}
void operator_lt_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (!(a < b))
*p = 42;
}
void operator_lt_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (a < b)
*p = 42;
}
void operator_le_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (!(a <= b))
*p = 42;
}
void operator_le_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (a <= b)
*p = 42;
}
void operator_gt_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (!(a > b))
*p = 42;
}
void operator_gt_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (a > b)
*p = 42;
}
void operator_ge_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (!(a >= b))
*p = 42;
}
void operator_ge_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (a >= b)
*p = 42;
}
void std_less_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (!(std::less<A>()(a, b)))
*p = 42;
}
void std_less_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (std::less<A>()(a, b))
*p = 42;
}
void std_less_equal_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (!(std::less_equal<A>()(a, b)))
*p = 42;
}
void std_less_equal_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y + 1};
if (std::less_equal<A>()(a, b))
*p = 42;
}
void std_greater_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (!(std::greater<A>()(a, b)))
*p = 42;
}
void std_greater_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (std::greater<A>()(a, b))
*p = 42;
}
void std_greater_equal_ok(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (!(std::greater_equal<A>()(a, b)))
*p = 42;
}
void std_greater_equal_bad(const A& a) {
int* p = nullptr;
A b{a.x, a.y - 1};
if (std::greater_equal<A>()(a, b))
*p = 42;
}
Loading…
Cancel
Save