Skip to content

Commit 1f15671

Browse files
committed
remove more instances of 'idiom'
Signed-off-by: Justin Stitt <[email protected]>
1 parent 821ce7a commit 1f15671

File tree

9 files changed

+71
-75
lines changed

9 files changed

+71
-75
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,31 +294,35 @@ Moved checkers
294294
Sanitizers
295295
----------
296296

297-
- Added the ``-fno-sanitize-overflow-idioms`` flag which disables integer
298-
overflow and truncation sanitizer instrumentation for specific
299-
overflow-dependent code patterns. The noise created by these idioms is a
300-
large reason as to why large projects refuse to turn on arithmetic
301-
sanitizers.
297+
- Added the ``-fsanitize-overflow-pattern-exclusion=`` flag which can be used
298+
to disable specific overflow-dependent code patterns. The supported patterns
299+
are: ``add-overflow-test``, ``negated-unsigned-const``, and
300+
``post-decr-while``. The sanitizer instrumentation can be toggled off for all
301+
available patterns by specifying ``all``. Conversely, you can disable all
302+
exclusions with ``none``.
302303

303304
.. code-block:: c++
304305

306+
/// specified with ``-fsanitize-overflow-pattern-exclusion=add-overflow-test``
307+
int common_overflow_check_pattern(unsigned base, unsigned offset) {
308+
if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented
309+
}
310+
311+
/// specified with ``-fsanitize-overflow-pattern-exclusion=negated-unsigned-const``
305312
void negation_overflow() {
306313
unsigned long foo = -1UL; // No longer causes a negation overflow warning
307314
unsigned long bar = -2UL; // and so on...
308315
}
309316

317+
/// specified with ``-fsanitize-overflow-pattern-exclusion=post-decr-while``
310318
void while_post_decrement() {
311319
unsigned char count = 16;
312320
while (count--) { /* ... */} // No longer causes unsigned-integer-overflow sanitizer to trip
313321
}
314322
315-
int common_overflow_check_pattern(unsigned base, unsigned offset) {
316-
if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented
317-
}
318-
319-
Note that the ``-fsanitize-overflow-idioms`` flag now also exists but has
320-
virtually no function other than to disable an already present
321-
``-fno-sanitize-overflow-idioms``.
323+
Many existing projects have a large amount of these code patterns present.
324+
This new flag should allow those projects to enable integer sanitizers with
325+
less noise.
322326

323327
Python Binding Changes
324328
----------------------

clang/docs/UndefinedBehaviorSanitizer.rst

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -293,56 +293,58 @@ To silence reports from unsigned integer overflow, you can set
293293
``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for
294294
providing fuzzing signal without blowing up logs.
295295

296-
Issue Suppression
297-
=================
298-
299-
UndefinedBehaviorSanitizer is not expected to produce false positives.
300-
If you see one, look again; most likely it is a true positive!
301-
302-
Disabling Instrumentation with ``__attribute__((no_sanitize("undefined")))``
303-
----------------------------------------------------------------------------
304-
305-
You disable UBSan checks for particular functions with
306-
``__attribute__((no_sanitize("undefined")))``. You can use all values of
307-
``-fsanitize=`` flag in this attribute, e.g. if your function deliberately
308-
contains possible signed integer overflow, you can use
309-
``__attribute__((no_sanitize("signed-integer-overflow")))``.
310-
311-
This attribute may not be
312-
supported by other compilers, so consider using it together with
313-
``#if defined(__clang__)``.
314-
315-
Disabling instrumentation of common overflow idioms
316-
=====================================================
296+
Disabling instrumentation for common overflow patterns
297+
------------------------------------------------------
317298

