Skip to content

Commit fe88aab

Browse files
committed
Make _LIBCPP_ASSUME usable when it is appropriate
libc++ turned off _LIBCPP_ASSUME because turning every debug assert into __builtin_assume tripped https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 However, this means we can't use _LIBCPP_ASSUME when there is a clear optimization intent. See #78929 (comment) for discussion of a place where _LIBCPP_ASSUME would be valuable. Go ahead and fix this now, and adjust the comments. I don't think we want _LIBCPP_ASSUME in disabled asserts anyway, at least not in any of the hardened modes. This PR should have no impact on libc++ right now, since _LIBCPP_ASSUME is currently never called standalone, but I figure I can do this as a standalone PR since it's pretty straightforward.
1 parent 5ad418b commit fe88aab

File tree

1 file changed

+31
-28
lines changed

1 file changed

+31
-28
lines changed

libcxx/include/__assert

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,20 @@
2323
: _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \
2424
expression) " failed: " message "\n"))
2525

26-
// TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add
27-
// assumptions without a clear optimization intent, disable that to avoid worsening the code generation.
28-
// See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a discussion.
29-
#if 0 && __has_builtin(__builtin_assume)
26+
// WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear
27+
// optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a
28+
// discussion.
29+
#if __has_builtin(__builtin_assume)
3030
# define _LIBCPP_ASSUME(expression) \
3131
(_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \
3232
__builtin_assume(static_cast<bool>(expression)) _LIBCPP_DIAGNOSTIC_POP)
3333
#else
3434
# define _LIBCPP_ASSUME(expression) ((void)0)
3535
#endif
3636

37+
// Historically, disabled assertions below expanded to `_LIBCPP_ASSUME`, but this both triggers the
38+
// issue described above, and also causes every debug assertion to be a safety risk.
39+
3740
// clang-format off
3841
// Fast hardening mode checks.
3942

@@ -44,18 +47,18 @@
4447
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message)
4548
// Disabled checks.
4649
// On most modern platforms, dereferencing a null pointer does not lead to an actual memory access.
47-
# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSUME(expression)
50+
# define _LIBCPP_ASSERT_NON_NULL(expression, message) ((void)0)
4851
// Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security
4952
// vulnerability.
50-
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression)
51-
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) _LIBCPP_ASSUME(expression)
52-
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
53-
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression)
54-
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSUME(expression)
55-
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSUME(expression)
56-
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
57-
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
58-
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression)
53+
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) ((void)0)
54+
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) ((void)0)
55+
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) ((void)0)
56+
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) ((void)0)
57+
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) ((void)0)
58+
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) ((void)0)
59+
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) ((void)0)
60+
# define _LIBCPP_ASSERT_INTERNAL(expression, message) ((void)0)
61+
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) ((void)0)
5962

6063
// Extensive hardening mode checks.
6164

@@ -73,8 +76,8 @@
7376
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSERT(expression, message)
7477
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message)
7578
// Disabled checks.
76-
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
77-
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
79+
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) ((void)0)
80+
# define _LIBCPP_ASSERT_INTERNAL(expression, message) ((void)0)
7881

7982
// Debug hardening mode checks.
8083

@@ -99,18 +102,18 @@
99102
#else
100103

101104
// All checks disabled.
102-
# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSUME(expression)
103-
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSUME(expression)
104-
# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSUME(expression)
105-
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression)
106-
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) _LIBCPP_ASSUME(expression)
107-
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
108-
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression)
109-
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSUME(expression)
110-
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSUME(expression)
111-
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
112-
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
113-
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression)
105+
# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) ((void)0)
106+
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) ((void)0)
107+
# define _LIBCPP_ASSERT_NON_NULL(expression, message) ((void)0)
108+
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) ((void)0)
109+
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) ((void)0)
110+
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) ((void)0)
111+
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) ((void)0)
112+
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) ((void)0)
113+
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) ((void)0)
114+
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) ((void)0)
115+
# define _LIBCPP_ASSERT_INTERNAL(expression, message) ((void)0)
116+
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) ((void)0)
114117

115118
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
116119
// clang-format on

0 commit comments

Comments
 (0)