Skip to content

Commit

Permalink
[clang-tidy] Fix false-positives in misc-static-assert caused by non-…
Browse files Browse the repository at this point in the history
…constexpr variables (#77203)

Ignore false-positives when referring to non-constexpr variables in
non-unevaluated context (like decltype, sizeof, ...).

Moved from https://reviews.llvm.org/D158657

Fixes: #24066
  • Loading branch information
PiotrZSL committed Jan 12, 2024
1 parent 8887178 commit 3af6ae0
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
10 changes: 9 additions & 1 deletion clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "StaticAssertCheck.h"
#include "../utils/Matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
Expand Down Expand Up @@ -45,13 +46,20 @@ void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
IsAlwaysFalse);
auto NonConstexprFunctionCall =
callExpr(hasDeclaration(functionDecl(unless(isConstexpr()))));
auto NonConstexprVariableReference =
declRefExpr(to(varDecl(unless(isConstexpr()))),
unless(hasAncestor(expr(matchers::hasUnevaluatedContext()))),
unless(hasAncestor(typeLoc())));

auto NonConstexprCode =
expr(anyOf(NonConstexprFunctionCall, NonConstexprVariableReference));
auto AssertCondition =
expr(
anyOf(expr(ignoringParenCasts(anyOf(
AssertExprRoot, unaryOperator(hasUnaryOperand(
ignoringParenCasts(AssertExprRoot)))))),
anything()),
unless(findAll(NonConstexprFunctionCall)))
unless(NonConstexprCode), unless(hasDescendant(NonConstexprCode)))
.bind("condition");
auto Condition =
anyOf(ignoringParenImpCasts(callExpr(
Expand Down
6 changes: 5 additions & 1 deletion clang-tools-extra/docs/ReleaseNotes.rst
Expand Up @@ -119,7 +119,7 @@ Improvements to clang-tidy

- Improved `--dump-config` to print check options in alphabetical order.

- Improved :program:`clang-tidy-diff.py` script.
- Improved :program:`clang-tidy-diff.py` script.
* Return exit code `1` if any :program:`clang-tidy` subprocess exits with
a non-zero code or if exporting fixes fails.

Expand Down Expand Up @@ -381,6 +381,10 @@ Changes in existing checks
<clang-tidy/checks/misc/redundant-expression>` check to ignore
false-positives in unevaluated context (e.g., ``decltype``).

- Improved :doc:`misc-static-assert
<clang-tidy/checks/misc/static-assert>` check to ignore false-positives when
referring to non-``constexpr`` variables in non-unevaluated context.

- Improved :doc:`misc-unused-using-decls
<clang-tidy/checks/misc/unused-using-decls>` check to avoid false positive when
using in elaborated type and only check cpp files.
Expand Down
42 changes: 42 additions & 0 deletions clang-tools-extra/test/clang-tidy/checkers/misc/static-assert.cpp
Expand Up @@ -20,6 +20,48 @@ void print(...);
#define my_macro() assert(0 == 1)
// CHECK-FIXES: #define my_macro() assert(0 == 1)

namespace PR24066 {

void referenceMember() {
struct {
int A;
int B;
} S;
assert(&S.B - &S.A == 1);
}

const int X = 1;
void referenceVariable() {
assert(X > 0);
}


constexpr int Y = 1;
void referenceConstexprVariable() {
assert(Y > 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
// CHECK-FIXES-CXX11: {{^ }}static_assert(Y > 0, "");
// CHECK-FIXES-CXX17: {{^ }}static_assert(Y > 0);
}

void useInSizeOf() {
char a = 0;
assert(sizeof(a) == 1U);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
// CHECK-FIXES-CXX11: {{^ }}static_assert(sizeof(a) == 1U, "");
// CHECK-FIXES-CXX17: {{^ }}static_assert(sizeof(a) == 1U);
}

void useInDecltype() {
char a = 0;
assert(static_cast<decltype(a)>(256) == 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
// CHECK-FIXES-CXX11: {{^ }}static_assert(static_cast<decltype(a)>(256) == 0, "");
// CHECK-FIXES-CXX17: {{^ }}static_assert(static_cast<decltype(a)>(256) == 0);
}

}

constexpr bool myfunc(int a, int b) { return a * b == 0; }

typedef __SIZE_TYPE__ size_t;
Expand Down

0 comments on commit 3af6ae0

Please sign in to comment.