Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11789,10 +11789,11 @@ static bool checkForArray(const Expr *E) {
/// Detect patterns ptr + size >= ptr and ptr + size < ptr, where ptr is a
/// pointer and size is an unsigned integer. Return whether the result is
/// always true/false.
static std::optional<bool> isTautologicalBoundsCheck(const Expr *LHS,
static std::optional<bool> isTautologicalBoundsCheck(Sema &S, const Expr *LHS,
const Expr *RHS,
BinaryOperatorKind Opc) {
if (!LHS->getType()->isPointerType())
if (!LHS->getType()->isPointerType() ||
S.getLangOpts().isSignedOverflowDefined())
return std::nullopt;

// Canonicalize to >= or < predicate.
Expand Down Expand Up @@ -11940,7 +11941,7 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
<< 1 /*array comparison*/
<< Result);
} else if (std::optional<bool> Res =
isTautologicalBoundsCheck(LHS, RHS, Opc)) {
isTautologicalBoundsCheck(S, LHS, RHS, Opc)) {
S.DiagRuntimeBehavior(Loc, nullptr,
S.PDiag(diag::warn_comparison_always)
<< 2 /*pointer comparison*/
Expand Down
50 changes: 41 additions & 9 deletions clang/test/Sema/tautological-pointer-comparison.c
Original file line number Diff line number Diff line change
@@ -1,40 +1,72 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -DFWRAPV -fwrapv -verify %s

#ifdef FWRAPV
// expected-no-diagnostics
#endif

int add_ptr_idx_ult_ptr(const char *ptr, unsigned index) {
return ptr + index < ptr; // expected-warning {{pointer comparison always evaluates to false}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to false}}
#endif
return ptr + index < ptr;
}

int add_idx_ptr_ult_ptr(const char *ptr, unsigned index) {
return index + ptr < ptr; // expected-warning {{pointer comparison always evaluates to false}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to false}}
#endif
return index + ptr < ptr;
}

int ptr_ugt_add_ptr_idx(const char *ptr, unsigned index) {
return ptr > ptr + index; // expected-warning {{pointer comparison always evaluates to false}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to false}}
#endif
return ptr > ptr + index;
}

int ptr_ugt_add_idx_ptr(const char *ptr, unsigned index) {
return ptr > index + ptr; // expected-warning {{pointer comparison always evaluates to false}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to false}}
#endif
return ptr > index + ptr;
}

int add_ptr_idx_uge_ptr(const char *ptr, unsigned index) {
return ptr + index >= ptr; // expected-warning {{pointer comparison always evaluates to true}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to true}}
#endif
return ptr + index >= ptr;
}

int add_idx_ptr_uge_ptr(const char *ptr, unsigned index) {
return index + ptr >= ptr; // expected-warning {{pointer comparison always evaluates to true}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to true}}
#endif
return index + ptr >= ptr;
}

int ptr_ule_add_ptr_idx(const char *ptr, unsigned index) {
return ptr <= ptr + index; // expected-warning {{pointer comparison always evaluates to true}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to true}}
#endif
return ptr <= ptr + index;
}

int ptr_ule_add_idx_ptr(const char *ptr, unsigned index) {
return ptr <= index + ptr; // expected-warning {{pointer comparison always evaluates to true}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to true}}
#endif
return ptr <= index + ptr;
}

int add_ptr_idx_ult_ptr_array(unsigned index) {
char ptr[10];
return ptr + index < ptr; // expected-warning {{pointer comparison always evaluates to false}}
#ifndef FWRAPV
// expected-warning@+2 {{pointer comparison always evaluates to false}}
#endif
return ptr + index < ptr;
}

// Negative tests with wrong predicate.
Expand Down
Loading