318-
There are certain overflow-dependent code patterns which produce a lot of noise
319-
for integer overflow/truncation sanitizers. To disable instrumentation for
320-
these common patterns one should use ``-fno-sanitize-overflow-idioms``. Its
321-
inverse ``-fsanitize-overflow-idioms`` also exists but has no function other
322-
than to disable an already present ``-fno-sanitize-overflow-idioms``.
299+
There are certain overflow-dependent or overflow-prone code patterns which
300+
produce a lot of noise for integer overflow/truncation sanitizers. To disable
301+
instrumentation for these common patterns one should use
302+
``-fsanitize-overflow-pattern-exclusion=``.
323303

324-
Currently, this option handles three pervasive overflow-dependent code idioms:
304+
Currently, this option supports three pervasive overflow-dependent code idioms:
325305

326306
.. code-block:: c++
327307

308+
/// -fsanitize-overflow-pattern-exclusion=negated-unsigned-const
328309
unsigned long foo = -1UL; // No longer causes a negation overflow warning
329310
unsigned long bar = -2UL; // and so on...
330311

331312
.. code-block:: c++
332313

314+
/// -fsanitize-overflow-pattern-exclusion=post-decr-while
333315
unsigned char count = 16;
334316
while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
335317
336318
.. code-block:: c++
337319

320+
/// -fsanitize-overflow-pattern-exclusion=add-overflow-test
338321
if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings,
339322
// won't be instrumented (same for signed types)
340323
341324
Negated unsigned constants, post-decrements in a while loop condition and
342-
simple overflow checks are accepted and pervasive code patterns. Existing
343-
projects that enable more warnings or sanitizers may find that the compiler is
344-
too noisy. Now, they can use ``-fno-sanitize-overflow-idioms`` with no source
345-
modifications.
325+
simple overflow checks are accepted and pervasive code patterns. You can enable
326+
all exclusions with ``-fsanitize-overflow-pattern-exclusion=all`` or disable
327+
all exclusions with ``-fsanitize-overflow-pattern-exclusion=none``. Specifying
328+
``none`` has precedence over other values.
329+
330+
Issue Suppression
331+
=================
332+
333+
UndefinedBehaviorSanitizer is not expected to produce false positives.
334+
If you see one, look again; most likely it is a true positive!
335+
336+
Disabling Instrumentation with ``__attribute__((no_sanitize("undefined")))``
337+
----------------------------------------------------------------------------
338+
339+
You disable UBSan checks for particular functions with
340+
``__attribute__((no_sanitize("undefined")))``. You can use all values of
341+
``-fsanitize=`` flag in this attribute, e.g. if your function deliberately
342+
contains possible signed integer overflow, you can use
343+
``__attribute__((no_sanitize("signed-integer-overflow")))``.
344+
345+
This attribute may not be
346+
supported by other compilers, so consider using it together with
347+
``#if defined(__clang__)``.
346348

347349
Suppressing Errors in Recompiled Code (Ignorelist)
348350
--------------------------------------------------

clang/include/clang/Driver/Options.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,11 +2558,6 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
25582558
"Disable">,
25592559
BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
25602560
Group<f_clang_Group>;
2561-
defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
2562-
LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
2563-
PosFlag<SetTrue, [], [], "Enable">,
2564-
NegFlag<SetFalse, [], [], "Disable">,
2565-
BothFlags<[], [ClangOption], " the instrumentation of common overflow idioms">>;
25662561
def fsanitize_overflow_pattern_exclusion_EQ : CommaJoined<["-"], "fsanitize-overflow-pattern-exclusion=">,
25672562
HelpText<"Specify the overflow patterns to exclude from artihmetic sanitizer instrumentation">,
25682563
Visibility<[ClangOption, CC1Option]>,

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ class SanitizerArgs {
6565
// True if cross-dso CFI support if provided by the system (i.e. Android).
6666
bool ImplicitCfiRuntime = false;
6767
bool NeedsMemProfRt = false;
68-
bool SanitizeOverflowIdioms = true;
6968
bool HwasanUseAliases = false;
7069
llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
7170
llvm::AsanDetectStackUseAfterReturnMode::Invalid;

clang/lib/AST/Expr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4760,12 +4760,12 @@ ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx,
47604760
}
47614761

