Skip to content

Commit 4d229af

Browse files
authored
Merge pull request #2909 from glebm/ptr-comparison
Add comparison operators for SharedImpl, fix bugs
2 parents 0328de2 + 0bab610 commit 4d229af

File tree

9 files changed

+140
-10
lines changed

9 files changed

+140
-10
lines changed

include/sass/base.h

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
#endif
1818
#endif
1919

20+
// Work around lack of `noexcept` keyword support in VS2013
21+
#if defined(_MSC_VER) && (_MSC_VER <= 1800) && !defined(_ALLOW_KEYWORD_MACROS)
22+
#define _ALLOW_KEYWORD_MACROS 1
23+
#define noexcept throw( )
24+
#endif
25+
2026
#include <stddef.h>
2127
#include <stdbool.h>
2228

src/ast.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ namespace Sass {
184184
/////////////////////////////////////////////////////////////////////////
185185

186186
Bubble::Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g, size_t t)
187-
: Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == 0)
187+
: Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == nullptr)
188188
{ }
189189
Bubble::Bubble(const Bubble* ptr)
190190
: Statement(ptr),
@@ -834,7 +834,7 @@ namespace Sass {
834834
}
835835

836836
bool At_Root_Block::exclude_node(Statement_Obj s) {
837-
if (expression() == 0)
837+
if (expression() == nullptr)
838838
{
839839
return s->statement_type() == Statement::RULESET;
840840
}

src/ast.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ namespace Sass {
312312
bool empty() const { return list_.empty(); }
313313
bool has(Expression_Obj k) const { return elements_.count(k) == 1; }
314314
Expression_Obj at(Expression_Obj k) const;
315-
bool has_duplicate_key() const { return duplicate_key_ != 0; }
315+
bool has_duplicate_key() const { return duplicate_key_ != nullptr; }
316316
Expression_Obj get_duplicate_key() const { return duplicate_key_; }
317317
const ExpressionMap elements() { return elements_; }
318318
Hashed& operator<<(std::pair<Expression_Obj, Expression_Obj> p)

src/expand.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ namespace Sass {
104104
bool has_parent_selector = false;
105105
for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
106106
Selector_List_Obj ll = selector_stack.at(i);
107-
has_parent_selector = ll != 0 && ll->length() > 0;
107+
has_parent_selector = ll != nullptr && ll->length() > 0;
108108
}
109109

110110
Selector_List_Obj sel = r->selector();
@@ -614,7 +614,7 @@ namespace Sass {
614614

615615

616616
Selector_List_Obj contextualized = Cast<Selector_List>(s->perform(&eval));
617-
if (contextualized == false) return;
617+
if (contextualized == nullptr) return;
618618
for (auto complex_sel : contextualized->elements()) {
619619
Complex_Selector_Obj c = complex_sel;
620620
if (!c->head() || c->tail()) {

src/inspect.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ namespace Sass {
10601060

10611061
for (size_t i = 0, L = g->length(); i < L; ++i) {
10621062
if (!in_wrapped && i == 0) append_indentation();
1063-
if ((*g)[i] == 0) continue;
1063+
if ((*g)[i] == nullptr) continue;
10641064
schedule_mapping(g->at(i)->last());
10651065
// add_open_mapping((*g)[i]->last());
10661066
(*g)[i]->perform(this);

src/memory/SharedPtr.hpp

+97-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
#include "sass/base.h"
55

6+
#include <cstddef>
67
#include <iostream>
78
#include <string>
9+
#include <type_traits>
810
#include <vector>
911

1012
namespace Sass {
@@ -185,6 +187,100 @@ namespace Sass {
185187
T* detach() { return static_cast<T*>(SharedPtr::detach()); }
186188
};
187189

188-
}
190+
// Comparison operators, based on:
191+
// https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp
192+
193+
template<class T1, class T2>
194+
bool operator==(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
195+
return x.ptr() == y.ptr();
196+
}
197+
198+
template<class T1, class T2>
199+
bool operator!=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
200+
return x.ptr() != y.ptr();
201+
}
202+
203+
template<class T1, class T2>
204+
bool operator<(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
205+
using CT = typename std::common_type<T1*, T2*>::type;
206+
return std::less<CT>()(x.get(), y.get());
207+
}
208+
209+
template<class T1, class T2>
210+
bool operator<=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
211+
return !(y < x);
212+
}
213+
214+
template<class T1, class T2>
215+
bool operator>(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
216+
return y < x;
217+
}
218+
219+
template<class T1, class T2>
220+
bool operator>=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
221+
return !(x < y);
222+
}
223+
224+
template <class T>
225+
bool operator==(const SharedImpl<T>& x, std::nullptr_t) noexcept {
226+
return x.isNull();
227+
}
228+
229+
template <class T>
230+
bool operator==(std::nullptr_t, const SharedImpl<T>& x) noexcept {
231+
return x.isNull();
232+
}
233+
234+
template <class T>
235+
bool operator!=(const SharedImpl<T>& x, std::nullptr_t) noexcept {
236+
return !x.isNull();
237+
}
238+
239+
template <class T>
240+
bool operator!=(std::nullptr_t, const SharedImpl<T>& x) noexcept {
241+
return !x.isNull();
242+
}
243+
244+
template <class T>
245+
bool operator<(const SharedImpl<T>& x, std::nullptr_t) {
246+
return std::less<T*>()(x.get(), nullptr);
247+
}
248+
249+
template <class T>
250+
bool operator<(std::nullptr_t, const SharedImpl<T>& y) {
251+
return std::less<T*>()(nullptr, y.get());
252+
}
253+
254+
template <class T>
255+
bool operator<=(const SharedImpl<T>& x, std::nullptr_t) {
256+
return !(nullptr < x);
257+
}
258+
259+
template <class T>
260+
bool operator<=(std::nullptr_t, const SharedImpl<T>& y) {
261+
return !(y < nullptr);
262+
}
263+
264+
template <class T>
265+
bool operator>(const SharedImpl<T>& x, std::nullptr_t) {
266+
return nullptr < x;
267+
}
268+
269+
template <class T>
270+
bool operator>(std::nullptr_t, const SharedImpl<T>& y) {
271+
return y < nullptr;
272+
}
273+
274+
template <class T>
275+
bool operator>=(const SharedImpl<T>& x, std::nullptr_t) {
276+
return !(x < nullptr);
277+
}
278+
279+
template <class T>
280+
bool operator>=(std::nullptr_t, const SharedImpl<T>& y) {
281+
return !(nullptr < y);
282+
}
283+
284+
} // namespace Sass
189285

190286
#endif

src/parser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2488,7 +2488,7 @@ namespace Sass {
24882488
Supports_Condition_Obj Parser::parse_supports_condition_in_parens(bool parens_required)
24892489
{
24902490
Supports_Condition_Obj interp = parse_supports_interpolation();
2491-
if (interp != 0) return interp;
2491+
if (interp != nullptr) return interp;
24922492

24932493
if (!lex < exactly <'('> >()) {
24942494
if (parens_required) {

src/util.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,9 @@ namespace Sass {
627627

628628
bool isPrintable(Media_Block* m, Sass_Output_Style style)
629629
{
630-
if (m == 0) return false;
630+
if (m == nullptr) return false;
631631
Block_Obj b = m->block();
632-
if (b == 0) return false;
632+
if (b == nullptr) return false;
633633
for (size_t i = 0, L = b->length(); i < L; ++i) {
634634
Statement_Obj stm = b->at(i);
635635
if (Cast<Directive>(stm)) return true;

test/test_shared_ptr.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,32 @@ bool TestDetachNull() {
135135
return true;
136136
}
137137

138+
class EmptyTestObj : public Sass::SharedObj {
139+
public:
140+
const std::string to_string() const { return ""; }
141+
};
142+
143+
bool TestComparisonWithSharedPtr() {
144+
Sass::SharedImpl<EmptyTestObj> a = new EmptyTestObj();
145+
ASSERT(a == a);
146+
Sass::SharedImpl<EmptyTestObj> b = a;
147+
ASSERT(a == b);
148+
Sass::SharedImpl<EmptyTestObj> c = new EmptyTestObj();
149+
ASSERT(a != c);
150+
Sass::SharedImpl<EmptyTestObj> nullobj;
151+
ASSERT(a != nullobj);
152+
ASSERT(nullobj == nullobj);
153+
return true;
154+
}
155+
156+
bool TestComparisonWithNullptr() {
157+
Sass::SharedImpl<EmptyTestObj> a = new EmptyTestObj();
158+
ASSERT(a != nullptr);
159+
Sass::SharedImpl<EmptyTestObj> nullobj;
160+
ASSERT(nullobj == nullptr);
161+
return true;
162+
}
163+
138164
#define TEST(fn) \
139165
if (fn()) { \
140166
passed.push_back(#fn); \
@@ -155,6 +181,8 @@ int main(int argc, char **argv) {
155181
TEST(TestSelfAssignDetach);
156182
TEST(TestDetachedPtrIsNotDestroyedUntilAssignment);
157183
TEST(TestDetachNull);
184+
TEST(TestComparisonWithSharedPtr);
185+
TEST(TestComparisonWithNullptr);
158186
std::cerr << argv[0] << ": Passed: " << passed.size()
159187
<< ", failed: " << failed.size()
160188
<< "." << std::endl;

0 commit comments

Comments
 (0)