[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
PiotrZSL wrote: @BenBlaise Clang-tidy 19 branch out is in ... a month. Any plans to finish this ? It's fine if this would get in limited scope (only for explicit casts), but some current issues need fixes. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
PiotrZSL wrote: @BenBlaise Ok, no problem, then it will get into next release. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
BenBlaise wrote: I would like to, but I won't get around to it by then (concentrating on a thesis defense for tomorrow). https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
PiotrZSL wrote: @BenBlaise Any plans to finish this ? Clang-tidy 18 branch-out is in ~3 days. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), + this); +} + +static StringRef getRawStringRef(const SourceRange , + const SourceManager , + const LangOptions ) { + CharSourceRange TextRange = Lexer::getAsCharRange(Range, Sources, LangOpts); + return Lexer::getSourceText(TextRange, Sources, LangOpts); +} + +void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { + + const auto = *Result.SourceManager; + const auto = Result.Nodes; + + const auto *MatchedCast = Nodes.getNodeAs("expr"); + const auto *Lit = Nodes.getNodeAs("lit"); + assert(MatchedCast && Lit); + + StringRef LitText = getRawStringRef(Lit->getExprLoc(), SM, getLangOpts()); + std::string CastType = MatchedCast->getTypeAsWritten().getAsString(); + std::string Fix; // Replacement string for the fix-it hint. + std::optional Seq; // Literal sequence, prefix or suffix. + + if (const auto *CharLit = Nodes.getNodeAs("char"); + CharLit && CharPrefix.contains(CastType)) { +if (const Replacement = CharPrefix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!CharLit->getLocation().isMacroID()) { +Fix.append(Rep.Seq); +Fix.append(CharRegex.sub("", LitText.str())); + } +} + } else if (const auto *IntLit = Nodes.getNodeAs("int"); + IntLit && IntSuffix.contains(CastType)) { +if (const Replacement = IntSuffix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!IntLit->getLocation().isMacroID()) { +Fix.append(IntRegex.sub("", LitText.str())); +Fix.append(Rep.Seq); + } +} + } else if (const auto *FloatLit = Nodes.getNodeAs("float"); + FloatLit && FloatSuffix.contains(CastType)) { +if (const Replacement = FloatSuffix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!FloatLit->getLocation().isMacroID()) { +Fix.append(FloatRegex.sub("", LitText.str())); +Fix.append(Rep.Seq); + } +} + } + + const TypeLoc CastTypeLoc = MatchedCast->getTypeInfoAsWritten()->getTypeLoc(); + + if (!Fix.empty() && !CastTypeLoc.getBeginLoc().isMacroID()) { + +// Recommend
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), + this); +} + +static StringRef getRawStringRef(const SourceRange , + const SourceManager , + const LangOptions ) { + CharSourceRange TextRange = Lexer::getAsCharRange(Range, Sources, LangOpts); + return Lexer::getSourceText(TextRange, Sources, LangOpts); +} + +void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { + + const auto = *Result.SourceManager; + const auto = Result.Nodes; + + const auto *MatchedCast = Nodes.getNodeAs("expr"); + const auto *Lit = Nodes.getNodeAs("lit"); + assert(MatchedCast && Lit); + + StringRef LitText = getRawStringRef(Lit->getExprLoc(), SM, getLangOpts()); + std::string CastType = MatchedCast->getTypeAsWritten().getAsString(); + std::string Fix; // Replacement string for the fix-it hint. + std::optional Seq; // Literal sequence, prefix or suffix. + + if (const auto *CharLit = Nodes.getNodeAs("char"); + CharLit && CharPrefix.contains(CastType)) { +if (const Replacement = CharPrefix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!CharLit->getLocation().isMacroID()) { +Fix.append(Rep.Seq); +Fix.append(CharRegex.sub("", LitText.str())); + } +} + } else if (const auto *IntLit = Nodes.getNodeAs("int"); + IntLit && IntSuffix.contains(CastType)) { +if (const Replacement = IntSuffix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!IntLit->getLocation().isMacroID()) { +Fix.append(IntRegex.sub("", LitText.str())); +Fix.append(Rep.Seq); + } +} + } else if (const auto *FloatLit = Nodes.getNodeAs("float"); + FloatLit && FloatSuffix.contains(CastType)) { +if (const Replacement = FloatSuffix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!FloatLit->getLocation().isMacroID()) { +Fix.append(FloatRegex.sub("", LitText.str())); +Fix.append(Rep.Seq); + } +} + } + + const TypeLoc CastTypeLoc = MatchedCast->getTypeInfoAsWritten()->getTypeLoc(); + + if (!Fix.empty() && !CastTypeLoc.getBeginLoc().isMacroID()) { + +// Recommend
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,105 @@ +// RUN: %check_clang_tidy %s readability-use-builtin-literals %t + +void warn_and_fix() { + + (char16_t)U'a'; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: u'a'; + (char32_t)u'a'; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: U'a'; + + (int)1; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 1; + (unsigned int)0x1ul; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 0x1u; + (long int)2l; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2L; + (unsigned long int)0x2lu; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 0x2uL; + (long long int)3ll; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 3LL; + (unsigned long long int)0x3llu; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 0x3uLL; + + (double)1.f; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 1.; + (float)2.; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2.f; + (long double)3e0f; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 3e0L; + + float(2.); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2.f; + double{2.}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2.; + + static_cast(2.f); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2.; + + reinterpret_cast(1); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 1; +} + +#define OPSHIFT ((unsigned)27) +#define OCHAR (2LU< +T f() { + return T(1); +} + +int no_warn() { + +(void)0; +(unsigned*)0; + +static_cast(INT_MAX); +(unsigned)MAXCOL; + +(SUINT)31; + +return f(); +} PiotrZSL wrote: Missing test for `size_t` and lack of warning & fix. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,38 @@ +.. title:: clang-tidy - readability-use-builtin-literals + +readability-use-builtin-literals + + +Finds literals explicitly casted to a type that could be expressed using builtin prefixes or suffixes. + +In elementary cases, provides automated fix-it hints. + +.. code-block:: c++ + +(char)'a';// -> 'a' PiotrZSL wrote: list here all supported types, for example in form of table, like type, example, replacement. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), + this); +} + +static StringRef getRawStringRef(const SourceRange , + const SourceManager , + const LangOptions ) { + CharSourceRange TextRange = Lexer::getAsCharRange(Range, Sources, LangOpts); + return Lexer::getSourceText(TextRange, Sources, LangOpts); +} + +void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { + + const auto = *Result.SourceManager; + const auto = Result.Nodes; + + const auto *MatchedCast = Nodes.getNodeAs("expr"); + const auto *Lit = Nodes.getNodeAs("lit"); + assert(MatchedCast && Lit); + + StringRef LitText = getRawStringRef(Lit->getExprLoc(), SM, getLangOpts()); + std::string CastType = MatchedCast->getTypeAsWritten().getAsString(); PiotrZSL wrote: double read of getTypeInfoAsWritten, read it once and assign to local variable. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, PiotrZSL wrote: Missing check for C++17. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,105 @@ +// RUN: %check_clang_tidy %s readability-use-builtin-literals %t + +void warn_and_fix() { + + (char16_t)U'a'; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: u'a'; + (char32_t)u'a'; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: U'a'; + + (int)1; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 1; + (unsigned int)0x1ul; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 0x1u; + (long int)2l; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2L; + (unsigned long int)0x2lu; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 0x2uL; + (long long int)3ll; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 3LL; + (unsigned long long int)0x3llu; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 0x3uLL; + + (double)1.f; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 1.; + (float)2.; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 2.f; + (long double)3e0f; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use built-in literal instead of explicit cast [readability-use-builtin-literals] + // CHECK-FIXES: 3e0L; + PiotrZSL wrote: missing tests for: - float16_t - float32_t - float64_t - float128_t - bfloat16 https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), + this); +} + +static StringRef getRawStringRef(const SourceRange , + const SourceManager , + const LangOptions ) { + CharSourceRange TextRange = Lexer::getAsCharRange(Range, Sources, LangOpts); + return Lexer::getSourceText(TextRange, Sources, LangOpts); +} + +void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { + + const auto = *Result.SourceManager; + const auto = Result.Nodes; + + const auto *MatchedCast = Nodes.getNodeAs("expr"); + const auto *Lit = Nodes.getNodeAs("lit"); + assert(MatchedCast && Lit); + + StringRef LitText = getRawStringRef(Lit->getExprLoc(), SM, getLangOpts()); + std::string CastType = MatchedCast->getTypeAsWritten().getAsString(); + std::string Fix; // Replacement string for the fix-it hint. + std::optional Seq; // Literal sequence, prefix or suffix. + + if (const auto *CharLit = Nodes.getNodeAs("char"); + CharLit && CharPrefix.contains(CastType)) { +if (const Replacement = CharPrefix.at(CastType); Rep(getLangOpts())) { + + Seq = Rep.Seq; + if (!CharLit->getLocation().isMacroID()) { PiotrZSL wrote: Add option IgnoreMacros to check, to handle this situation. You may also use get SpellingLocation to actualy do a replacement where that literal is in code. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), + this); +} + +static StringRef getRawStringRef(const SourceRange , + const SourceManager , + const LangOptions ) { + CharSourceRange TextRange = Lexer::getAsCharRange(Range, Sources, LangOpts); + return Lexer::getSourceText(TextRange, Sources, LangOpts); +} + +void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { + + const auto = *Result.SourceManager; + const auto = Result.Nodes; + + const auto *MatchedCast = Nodes.getNodeAs("expr"); + const auto *Lit = Nodes.getNodeAs("lit"); + assert(MatchedCast && Lit); + + StringRef LitText = getRawStringRef(Lit->getExprLoc(), SM, getLangOpts()); + std::string CastType = MatchedCast->getTypeAsWritten().getAsString(); + std::string Fix; // Replacement string for the fix-it hint. + std::optional Seq; // Literal sequence, prefix or suffix. + + if (const auto *CharLit = Nodes.getNodeAs("char"); + CharLit && CharPrefix.contains(CastType)) { PiotrZSL wrote: double search of CastType in map, consider spliting those 3 ifs into 3 methods. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, PiotrZSL wrote: use "U" instead of "u", to be in sync with readability-uppercase-literal-suffix check. Verify also other suffixes. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( PiotrZSL wrote: `ignoringParenImpCasts` doesn't look to be needed because TK_IgnoreUnlessSpelledInSource is used, and without it all tests still pass. Remove or add tests to cover this. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), PiotrZSL wrote: change this "expr" into "cast", as later in check method is not so clear what it refers. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( PiotrZSL wrote: Do not make matchers `static`, this can be problematic https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
https://github.com/PiotrZSL requested changes to this pull request. Overall what is now is +- working. Few fixes are still needed to tests, code, maybe some tiny refactoring and code formatting. Consider adding support for implicit casts: ``` unsigned X = 10; `-VarDecl col:10 X 'unsigned int' cinit `-ImplicitCastExpr 'unsigned int' `-IntegerLiteral 'int' 10 ``` To: ``` unsigned X = 10U; `-VarDecl col:10 X 'unsigned int' cinit `-IntegerLiteral 'unsigned int' 10 ``` I worry also a little bit about integer overflow issues. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
https://github.com/PiotrZSL edited https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,38 @@ +.. title:: clang-tidy - readability-use-builtin-literals + +readability-use-builtin-literals + + +Finds literals explicitly casted to a type that could be expressed using builtin prefixes or suffixes. EugeneZelenko wrote: Please follow 80-characters limit. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
https://github.com/EugeneZelenko edited https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
https://github.com/EugeneZelenko requested changes to this pull request. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
@@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +}); + +static const llvm::Regex FloatRegex( +"([fF]|[lL]|([fF]16)|([fF]32)|([fF]64)|([fF]128)|((bf|BF)16))?$"); +static const llvm::StringMap FloatSuffix({ +{"double", {""}}, +{"float", {"f"}}, +{"long double", {"L"}}, +{"std::float16_t", {"f16"}}, +{"std::float32_t", {"f32"}}, +{"std::float64_t", {"f64"}}, +{"std::float128_t", {"f128"}}, +{"std::bfloat16_t", {"bf16"}}, +{"float16_t", {"f16"}}, +{"float32_t", {"f32"}}, +{"float64_t", {"f64"}}, +{"float128_t", {"f128"}}, +{"bfloat16_t", {"bf16"}}, +}); + +void UseBuiltinLiteralsCheck::registerMatchers(MatchFinder *Finder) { + static const auto Literal = has(ignoringParenImpCasts( + expr(anyOf(characterLiteral().bind("char"), integerLiteral().bind("int"), + floatLiteral().bind("float"))) + .bind("lit"))); + Finder->addMatcher( + traverse(TK_IgnoreUnlessSpelledInSource, + explicitCastExpr(anyOf(Literal, has(initListExpr(Literal + .bind("expr")), + this); +} + +static StringRef getRawStringRef(const SourceRange , + const SourceManager , + const LangOptions ) { + CharSourceRange TextRange = Lexer::getAsCharRange(Range, Sources, LangOpts); + return Lexer::getSourceText(TextRange, Sources, LangOpts); +} + +void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { + + const auto = *Result.SourceManager; EugeneZelenko wrote: Please don't use `auto` unless type is explicitly stated in same statement or iterator. Same in other places. https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 7767c5856d85cd1acf2efc32f77fdf07f00f9ff4 b4d7dbcf67117471a2d7025013fb1fcd188b33b6 -- clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.h clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals-cpp17.cpp clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals-cpp23.cpp clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals.cpp clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp `` View the diff from clang-format here. ``diff diff --git a/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp index ede4651789..6a10fbd51c 100644 --- a/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp @@ -104,7 +104,7 @@ void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { StringRef LitText = getRawStringRef(Lit->getExprLoc(), SM, getLangOpts()); std::string CastType = MatchedCast->getTypeAsWritten().getAsString(); - std::string Fix; // Replacement string for the fix-it hint. + std::string Fix; // Replacement string for the fix-it hint. std::optional Seq; // Literal sequence, prefix or suffix. if (const auto *CharLit = Nodes.getNodeAs("char"); @@ -153,8 +153,8 @@ void UseBuiltinLiteralsCheck::check(const MatchFinder::MatchResult ) { diag(MatchedCast->getExprLoc(), "use built-in '%0' %1 instead of explicit cast to '%2'") << *Seq - << (Nodes.getNodeAs("char") ? "prefix" : "suffix") - << CastType; +<< (Nodes.getNodeAs("char") ? "prefix" : "suffix") +<< CastType; } } `` https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
llvmbot wrote: @llvm/pr-subscribers-clang-tidy Author: None (BenBlaise) Changes Finds literals explicitly casted to a type that could be expressed using builtin prefixes or suffixes. In elementary cases, provides automated fix-it hints. ```cpp (char)'a';// - 'a' (char16_t)U'a'; // - u'a' static_castunsigned int(0x1ul); // - 0x1u reinterpret_castlong long int(3ll); // - 3LL float(2.);// - 2.f double{2.}; // - 2. ``` Defined for character, integer and floating literals. --- Full diff: https://github.com/llvm/llvm-project/pull/76065.diff 10 Files Affected: - (modified) clang-tools-extra/clang-tidy/readability/CMakeLists.txt (+1) - (modified) clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp (+3) - (added) clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp (+161) - (added) clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.h (+37) - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+6) - (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) - (added) clang-tools-extra/docs/clang-tidy/checks/readability/use-builtin-literals.rst (+38) - (added) clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals-cpp17.cpp (+11) - (added) clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals-cpp23.cpp (+19) - (added) clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals.cpp (+105) ``diff diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 5452c2d48a4617..3c5e12aaeb3bd4 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -51,6 +51,7 @@ add_clang_library(clangTidyReadabilityModule UniqueptrDeleteReleaseCheck.cpp UppercaseLiteralSuffixCheck.cpp UseAnyOfAllOfCheck.cpp + UseBuiltinLiteralsCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index b8e6e641432060..b0ec5a906cac55 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -54,6 +54,7 @@ #include "UniqueptrDeleteReleaseCheck.h" #include "UppercaseLiteralSuffixCheck.h" #include "UseAnyOfAllOfCheck.h" +#include "UseBuiltinLiteralsCheck.h" namespace clang::tidy { namespace readability { @@ -151,6 +152,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-uppercase-literal-suffix"); CheckFactories.registerCheck( "readability-use-anyofallof"); +CheckFactories.registerCheck( +"readability-use-builtin-literals"); } }; diff --git a/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp new file mode 100644 index 00..ede46517898d87 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp @@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static const llvm::Regex CharRegex("^(u8|u|U|L)?"); +static const llvm::StringMap CharPrefix({ +{"char", {""}}, +{"char8_t", {"u8"}}, +{"char16_t", {"u"}}, +{"char32_t", {"U"}}, +{"wchar_t", {"L"}}, +}); + +static const llvm::Regex + IntRegex("(([uU]?[lL]{0,2})|([lL]{0,2}[uU]?)|([uU]?[zZ]?)|([zZ]?[uU]?))?$"); +static const llvm::StringMap IntSuffix({ +{"int", {""}}, +{"unsigned int", {"u"}}, +{"long", {"L"}}, +{"unsigned long", {"uL"}}, +{"long long", {"LL"}}, +{"unsigned long long", {"uLL"}}, +{"size_t", {"uz", [](const auto ) { return LS.isCPlusPlus23(); }}}, +{"std::size_t", {"uz",
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/76065 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add readability-use-builtin-literals check (PR #76065)
https://github.com/BenBlaise created https://github.com/llvm/llvm-project/pull/76065 Finds literals explicitly casted to a type that could be expressed using builtin prefixes or suffixes. In elementary cases, provides automated fix-it hints. ```cpp (char)'a';// -> 'a' (char16_t)U'a'; // -> u'a' static_cast(0x1ul); // -> 0x1u reinterpret_cast(3ll); // -> 3LL float(2.);// -> 2.f double{2.}; // -> 2. ``` Defined for character, integer and floating literals. >From b4d7dbcf67117471a2d7025013fb1fcd188b33b6 Mon Sep 17 00:00:00 2001 From: Benedict Blaise Date: Wed, 20 Dec 2023 16:07:10 +0100 Subject: [PATCH] [clang-tidy] Add readability-use-builtin-literals check Finds literals explicitly casted to a type that could be expressed using builtin prefixes or suffixes. In elementary cases, provides automated fix-it hints. Defined for character, integer and floating literals. --- .../clang-tidy/readability/CMakeLists.txt | 1 + .../readability/ReadabilityTidyModule.cpp | 3 + .../readability/UseBuiltinLiteralsCheck.cpp | 161 ++ .../readability/UseBuiltinLiteralsCheck.h | 37 clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../readability/use-builtin-literals.rst | 38 + .../use-builtin-literals-cpp17.cpp| 11 ++ .../use-builtin-literals-cpp23.cpp| 19 +++ .../readability/use-builtin-literals.cpp | 105 10 files changed, 382 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/use-builtin-literals.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals-cpp17.cpp create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals-cpp23.cpp create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/use-builtin-literals.cpp diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 5452c2d48a4617..3c5e12aaeb3bd4 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -51,6 +51,7 @@ add_clang_library(clangTidyReadabilityModule UniqueptrDeleteReleaseCheck.cpp UppercaseLiteralSuffixCheck.cpp UseAnyOfAllOfCheck.cpp + UseBuiltinLiteralsCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index b8e6e641432060..b0ec5a906cac55 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -54,6 +54,7 @@ #include "UniqueptrDeleteReleaseCheck.h" #include "UppercaseLiteralSuffixCheck.h" #include "UseAnyOfAllOfCheck.h" +#include "UseBuiltinLiteralsCheck.h" namespace clang::tidy { namespace readability { @@ -151,6 +152,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-uppercase-literal-suffix"); CheckFactories.registerCheck( "readability-use-anyofallof"); +CheckFactories.registerCheck( +"readability-use-builtin-literals"); } }; diff --git a/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp new file mode 100644 index 00..ede46517898d87 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/UseBuiltinLiteralsCheck.cpp @@ -0,0 +1,161 @@ +//===--- UseBuiltinLiteralsCheck.cpp - clang-tidy -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseBuiltinLiteralsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +using RuleOnStd = bool (*)(const LangStandard ); + +struct Replacement { + Replacement(StringRef Seq, const RuleOnStd Std = nullptr) + : Seq(Seq), Std(Std) {} + bool operator()(const LangOptions ) const { +return Std ? Std(LangStandard::getLangStandardForKind(LO.LangStd)) : true; + } + StringRef Seq; + RuleOnStd Std; +}; + +} // namespace + +static