47624762
namespace {
4763-
/// Certain overflow-dependent code idioms can have their integer overflow
4763+
/// Certain overflow-dependent code patterns can have their integer overflow
47644764
/// sanitization disabled. Check for the common pattern `if (a + b < a)` and
47654765
/// return the resulting BinaryOperator responsible for the addition so we can
47664766
/// elide overflow checks during codegen.
47674767
static std::optional<BinaryOperator *>
4768-
getOverflowIdiomBinOp(const BinaryOperator *E) {
4768+
getOverflowPatternBinOp(const BinaryOperator *E) {
47694769
Expr *Addition, *ComparedTo;
47704770
if (E->getOpcode() == BO_LT) {
47714771
Addition = E->getLHS();
@@ -4821,7 +4821,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
48214821
SubExprs[RHS] = rhs;
48224822
if (Ctx.getLangOpts().isOverflowPatternExcluded(
48234823
LangOptions::OverflowPatternExclusionKind::AddOverflowTest)) {
4824-
std::optional<BinaryOperator *> Result = getOverflowIdiomBinOp(this);
4824+
std::optional<BinaryOperator *> Result = getOverflowPatternBinOp(this);
48254825
if (Result.has_value())
48264826
Result.value()->ExcludedOverflowPattern = true;
48274827
}

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,7 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
198198

199199
const UnaryOperator *UO = dyn_cast<UnaryOperator>(Op.E);
200200

201-
// TODO: rename or rework NegUnsignedConst because it doesn't only work on
202-
// constants.
203-
if (UO && UO->getOpcode() == UO_Minus &&
201+
if (UO && UO->getOpcode() == UO_Minus && UO->isIntegerConstantExpr(Ctx) &&
204202
Ctx.getLangOpts().isOverflowPatternExcluded(
205203
LangOptions::OverflowPatternExclusionKind::NegUnsignedConst))
206204
return true;

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,10 +1080,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
10801080
options::OPT_fmemory_profile_EQ,
10811081
options::OPT_fno_memory_profile, false);
10821082

1083-
SanitizeOverflowIdioms =
1084-
Args.hasFlag(options::OPT_fsanitize_overflow_idioms,
1085-
options::OPT_fno_sanitize_overflow_idioms, true);
1086-
10871083
// Finally, initialize the set of available and recoverable sanitizers.
10881084
Sanitizers.Mask |= Kinds;
10891085
RecoverableSanitizers.Mask |= RecoverableKinds;
@@ -1375,9 +1371,6 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
13751371
CmdArgs.push_back("+tagged-globals");
13761372
}
13771373

1378-
if (!SanitizeOverflowIdioms)
1379-
CmdArgs.push_back("-fno-sanitize-overflow-idioms");
1380-
13811374
// MSan: Workaround for PR16386.
13821375
// ASan: This is mainly to help LSan with cases such as
13831376
// https://github.com/google/sanitizers/issues/373

clang/test/CodeGen/overflow-idiom-exclusion-fp.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Check for potential false positives from patterns that _almost_ match classic overflow idioms
1+
// Check for potential false positives from patterns that _almost_ match classic overflow-dependent or overflow-prone code patterns
22
// RUN: %clang %s -O2 -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-overflow-pattern-exclusion=all -S -emit-llvm -o - | FileCheck %s
33
// RUN: %clang %s -O2 -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-overflow-pattern-exclusion=all -fwrapv -S -emit-llvm -o - | FileCheck %s
44

@@ -8,7 +8,8 @@ extern int u, v, w;
88
extern unsigned some(void);
99

1010
// Make sure all these still have handler paths, we shouldn't be excluding
11-
// instrumentation of any "near" idioms.
11+
// instrumentation of any "near" patterns.
12+
// CHECK-LABEL: close_but_not_quite
1213
void close_but_not_quite(void) {
1314
// CHECK: br i1{{.*}}handler.
1415
if (a + b > a)
@@ -26,6 +27,7 @@ void close_but_not_quite(void) {
2627
if (a + b + 1 < a)
2728
c = 9;
2829

30+
// CHECK: br i1{{.*}}handler.
2931
// CHECK: br i1{{.*}}handler.
3032
if (a + b < a + 1)
3133
c = 9;
@@ -42,10 +44,6 @@ void close_but_not_quite(void) {
4244
if (a + b == a)
4345
c = 9;
4446

45-
// CHECK: br i1{{.*}}handler
46-
if (u + v < u) /* matches overflow idiom, but is signed */
47-
c = 9;
48-
4947
// CHECK: br i1{{.*}}handler
5048
// Although this can never actually overflow we are still checking that the
5149
// sanitizer instruments it.
@@ -54,14 +52,15 @@ void close_but_not_quite(void) {
5452
}
5553

5654
// cvise'd kernel code that caused problems during development
57-
// CHECK: br i1{{.*}}handler
5855
typedef unsigned size_t;
5956
typedef enum { FSE_repeat_none } FSE_repeat;
6057
typedef enum { ZSTD_defaultAllowed } ZSTD_defaultPolicy_e;
6158
FSE_repeat ZSTD_selectEncodingType_repeatMode;
6259
ZSTD_defaultPolicy_e ZSTD_selectEncodingType_isDefaultAllowed;
6360
size_t ZSTD_NCountCost(void);
6461

62+
// CHECK-LABEL: ZSTD_selectEncodingType
63+
// CHECK: br i1{{.*}}handler
6564
void ZSTD_selectEncodingType(void) {
6665
size_t basicCost =
6766
ZSTD_selectEncodingType_isDefaultAllowed ? ZSTD_NCountCost() : 0,
@@ -70,8 +69,15 @@ void ZSTD_selectEncodingType(void) {
7069
ZSTD_selectEncodingType_repeatMode = FSE_repeat_none;
7170
}
7271

72+
// CHECK-LABEL: function_calls
7373
void function_calls(void) {
7474
// CHECK: br i1{{.*}}handler
7575
if (some() + b < some())
7676
c = 9;
7777
}
78+
79+
// CHECK-LABEL: not_quite_a_negated_unsigned_const
80+
void not_quite_a_negated_unsigned_const(void) {
81+
// CHECK: br i1{{.*}}handler
82+
a = -b;
83+
}

clang/test/CodeGen/overflow-idiom-exclusion.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Ensure some common idioms don't trigger the overflow sanitizers when
2-
// -fno-sanitize-overflow-idioms is enabled. In many cases, overflow warnings
3-
// caused by these idioms are seen as "noise" and result in users turning off
1+
// Ensure some common overflow-dependent or overflow-prone code patterns don't
2+
// trigger the overflow sanitizers. In many cases, overflow warnings caused by
3+
// these patterns are seen as "noise" and result in users turning off
44
// sanitization all together.
55

66
// A pattern like "if (a + b < a)" simply checks for overflow and usually means
@@ -9,8 +9,7 @@
99
// Similarly, a pattern resembling "while (i--)" is extremely common and
1010
// warning on its inevitable overflow can be seen as superfluous. Do note that
1111
// using "i" in future calculations can be tricky because it will still
12-
// wrap-around. Using -fno-sanitize-overflow-idioms or not doesn't change this
13-
// fact -- we just won't warn/trap with sanitizers.
12+
// wrap-around.
1413

1514
// Another common pattern that, in some cases, is found to be too noisy is
1615
// unsigned negation, for example:
@@ -107,7 +106,7 @@ void nestedstructs(void) {
107106
}
108107

109108
// Normally, this would be folded into a simple call to the overflow handler
110-
// and a store. Excluding this idiom results in just a store.
109+
// and a store. Excluding this pattern results in just a store.
111110
void constants(void) {
112111
unsigned base = 4294967295;
113112
unsigned offset = 1;

0 commit comments

Comments
 (0)