[clang] Tweaked fixit for static assert with no message

If a static assert has a message as the right side of an and condition, suggest a fix it of replacing the '&&' to ','.

`static_assert(cond && "Failed Cond")` -> `static_assert(cond, "Failed cond")`

This use case comes up when lazily replacing asserts with static asserts.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D89065
This commit is contained in:
Nathan James 2021-02-22 17:43:52 +00:00
parent 5e7e499b91
commit 5616c5b866
No known key found for this signature in database
GPG key ID: CC007AFCDA90AA5F
2 changed files with 42 additions and 6 deletions

View file

@ -856,6 +856,16 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator(
DeclFromDeclSpec);
}
static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr,
SourceLocation EndExprLoc) {
if (const auto *BO = dyn_cast_or_null<BinaryOperator>(AssertExpr)) {
if (BO->getOpcode() == BO_LAnd &&
isa<StringLiteral>(BO->getRHS()->IgnoreImpCasts()))
return FixItHint::CreateReplacement(BO->getOperatorLoc(), ",");
}
return FixItHint::CreateInsertion(EndExprLoc, ", \"\"");
}
/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
///
/// [C++0x] static_assert-declaration:
@ -892,12 +902,11 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
ExprResult AssertMessage;
if (Tok.is(tok::r_paren)) {
Diag(Tok, getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_static_assert_no_message
: diag::ext_static_assert_no_message)
<< (getLangOpts().CPlusPlus17
? FixItHint()
: FixItHint::CreateInsertion(Tok.getLocation(), ", \"\""));
if (getLangOpts().CPlusPlus17)
Diag(Tok, diag::warn_cxx14_compat_static_assert_no_message);
else
Diag(Tok, diag::ext_static_assert_no_message)
<< getStaticAssertNoMessageFixIt(AssertExpr.get(), Tok.getLocation());
} else {
if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::semi);

View file

@ -0,0 +1,27 @@
// RUN: %clang_cc1 -std=c++14 %s -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// Ensure no warnings are emitted in c++17.
// RUN: %clang_cc1 -std=c++17 %s -verify=cxx17
// RUN: %clang_cc1 -std=c++14 %s -fixit-recompile -fixit-to-temporary -Werror
// cxx17-no-diagnostics
static_assert(true && "String");
// CHECK-DAG: {[[@LINE-1]]:20-[[@LINE-1]]:22}:","
// String literal prefixes are good.
static_assert(true && R"(RawString)");
// CHECK-DAG: {[[@LINE-1]]:20-[[@LINE-1]]:22}:","
static_assert(true && L"RawString");
// CHECK-DAG: {[[@LINE-1]]:20-[[@LINE-1]]:22}:","
static_assert(true);
// CHECK-DAG: {[[@LINE-1]]:19-[[@LINE-1]]:19}:", \"\""
// While its technically possible to transform this to
// static_assert(true, "String") we don't attempt this fix.
static_assert("String" && true);
// CHECK-DAG: {[[@LINE-1]]:31-[[@LINE-1]]:31}:", \"\""
// Don't be smart and look in parentheses.
static_assert((true && "String"));
// CHECK-DAG: {[[@LINE-1]]:33-[[@LINE-1]]:33}:", \"\""