Index: clang-tools-extra/trunk/clang-tidy/cert/CERTTidyModule.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/cert/CERTTidyModule.cpp +++ clang-tools-extra/trunk/clang-tidy/cert/CERTTidyModule.cpp @@ -16,6 +16,7 @@ #include "../misc/StaticAssertCheck.h" #include "../misc/ThrowByValueCatchByReferenceCheck.h" #include "../performance/MoveConstructorInitCheck.h" +#include "../readability/UppercaseLiteralSuffixCheck.h" #include "CommandProcessorCheck.h" #include "DontModifyStdNamespaceCheck.h" #include "FloatLoopCounter.h" @@ -65,6 +66,8 @@ // C checkers // DCL CheckFactories.registerCheck("cert-dcl03-c"); + CheckFactories.registerCheck( + "cert-dcl16-c"); // ENV CheckFactories.registerCheck("cert-env33-c"); // FLP @@ -78,6 +81,13 @@ CheckFactories.registerCheck( "cert-msc32-c"); } + + ClangTidyOptions getModuleOptions() override { + ClangTidyOptions Options; + ClangTidyOptions::OptionMap &Opts = Options.CheckOptions; + Opts["cert-dcl16-c.NewSuffixes"] = "L;LL;LU;LLU"; + return Options; + } }; } // namespace cert Index: clang-tools-extra/trunk/clang-tidy/cert/CMakeLists.txt =================================================================== --- clang-tools-extra/trunk/clang-tidy/cert/CMakeLists.txt +++ clang-tools-extra/trunk/clang-tidy/cert/CMakeLists.txt @@ -24,5 +24,6 @@ clangTidyGoogleModule clangTidyMiscModule clangTidyPerformanceModule + clangTidyReadabilityModule clangTidyUtils ) Index: clang-tools-extra/trunk/clang-tidy/hicpp/HICPPTidyModule.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/hicpp/HICPPTidyModule.cpp +++ clang-tools-extra/trunk/clang-tidy/hicpp/HICPPTidyModule.cpp @@ -35,6 +35,7 @@ #include "../readability/BracesAroundStatementsCheck.h" #include "../readability/FunctionSizeCheck.h" #include "../readability/IdentifierNamingCheck.h" +#include "../readability/UppercaseLiteralSuffixCheck.h" #include "ExceptionBaseclassCheck.h" #include "MultiwayPathsCoveredCheck.h" #include "NoAssemblerCheck.h" @@ -100,6 +101,8 @@ "hicpp-use-nullptr"); CheckFactories.registerCheck( "hicpp-use-override"); + CheckFactories.registerCheck( + "hicpp-uppercase-literal-suffix"); CheckFactories.registerCheck( "hicpp-vararg"); } Index: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt +++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt @@ -31,6 +31,7 @@ StaticDefinitionInAnonymousNamespaceCheck.cpp StringCompareCheck.cpp UniqueptrDeleteReleaseCheck.cpp + UppercaseLiteralSuffixCheck.cpp LINK_LIBS clangAST Index: clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -9,6 +9,7 @@ #include "IdentifierNamingCheck.h" +#include "../utils/ASTUtils.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/PPCallbacks.h" @@ -681,25 +682,7 @@ if (!Failure.ShouldFix) return; - // Check if the range is entirely contained within a macro argument. - SourceLocation MacroArgExpansionStartForRangeBegin; - SourceLocation MacroArgExpansionStartForRangeEnd; - bool RangeIsEntirelyWithinMacroArgument = - SourceMgr && - SourceMgr->isMacroArgExpansion(Range.getBegin(), - &MacroArgExpansionStartForRangeBegin) && - SourceMgr->isMacroArgExpansion(Range.getEnd(), - &MacroArgExpansionStartForRangeEnd) && - MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd; - - // Check if the range contains any locations from a macro expansion. - bool RangeContainsMacroExpansion = RangeIsEntirelyWithinMacroArgument || - Range.getBegin().isMacroID() || - Range.getEnd().isMacroID(); - - bool RangeCanBeFixed = - RangeIsEntirelyWithinMacroArgument || !RangeContainsMacroExpansion; - Failure.ShouldFix = RangeCanBeFixed; + Failure.ShouldFix = utils::rangeCanBeFixed(Range, SourceMgr); } /// Convenience method when the usage to be added is a NamedDecl Index: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -38,6 +38,7 @@ #include "StaticDefinitionInAnonymousNamespaceCheck.h" #include "StringCompareCheck.h" #include "UniqueptrDeleteReleaseCheck.h" +#include "UppercaseLiteralSuffixCheck.h" namespace clang { namespace tidy { @@ -102,6 +103,8 @@ "readability-simplify-boolean-expr"); CheckFactories.registerCheck( "readability-uniqueptr-delete-release"); + CheckFactories.registerCheck( + "readability-uppercase-literal-suffix"); } }; Index: clang-tools-extra/trunk/clang-tidy/readability/UppercaseLiteralSuffixCheck.h =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/UppercaseLiteralSuffixCheck.h +++ clang-tools-extra/trunk/clang-tidy/readability/UppercaseLiteralSuffixCheck.h @@ -0,0 +1,44 @@ +//===--- UppercaseLiteralSuffixCheck.h - clang-tidy -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UPPERCASELITERALSUFFIXCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UPPERCASELITERALSUFFIXCHECK_H + +#include "../ClangTidy.h" +#include "../utils/OptionsUtils.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Detects when the integral literal or floating point literal has +/// non-uppercase suffix, and suggests to make the suffix uppercase. +/// Alternatively, a list of destination suffixes can be provided. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-uppercase-literal-suffix.html +class UppercaseLiteralSuffixCheck : public ClangTidyCheck { +public: + UppercaseLiteralSuffixCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + template + bool checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result); + + const std::vector NewSuffixes; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UPPERCASELITERALSUFFIXCHECK_H Index: clang-tools-extra/trunk/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp @@ -0,0 +1,238 @@ +//===--- UppercaseLiteralSuffixCheck.cpp - clang-tidy ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "UppercaseLiteralSuffixCheck.h" +#include "../utils/ASTUtils.h" +#include "../utils/OptionsUtils.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +namespace { + +struct IntegerLiteralCheck { + using type = clang::IntegerLiteral; + static constexpr llvm::StringLiteral Name = llvm::StringLiteral("integer"); + // What should be skipped before looking for the Suffixes? (Nothing here.) + static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral(""); + // Suffix can only consist of 'u' and 'l' chars, and can be a complex number + // ('i', 'j'). In MS compatibility mode, suffixes like i32 are supported. + static constexpr llvm::StringLiteral Suffixes = + llvm::StringLiteral("uUlLiIjJ"); +}; +constexpr llvm::StringLiteral IntegerLiteralCheck::Name; +constexpr llvm::StringLiteral IntegerLiteralCheck::SkipFirst; +constexpr llvm::StringLiteral IntegerLiteralCheck::Suffixes; + +struct FloatingLiteralCheck { + using type = clang::FloatingLiteral; + static constexpr llvm::StringLiteral Name = + llvm::StringLiteral("floating point"); + // C++17 introduced hexadecimal floating-point literals, and 'f' is both a + // valid hexadecimal digit in a hex float literal and a valid floating-point + // literal suffix. + // So we can't just "skip to the chars that can be in the suffix". + // Since the exponent ('p'/'P') is mandatory for hexadecimal floating-point + // literals, we first skip everything before the exponent. + static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral("pP"); + // Suffix can only consist of 'f', 'l', "f16", 'h', 'q' chars, + // and can be a complex number ('i', 'j'). + static constexpr llvm::StringLiteral Suffixes = + llvm::StringLiteral("fFlLhHqQiIjJ"); +}; +constexpr llvm::StringLiteral FloatingLiteralCheck::Name; +constexpr llvm::StringLiteral FloatingLiteralCheck::SkipFirst; +constexpr llvm::StringLiteral FloatingLiteralCheck::Suffixes; + +struct NewSuffix { + SourceRange LiteralLocation; + StringRef OldSuffix; + llvm::Optional FixIt; +}; + +llvm::Optional GetMacroAwareLocation(SourceLocation Loc, + const SourceManager &SM) { + // Do nothing if the provided location is invalid. + if (Loc.isInvalid()) + return llvm::None; + // Look where the location was *actually* written. + SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); + if (SpellingLoc.isInvalid()) + return llvm::None; + return SpellingLoc; +} + +llvm::Optional GetMacroAwareSourceRange(SourceRange Loc, + const SourceManager &SM) { + llvm::Optional Begin = + GetMacroAwareLocation(Loc.getBegin(), SM); + llvm::Optional End = GetMacroAwareLocation(Loc.getEnd(), SM); + if (!Begin || !End) + return llvm::None; + return SourceRange(*Begin, *End); +} + +llvm::Optional +getNewSuffix(llvm::StringRef OldSuffix, + const std::vector &NewSuffixes) { + // If there is no config, just uppercase the entirety of the suffix. + if (NewSuffixes.empty()) + return OldSuffix.upper(); + // Else, find matching suffix, case-*insensitive*ly. + auto NewSuffix = llvm::find_if( + NewSuffixes, [OldSuffix](const std::string &PotentialNewSuffix) { + return OldSuffix.equals_lower(PotentialNewSuffix); + }); + // Have a match, return it. + if (NewSuffix != NewSuffixes.end()) + return *NewSuffix; + // Nope, I guess we have to keep it as-is. + return llvm::None; +} + +template +llvm::Optional +shouldReplaceLiteralSuffix(const Expr &Literal, + const std::vector &NewSuffixes, + const SourceManager &SM, const LangOptions &LO) { + NewSuffix ReplacementDsc; + + const auto &L = cast(Literal); + + // The naive location of the literal. Is always valid. + ReplacementDsc.LiteralLocation = L.getSourceRange(); + + // Was this literal fully spelled or is it a product of macro expansion? + bool RangeCanBeFixed = + utils::rangeCanBeFixed(ReplacementDsc.LiteralLocation, &SM); + + // The literal may have macro expansion, we need the final expanded src range. + llvm::Optional Range = + GetMacroAwareSourceRange(ReplacementDsc.LiteralLocation, SM); + if (!Range) + return llvm::None; + + if (RangeCanBeFixed) + ReplacementDsc.LiteralLocation = *Range; + // Else keep the naive literal location! + + // Get the whole literal from the source buffer. + bool Invalid; + const StringRef LiteralSourceText = Lexer::getSourceText( + CharSourceRange::getTokenRange(*Range), SM, LO, &Invalid); + assert(!Invalid && "Failed to retrieve the source text."); + + size_t Skip = 0; + + // Do we need to ignore something before actually looking for the suffix? + if (!LiteralType::SkipFirst.empty()) { + // E.g. we can't look for 'f' suffix in hexadecimal floating-point literals + // until after we skip to the exponent (which is mandatory there), + // because hex-digit-sequence may contain 'f'. + Skip = LiteralSourceText.find_first_of(LiteralType::SkipFirst); + // We could be in non-hexadecimal floating-point literal, with no exponent. + if (Skip == StringRef::npos) + Skip = 0; + } + + // Find the beginning of the suffix by looking for the first char that is + // one of these chars that can be in the suffix, potentially starting looking + // in the exponent, if we are skipping hex-digit-sequence. + Skip = LiteralSourceText.find_first_of(LiteralType::Suffixes, /*From=*/Skip); + + // We can't check whether the *Literal has any suffix or not without actually + // looking for the suffix. So it is totally possible that there is no suffix. + if (Skip == StringRef::npos) + return llvm::None; + + // Move the cursor in the source range to the beginning of the suffix. + Range->setBegin(Range->getBegin().getLocWithOffset(Skip)); + // And in our textual representation too. + ReplacementDsc.OldSuffix = LiteralSourceText.drop_front(Skip); + assert(!ReplacementDsc.OldSuffix.empty() && + "We still should have some chars left."); + + // And get the replacement suffix. + llvm::Optional NewSuffix = + getNewSuffix(ReplacementDsc.OldSuffix, NewSuffixes); + if (!NewSuffix || ReplacementDsc.OldSuffix == *NewSuffix) + return llvm::None; // The suffix was already the way it should be. + + if (RangeCanBeFixed) + ReplacementDsc.FixIt = FixItHint::CreateReplacement(*Range, *NewSuffix); + + return ReplacementDsc; +} + +} // namespace + +UppercaseLiteralSuffixCheck::UppercaseLiteralSuffixCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + NewSuffixes( + utils::options::parseStringList(Options.get("NewSuffixes", ""))) {} + +void UppercaseLiteralSuffixCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "NewSuffixes", + utils::options::serializeStringList(NewSuffixes)); +} + +void UppercaseLiteralSuffixCheck::registerMatchers(MatchFinder *Finder) { + // Sadly, we can't check whether the literal has sufix or not. + // E.g. i32 suffix still results in 'BuiltinType::Kind::Int'. + // And such an info is not stored in the *Literal itself. + Finder->addMatcher( + stmt(allOf(eachOf(integerLiteral().bind(IntegerLiteralCheck::Name), + floatLiteral().bind(FloatingLiteralCheck::Name)), + unless(anyOf(hasParent(userDefinedLiteral()), + hasAncestor(isImplicit()), + hasAncestor(substNonTypeTemplateParmExpr()))))), + this); +} + +template +bool UppercaseLiteralSuffixCheck::checkBoundMatch( + const MatchFinder::MatchResult &Result) { + const auto *Literal = + Result.Nodes.getNodeAs(LiteralType::Name); + if (!Literal) + return false; + + // We won't *always* want to diagnose. + // We might have a suffix that is already uppercase. + if (auto Details = shouldReplaceLiteralSuffix( + *Literal, NewSuffixes, *Result.SourceManager, getLangOpts())) { + auto Complaint = diag(Details->LiteralLocation.getBegin(), + "%0 literal has suffix '%1', which is not uppercase") + << LiteralType::Name << Details->OldSuffix; + if (Details->FixIt) // Similarly, a fix-it is not always possible. + Complaint << *(Details->FixIt); + } + + return true; +} + +void UppercaseLiteralSuffixCheck::check( + const MatchFinder::MatchResult &Result) { + if (checkBoundMatch(Result)) + return; // If it *was* IntegerLiteral, don't check for FloatingLiteral. + checkBoundMatch(Result); +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: clang-tools-extra/trunk/clang-tidy/utils/ASTUtils.h =================================================================== --- clang-tools-extra/trunk/clang-tidy/utils/ASTUtils.h +++ clang-tools-extra/trunk/clang-tidy/utils/ASTUtils.h @@ -27,6 +27,18 @@ bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM, const LangOptions &LangOpts, StringRef FlagName); + +// Check if the range is entirely contained within a macro argument. +bool rangeIsEntirelyWithinMacroArgument(SourceRange Range, + const SourceManager *SM); + +// Check if the range contains any locations from a macro expansion. +bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM); + +// Can a fix-it be issued for this whole Range? +// FIXME: false-negative if the entire range is fully expanded from a macro. +bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM); + } // namespace utils } // namespace tidy } // namespace clang Index: clang-tools-extra/trunk/clang-tidy/utils/ASTUtils.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/utils/ASTUtils.cpp +++ clang-tools-extra/trunk/clang-tidy/utils/ASTUtils.cpp @@ -67,6 +67,32 @@ return true; } +bool rangeIsEntirelyWithinMacroArgument(SourceRange Range, + const SourceManager *SM) { + // Check if the range is entirely contained within a macro argument. + SourceLocation MacroArgExpansionStartForRangeBegin; + SourceLocation MacroArgExpansionStartForRangeEnd; + bool RangeIsEntirelyWithinMacroArgument = + SM && + SM->isMacroArgExpansion(Range.getBegin(), + &MacroArgExpansionStartForRangeBegin) && + SM->isMacroArgExpansion(Range.getEnd(), + &MacroArgExpansionStartForRangeEnd) && + MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd; + + return RangeIsEntirelyWithinMacroArgument; +} + +bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM) { + return rangeIsEntirelyWithinMacroArgument(Range, SM) || + Range.getBegin().isMacroID() || Range.getEnd().isMacroID(); +} + +bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM) { + return utils::rangeIsEntirelyWithinMacroArgument(Range, SM) || + !utils::rangeContainsMacroExpansion(Range, SM); +} + } // namespace utils } // namespace tidy } // namespace clang Index: clang-tools-extra/trunk/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/trunk/docs/ReleaseNotes.rst +++ clang-tools-extra/trunk/docs/ReleaseNotes.rst @@ -142,12 +142,30 @@ Detects usage of magic numbers, numbers that are used as literals instead of introduced via constants or symbols. +- New :doc:`readability-uppercase-literal-suffix + ` check. + + Detects when the integral literal or floating point literal has non-uppercase + suffix, and suggests to make the suffix uppercase. The list of destination + suffixes can be optionally provided. + +- New alias :doc:`cert-dcl16-c + ` to :doc:`readability-uppercase-literal-suffix + ` + added. + - New alias :doc:`cppcoreguidelines-non-private-member-variables-in-classes ` to :doc:`misc-non-private-member-variables-in-classes ` added. +- New alias :doc:`hicpp-uppercase-literal-suffix + ` to + :doc:`readability-uppercase-literal-suffix + ` + added. + - The :doc:`readability-redundant-smartptr-get ` check does not warn about calls inside macros anymore by default. Index: clang-tools-extra/trunk/docs/clang-tidy/checks/cert-dcl16-c.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/cert-dcl16-c.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/cert-dcl16-c.rst @@ -0,0 +1,9 @@ +.. title:: clang-tidy - cert-dcl16-c +.. meta:: + :http-equiv=refresh: 5;URL=readability-uppercase-literal-suffix.html + +cert-dcl16-c +============ + +The cert-dcl16-c check is an alias, please see +`readability-uppercase-literal-suffix `_ for more information. Index: clang-tools-extra/trunk/docs/clang-tidy/checks/hicpp-uppercase-literal-suffix.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/hicpp-uppercase-literal-suffix.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/hicpp-uppercase-literal-suffix.rst @@ -0,0 +1,9 @@ +.. title:: clang-tidy - hicpp-uppercase-literal-suffix +.. meta:: + :http-equiv=refresh: 5;URL=readability-uppercase-literal-suffix.html + +hicpp-uppercase-literal-suffix +============================== + +The hicpp-uppercase-literal-suffix check is an alias, please see +`readability-uppercase-literal-suffix `_ for more information. Index: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst @@ -66,6 +66,7 @@ bugprone-use-after-move bugprone-virtual-near-miss cert-dcl03-c (redirects to misc-static-assert) + cert-dcl16-c (redirects to readability-uppercase-literal-suffix) cert-dcl21-cpp cert-dcl50-cpp cert-dcl54-cpp (redirects to misc-new-delete-overloads) @@ -158,6 +159,7 @@ hicpp-use-nullptr (redirects to modernize-use-nullptr) hicpp-use-override (redirects to modernize-use-override) hicpp-vararg (redirects to cppcoreguidelines-pro-type-vararg) + hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) llvm-header-guard llvm-include-order llvm-namespace-comment @@ -249,4 +251,5 @@ readability-static-definition-in-anonymous-namespace readability-string-compare readability-uniqueptr-delete-release + readability-uppercase-literal-suffix zircon-temporary-objects Index: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst @@ -0,0 +1,42 @@ +.. title:: clang-tidy - readability-uppercase-literal-suffix + +readability-uppercase-literal-suffix +==================================== + +`cert-dcl16-c` redirects here as an alias for this check. +By default, only the suffixes that begin with 'l' ("l", "ll", "lu", "llu", +but not "u", "ul", "ull") are diagnosed by that alias. + +`hicpp-uppercase-literal-suffix` redirects here as an alias for this check. + +Detects when the integral literal or floating point (decimal or hexadecimal) +literal has a non-uppercase suffix and provides a fix-it-hint +with the uppercase suffix. + +All valid combinations of suffixes are supported. + +.. code:: c + + auto x = 1; // OK, no suffix. + + auto x = 1u; // warning: integer literal suffix 'u' is not upper-case + + auto x = 1U; // OK, suffix is uppercase. + + ... + +Optionally, a list of the destination suffixes can be provided. +When the suffix is found, a case-insensitive lookup in that list is made, +and if a replacement is found that is different from the current suffix, +then the diagnostic is issued. This allows for fine-grained control of +what suffixes to consider and what their replacements should be. + +For example, given a list ``L;uL``: +* ``l`` -> ``L`` +* ``L`` will be kept as is. +* ``ul`` -> ``uL`` +* ``Ul`` -> ``uL`` +* ``UL`` -> ``uL`` +* ``uL`` will be kept as is. +* ``ull`` will be kept as is, since it is not in the list +* and so on. Index: clang-tools-extra/trunk/test/clang-tidy/cert-uppercase-literal-suffix-integer.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/cert-uppercase-literal-suffix-integer.cpp +++ clang-tools-extra/trunk/test/clang-tidy/cert-uppercase-literal-suffix-integer.cpp @@ -0,0 +1,159 @@ +// RUN: %check_clang_tidy %s cert-dcl16-c %t -- -- -I %S +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,cert-dcl16-c' -fix -- -I %S +// RUN: clang-tidy %t.cpp -checks='-*,cert-dcl16-c' -warnings-as-errors='-*,cert-dcl16-c' -- -I %S + +#include "readability-uppercase-literal-suffix.h" + +void integer_suffix() { + static constexpr auto v0 = __LINE__; // synthetic + static_assert(v0 == 9 || v0 == 5, ""); + + static constexpr auto v1 = __cplusplus; // synthetic, long + + static constexpr auto v2 = 1; // no literal + static_assert(is_same::value, ""); + static_assert(v2 == 1, ""); + + // Unsigned + + static constexpr auto v3 = 1u; + static_assert(is_same::value, ""); + static_assert(v3 == 1, ""); + + static constexpr auto v4 = 1U; // OK. + static_assert(is_same::value, ""); + static_assert(v4 == 1, ""); + + // Long + + static constexpr auto v5 = 1l; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'l', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1l; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}L{{$}} + // CHECK-FIXES: static constexpr auto v5 = 1L; + static_assert(is_same::value, ""); + static_assert(v5 == 1, ""); + + static constexpr auto v6 = 1L; // OK. + static_assert(is_same::value, ""); + static_assert(v6 == 1, ""); + + // Long Long + + static constexpr auto v7 = 1ll; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'll', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 1ll; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LL{{$}} + // CHECK-FIXES: static constexpr auto v7 = 1LL; + static_assert(is_same::value, ""); + static_assert(v7 == 1, ""); + + static constexpr auto v8 = 1LL; // OK. + static_assert(is_same::value, ""); + static_assert(v8 == 1, ""); + + // Unsigned Long + + static constexpr auto v9 = 1ul; + static_assert(is_same::value, ""); + static_assert(v9 == 1, ""); + + static constexpr auto v10 = 1uL; + static_assert(is_same::value, ""); + static_assert(v10 == 1, ""); + + static constexpr auto v11 = 1Ul; + static_assert(is_same::value, ""); + static_assert(v11 == 1, ""); + + static constexpr auto v12 = 1UL; // OK. + static_assert(is_same::value, ""); + static_assert(v12 == 1, ""); + + // Long Unsigned + + static constexpr auto v13 = 1lu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'lu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 1lu; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LU{{$}} + // CHECK-FIXES: static constexpr auto v13 = 1LU; + static_assert(is_same::value, ""); + static_assert(v13 == 1, ""); + + static constexpr auto v14 = 1Lu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'Lu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1Lu; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LU{{$}} + // CHECK-FIXES: static constexpr auto v14 = 1LU; + static_assert(is_same::value, ""); + static_assert(v14 == 1, ""); + + static constexpr auto v15 = 1lU; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'lU', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1lU; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LU{{$}} + // CHECK-FIXES: static constexpr auto v15 = 1LU; + static_assert(is_same::value, ""); + static_assert(v15 == 1, ""); + + static constexpr auto v16 = 1LU; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 1, ""); + + // Unsigned Long Long + + static constexpr auto v17 = 1ull; + static_assert(is_same::value, ""); + static_assert(v17 == 1, ""); + + static constexpr auto v18 = 1uLL; + static_assert(is_same::value, ""); + static_assert(v18 == 1, ""); + + static constexpr auto v19 = 1Ull; + static_assert(is_same::value, ""); + static_assert(v19 == 1, ""); + + static constexpr auto v20 = 1ULL; // OK. + static_assert(is_same::value, ""); + static_assert(v20 == 1, ""); + + // Long Long Unsigned + + static constexpr auto v21 = 1llu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'llu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v21 = 1llu; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LLU{{$}} + // CHECK-FIXES: static constexpr auto v21 = 1LLU; + static_assert(is_same::value, ""); + static_assert(v21 == 1, ""); + + static constexpr auto v22 = 1LLu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'LLu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v22 = 1LLu; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LLU{{$}} + // CHECK-FIXES: static constexpr auto v22 = 1LLU; + static_assert(is_same::value, ""); + static_assert(v22 == 1, ""); + + static constexpr auto v23 = 1llU; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'llU', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v23 = 1llU; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LLU{{$}} + // CHECK-FIXES: static constexpr auto v23 = 1LLU; + static_assert(is_same::value, ""); + static_assert(v23 == 1, ""); + + static constexpr auto v24 = 1LLU; // OK. + static_assert(is_same::value, ""); + static_assert(v24 == 1, ""); +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-floating-point-opencl-half.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-floating-point-opencl-half.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-floating-point-opencl-half.cpp @@ -0,0 +1,30 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target x86_64-pc-linux-gnu -I %S -std=cl2.0 -x cl +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -fix -- -target x86_64-pc-linux-gnu -I %S -std=cl2.0 -x cl +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -target x86_64-pc-linux-gnu -I %S -std=cl2.0 -x cl + +#pragma OPENCL EXTENSION cl_khr_fp16 : enable + +void floating_point_half_suffix() { + static half v0 = 0x0p0; // no literal + + // half + + static half v2 = 1.h; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: floating point literal has suffix 'h', which is not uppercase + // CHECK-MESSAGES-NEXT: static half v2 = 1.h; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}H{{$}} + // CHECK-HIXES: static half v2 = 1.H; + + static half v3 = 1.e0h; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: floating point literal has suffix 'h', which is not uppercase + // CHECK-MESSAGES-NEXT: static half v3 = 1.e0h; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}H{{$}} + // CHECK-HIXES: static half v3 = 1.e0H; + + static half v4 = 1.H; // OK. + + static half v5 = 1.e0H; // OK. +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp @@ -0,0 +1,198 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target x86_64-pc-linux-gnu -I %S +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -fix -- -target x86_64-pc-linux-gnu -I %S +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -target x86_64-pc-linux-gnu -I %S + +#include "readability-uppercase-literal-suffix.h" + +void floating_point_suffix() { + static constexpr auto v0 = 1.; // no literal + static_assert(is_same::value, ""); + static_assert(v0 == 1., ""); + + static constexpr auto v1 = 1.e0; // no literal + static_assert(is_same::value, ""); + static_assert(v1 == 1., ""); + + // Float + + static constexpr auto v2 = 1.f; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v2 = 1.f; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto v2 = 1.F; + static_assert(is_same::value, ""); + static_assert(v2 == 1.0F, ""); + + static constexpr auto v3 = 1.e0f; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 1.e0f; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto v3 = 1.e0F; + static_assert(is_same::value, ""); + static_assert(v3 == 1.0F, ""); + + static constexpr auto v4 = 1.F; // OK. + static_assert(is_same::value, ""); + static_assert(v4 == 1.0F, ""); + + static constexpr auto v5 = 1.e0F; // OK. + static_assert(is_same::value, ""); + static_assert(v5 == 1.0F, ""); + + // Long double + + static constexpr auto v6 = 1.l; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'l', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v6 = 1.l; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}L{{$}} + // CHECK-FIXES: static constexpr auto v6 = 1.L; + static_assert(is_same::value, ""); + static_assert(v6 == 1., ""); + + static constexpr auto v7 = 1.e0l; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'l', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 1.e0l; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}L{{$}} + // CHECK-FIXES: static constexpr auto v7 = 1.e0L; + static_assert(is_same::value, ""); + static_assert(v7 == 1., ""); + + static constexpr auto v8 = 1.L; // OK. + static_assert(is_same::value, ""); + static_assert(v8 == 1., ""); + + static constexpr auto v9 = 1.e0L; // OK. + static_assert(is_same::value, ""); + static_assert(v9 == 1., ""); + + // __float128 + + static constexpr auto v10 = 1.q; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'q', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v10 = 1.q; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}Q{{$}} + // CHECK-FIXES: static constexpr auto v10 = 1.Q; + static_assert(is_same::value, ""); + static_assert(v10 == 1., ""); + + static constexpr auto v11 = 1.e0q; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'q', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v11 = 1.e0q; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}Q{{$}} + // CHECK-FIXES: static constexpr auto v11 = 1.e0Q; + static_assert(is_same::value, ""); + static_assert(v11 == 1., ""); + + static constexpr auto v12 = 1.Q; // OK. + static_assert(is_same::value, ""); + static_assert(v12 == 1., ""); + + static constexpr auto v13 = 1.e0Q; // OK. + static_assert(is_same::value, ""); + static_assert(v13 == 1., ""); + + // _Float16 + + static constexpr auto v14 = 1.f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v14 = 1.F16; + static_assert(is_same::value, ""); + static_assert(v14 == 1.F16, ""); + + static constexpr auto v15 = 1.e0f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v15 = 1.e0F16; + static_assert(is_same::value, ""); + static_assert(v15 == 1.F16, ""); + + static constexpr auto v16 = 1.F16; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 1.F16, ""); + + static constexpr auto v17 = 1.e0F16; // OK. + static_assert(is_same::value, ""); + static_assert(v17 == 1.F16, ""); +} + +void floating_point_complex_suffix() { + // _Complex, I + + static constexpr auto v14 = 1.i; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'i', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.i; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}I{{$}} + // CHECK-FIXES: static constexpr auto v14 = 1.I; + static_assert(is_same::value, ""); + static_assert(v14 == 1.I, ""); + + static constexpr auto v15 = 1.e0i; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'i', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0i; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}I{{$}} + // CHECK-FIXES: static constexpr auto v15 = 1.e0I; + static_assert(is_same::value, ""); + static_assert(v15 == 1.I, ""); + + static constexpr auto v16 = 1.I; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 1.I, ""); + + static constexpr auto v17 = 1.e0I; // OK. + static_assert(is_same::value, ""); + static_assert(v17 == 1.I, ""); + + // _Complex, J + + static constexpr auto v18 = 1.j; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'j', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v18 = 1.j; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}J{{$}} + // CHECK-FIXES: static constexpr auto v18 = 1.J; + static_assert(is_same::value, ""); + static_assert(v18 == 1.J, ""); + + static constexpr auto v19 = 1.e0j; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'j', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v19 = 1.e0j; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}J{{$}} + // CHECK-FIXES: static constexpr auto v19 = 1.e0J; + static_assert(is_same::value, ""); + static_assert(v19 == 1.J, ""); + + static constexpr auto v20 = 1.J; // OK. + static_assert(is_same::value, ""); + static_assert(v20 == 1.J, ""); + + static constexpr auto v21 = 1.e0J; // OK. + static_assert(is_same::value, ""); + static_assert(v21 == 1.J, ""); +} + +void macros() { +#define PASSTHROUGH(X) X + static constexpr auto m0 = PASSTHROUGH(1.f); + // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto m0 = PASSTHROUGH(1.f); + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto m0 = PASSTHROUGH(1.F); + static_assert(is_same::value, ""); + static_assert(m0 == 1.0F, ""); +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp @@ -0,0 +1,155 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target x86_64-pc-linux-gnu -I %S +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -fix -- -target x86_64-pc-linux-gnu -I %S +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -target x86_64-pc-linux-gnu -I %S + +#include "readability-uppercase-literal-suffix.h" + +void floating_point_suffix() { + static constexpr auto v0 = 0x0p0; // no literal + static_assert(is_same::value, ""); + static_assert(v0 == 0, ""); + + // Float + + static constexpr auto v1 = 0xfp0f; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v1 = 0xfp0f; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto v1 = 0xfp0F; + static_assert(is_same::value, ""); + static_assert(v1 == 15, ""); + + static constexpr auto v2 = 0xfp0F; // OK + static_assert(is_same::value, ""); + static_assert(v2 == 15, ""); + + static constexpr auto v3 = 0xfP0f; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 0xfP0f; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto v3 = 0xfP0F; + static_assert(is_same::value, ""); + static_assert(v3 == 15, ""); + + static constexpr auto v4 = 0xfP0F; // OK + static_assert(is_same::value, ""); + static_assert(v4 == 15, ""); + + static constexpr auto v5 = 0xFP0f; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 0xFP0f; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto v5 = 0xFP0F; + static_assert(is_same::value, ""); + static_assert(v5 == 15, ""); + + static constexpr auto v6 = 0xFP0F; // OK + static_assert(is_same::value, ""); + static_assert(v6 == 15, ""); + + static constexpr auto v7 = 0xFp0f; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 0xFp0f; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto v7 = 0xFp0F; + static_assert(is_same::value, ""); + static_assert(v7 == 15, ""); + + static constexpr auto v8 = 0xFp0F; // OK + static_assert(is_same::value, ""); + static_assert(v8 == 15, ""); + + // long double + + static constexpr auto v9 = 0xfp0l; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'l', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v9 = 0xfp0l; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}L{{$}} + // CHECK-FIXES: static constexpr auto v9 = 0xfp0L; + static_assert(is_same::value, ""); + static_assert(v9 == 0xfp0, ""); + + static constexpr auto v10 = 0xfp0L; // OK. + static_assert(is_same::value, ""); + static_assert(v10 == 0xfp0, ""); + + // __float128 + + static constexpr auto v11 = 0xfp0q; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'q', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v11 = 0xfp0q; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}Q{{$}} + // CHECK-FIXES: static constexpr auto v11 = 0xfp0Q; + static_assert(is_same::value, ""); + static_assert(v11 == 0xfp0, ""); + + static constexpr auto v12 = 0xfp0Q; // OK. + static_assert(is_same::value, ""); + static_assert(v12 == 0xfp0, ""); + + // _Float16 + + static constexpr auto v13 = 0xfp0f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16; + static_assert(is_same::value, ""); + static_assert(v13 == 0xfp0F16, ""); + + static constexpr auto v14 = 0xfp0F16; // OK. + static_assert(is_same::value, ""); + static_assert(v14 == 0xfp0F16, ""); +} + +void floating_point_complex_suffix() { + // _Complex, I + + static constexpr auto v14 = 0xfp0i; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'i', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 0xfp0i; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}I{{$}} + // CHECK-FIXES: static constexpr auto v14 = 0xfp0I; + static_assert(is_same::value, ""); + static_assert(v14 == 0xfp0I, ""); + + static constexpr auto v16 = 0xfp0I; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 0xfp0I, ""); + + // _Complex, J + + static constexpr auto v18 = 0xfp0j; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'j', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v18 = 0xfp0j; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}J{{$}} + // CHECK-FIXES: static constexpr auto v18 = 0xfp0J; + static_assert(is_same::value, ""); + static_assert(v18 == 0xfp0J, ""); + + static constexpr auto v20 = 0xfp0J; // OK. + static_assert(is_same::value, ""); + static_assert(v20 == 0xfp0J, ""); +} + +void macros() { +#define PASSTHROUGH(X) X + static constexpr auto m0 = PASSTHROUGH(0x0p0f); + // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto m0 = PASSTHROUGH(0x0p0f); + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F{{$}} + // CHECK-FIXES: static constexpr auto m0 = PASSTHROUGH(0x0p0F); + static_assert(is_same::value, ""); + static_assert(m0 == 0x0p0F, ""); +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-custom-list.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-custom-list.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-custom-list.cpp @@ -0,0 +1,130 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -config="{CheckOptions: [{key: readability-uppercase-literal-suffix.NewSuffixes, value: 'L;uL'}]}" -- -I %S +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -fix -config="{CheckOptions: [{key: readability-uppercase-literal-suffix.NewSuffixes, value: 'L;uL'}]}" -- -I %S +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -config="{CheckOptions: [{key: readability-uppercase-literal-suffix.NewSuffixes, value: 'L;uL'}]}" -- -I %S + +#include "readability-uppercase-literal-suffix.h" + +void integer_suffix() { + // Unsigned + + static constexpr auto v3 = 1u; // OK. + static_assert(is_same::value, ""); + static_assert(v3 == 1, ""); + + static constexpr auto v4 = 1U; // OK. + static_assert(is_same::value, ""); + static_assert(v4 == 1, ""); + + // Long + + static constexpr auto v5 = 1l; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'l', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1l; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}L{{$}} + // CHECK-FIXES: static constexpr auto v5 = 1L; + static_assert(is_same::value, ""); + static_assert(v5 == 1, ""); + + static constexpr auto v6 = 1L; // OK. + static_assert(is_same::value, ""); + static_assert(v6 == 1, ""); + + // Long Long + + static constexpr auto v7 = 1ll; // OK. + static_assert(is_same::value, ""); + static_assert(v7 == 1, ""); + + static constexpr auto v8 = 1LL; // OK. + static_assert(is_same::value, ""); + static_assert(v8 == 1, ""); + + // Unsigned Long + + static constexpr auto v9 = 1ul; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'ul', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1ul; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}uL{{$}} + // CHECK-FIXES: static constexpr auto v9 = 1uL; + static_assert(is_same::value, ""); + static_assert(v9 == 1, ""); + + static constexpr auto v10 = 1uL; // OK. + static_assert(is_same::value, ""); + static_assert(v10 == 1, ""); + + static constexpr auto v11 = 1Ul; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'Ul', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v11 = 1Ul; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}uL{{$}} + // CHECK-FIXES: static constexpr auto v11 = 1uL; + static_assert(is_same::value, ""); + static_assert(v11 == 1, ""); + + static constexpr auto v12 = 1UL; // OK. + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'UL', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v12 = 1UL; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}uL{{$}} + // CHECK-FIXES: static constexpr auto v12 = 1uL; + static_assert(is_same::value, ""); + static_assert(v12 == 1, ""); + + // Long Unsigned + + static constexpr auto v13 = 1lu; // OK. + static_assert(is_same::value, ""); + static_assert(v13 == 1, ""); + + static constexpr auto v14 = 1Lu; // OK. + static_assert(is_same::value, ""); + static_assert(v14 == 1, ""); + + static constexpr auto v15 = 1lU; // OK. + static_assert(is_same::value, ""); + static_assert(v15 == 1, ""); + + static constexpr auto v16 = 1LU; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 1, ""); + + // Unsigned Long Long + + static constexpr auto v17 = 1ull; // OK. + static_assert(is_same::value, ""); + static_assert(v17 == 1, ""); + + static constexpr auto v18 = 1uLL; // OK. + static_assert(is_same::value, ""); + static_assert(v18 == 1, ""); + + static constexpr auto v19 = 1Ull; // OK. + static_assert(is_same::value, ""); + static_assert(v19 == 1, ""); + + static constexpr auto v20 = 1ULL; // OK. + static_assert(is_same::value, ""); + static_assert(v20 == 1, ""); + + // Long Long Unsigned + + static constexpr auto v21 = 1llu; // OK. + static_assert(is_same::value, ""); + static_assert(v21 == 1, ""); + + static constexpr auto v22 = 1LLu; // OK. + static_assert(is_same::value, ""); + static_assert(v22 == 1, ""); + + static constexpr auto v23 = 1llU; // OK. + static_assert(is_same::value, ""); + static_assert(v23 == 1, ""); + + static constexpr auto v24 = 1LLU; // OK. + static_assert(is_same::value, ""); + static_assert(v24 == 1, ""); +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-macro.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-macro.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-macro.cpp @@ -0,0 +1,25 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -I %S + +void macros() { +#define INMACRO(X) 1.f + static constexpr auto m1 = INMACRO(); + // CHECK-NOTES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f', which is not uppercase + // CHECK-NOTES: :[[@LINE-3]]:20: note: expanded from macro 'INMACRO' + // CHECK-FIXES: #define INMACRO(X) 1.f + // CHECK-FIXES: static constexpr auto m1 = INMACRO(); + // ^ so no fix-its here. +} + +void horrible_macros() { +#define MAKE_UNSIGNED(x) x##u +#define ONE MAKE_UNSIGNED(1) + static constexpr auto hm0 = ONE; + // CHECK-NOTES: :[[@LINE-1]]:31: warning: integer literal has suffix 'u', which is not uppercase + // CHECK-NOTES: :[[@LINE-3]]:13: note: expanded from macro 'ONE' + // CHECK-NOTES: :[[@LINE-5]]:26: note: expanded from macro 'MAKE_UNSIGNED' + // CHECK-NOTES: note: expanded from here + // CHECK-FIXES: #define MAKE_UNSIGNED(x) x##u + // CHECK-FIXES: #define ONE MAKE_UNSIGNED(1) + // CHECK-FIXES: static constexpr auto hm0 = ONE; + // Certainly no fix-its. +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-ms.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-ms.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer-ms.cpp @@ -0,0 +1,77 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target x86_64-pc-linux-gnu -I %S -fms-extensions +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -fix -- -target x86_64-pc-linux-gnu -I %S -fms-extensions +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -target x86_64-pc-linux-gnu -I %S -fms-extensions + +#include "readability-uppercase-literal-suffix.h" + +void integer_suffix() { + static constexpr auto v0 = __LINE__; // synthetic + static_assert(v0 == 9 || v0 == 5, ""); + + static constexpr auto v1 = __cplusplus; // synthetic, long + + static constexpr auto v2 = 1; // no literal + static_assert(is_same::value, ""); + static_assert(v2 == 1, ""); + + // i32 + + static constexpr auto v3 = 1i32; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'i32', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 1i32; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}I32{{$}} + // CHECK-FIXES: static constexpr auto v3 = 1I32; + static_assert(is_same::value, ""); + static_assert(v3 == 1I32, ""); + + static constexpr auto v4 = 1I32; // OK. + static_assert(is_same::value, ""); + static_assert(v4 == 1I32, ""); + + // i64 + + static constexpr auto v5 = 1i64; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'i64', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1i64; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}I64{{$}} + // CHECK-FIXES: static constexpr auto v5 = 1I64; + static_assert(is_same::value, ""); + static_assert(v5 == 1I64, ""); + + static constexpr auto v6 = 1I64; // OK. + static_assert(is_same::value, ""); + static_assert(v6 == 1I64, ""); + + // i16 + + static constexpr auto v7 = 1i16; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'i16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 1i16; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}I16{{$}} + // CHECK-FIXES: static constexpr auto v7 = 1I16; + static_assert(is_same::value, ""); + static_assert(v7 == 1I16, ""); + + static constexpr auto v8 = 1I16; // OK. + static_assert(is_same::value, ""); + static_assert(v8 == 1I16, ""); + + // i8 + + static constexpr auto v9 = 1i8; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'i8', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1i8; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}I8{{$}} + // CHECK-FIXES: static constexpr auto v9 = 1I8; + static_assert(is_same::value, ""); + static_assert(v9 == 1I8, ""); + + static constexpr auto v10 = 1I8; // OK. + static_assert(is_same::value, ""); + static_assert(v10 == 1I8, ""); +} Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix-integer.cpp @@ -0,0 +1,268 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -I %S +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -fix -- -I %S +// RUN: clang-tidy %t.cpp -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -I %S + +#include "readability-uppercase-literal-suffix.h" + +void integer_suffix() { + static constexpr auto v0 = __LINE__; // synthetic + static_assert(v0 == 9 || v0 == 5, ""); + + static constexpr auto v1 = __cplusplus; // synthetic, long + + static constexpr auto v2 = 1; // no literal + static_assert(is_same::value, ""); + static_assert(v2 == 1, ""); + + // Unsigned + + static constexpr auto v3 = 1u; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'u', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 1u; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}U{{$}} + // CHECK-FIXES: static constexpr auto v3 = 1U; + static_assert(is_same::value, ""); + static_assert(v3 == 1, ""); + + static constexpr auto v4 = 1U; // OK. + static_assert(is_same::value, ""); + static_assert(v4 == 1, ""); + + // Long + + static constexpr auto v5 = 1l; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'l', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1l; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}L{{$}} + // CHECK-FIXES: static constexpr auto v5 = 1L; + static_assert(is_same::value, ""); + static_assert(v5 == 1, ""); + + static constexpr auto v6 = 1L; // OK. + static_assert(is_same::value, ""); + static_assert(v6 == 1, ""); + + // Long Long + + static constexpr auto v7 = 1ll; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'll', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 1ll; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LL{{$}} + // CHECK-FIXES: static constexpr auto v7 = 1LL; + static_assert(is_same::value, ""); + static_assert(v7 == 1, ""); + + static constexpr auto v8 = 1LL; // OK. + static_assert(is_same::value, ""); + static_assert(v8 == 1, ""); + + // Unsigned Long + + static constexpr auto v9 = 1ul; + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'ul', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1ul; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}UL{{$}} + // CHECK-FIXES: static constexpr auto v9 = 1UL; + static_assert(is_same::value, ""); + static_assert(v9 == 1, ""); + + static constexpr auto v10 = 1uL; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'uL', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v10 = 1uL; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}UL{{$}} + // CHECK-FIXES: static constexpr auto v10 = 1UL; + static_assert(is_same::value, ""); + static_assert(v10 == 1, ""); + + static constexpr auto v11 = 1Ul; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'Ul', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v11 = 1Ul; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}UL{{$}} + // CHECK-FIXES: static constexpr auto v11 = 1UL; + static_assert(is_same::value, ""); + static_assert(v11 == 1, ""); + + static constexpr auto v12 = 1UL; // OK. + static_assert(is_same::value, ""); + static_assert(v12 == 1, ""); + + // Long Unsigned + + static constexpr auto v13 = 1lu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'lu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 1lu; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LU{{$}} + // CHECK-FIXES: static constexpr auto v13 = 1LU; + static_assert(is_same::value, ""); + static_assert(v13 == 1, ""); + + static constexpr auto v14 = 1Lu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'Lu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1Lu; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LU{{$}} + // CHECK-FIXES: static constexpr auto v14 = 1LU; + static_assert(is_same::value, ""); + static_assert(v14 == 1, ""); + + static constexpr auto v15 = 1lU; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'lU', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1lU; + // CHECK-MESSAGES-NEXT: ^~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LU{{$}} + // CHECK-FIXES: static constexpr auto v15 = 1LU; + static_assert(is_same::value, ""); + static_assert(v15 == 1, ""); + + static constexpr auto v16 = 1LU; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 1, ""); + + // Unsigned Long Long + + static constexpr auto v17 = 1ull; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'ull', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v17 = 1ull; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}ULL{{$}} + // CHECK-FIXES: static constexpr auto v17 = 1ULL; + static_assert(is_same::value, ""); + static_assert(v17 == 1, ""); + + static constexpr auto v18 = 1uLL; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'uLL', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v18 = 1uLL; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}ULL{{$}} + // CHECK-FIXES: static constexpr auto v18 = 1ULL; + static_assert(is_same::value, ""); + static_assert(v18 == 1, ""); + + static constexpr auto v19 = 1Ull; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'Ull', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v19 = 1Ull; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}ULL{{$}} + // CHECK-FIXES: static constexpr auto v19 = 1ULL; + static_assert(is_same::value, ""); + static_assert(v19 == 1, ""); + + static constexpr auto v20 = 1ULL; // OK. + static_assert(is_same::value, ""); + static_assert(v20 == 1, ""); + + // Long Long Unsigned + + static constexpr auto v21 = 1llu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'llu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v21 = 1llu; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LLU{{$}} + // CHECK-FIXES: static constexpr auto v21 = 1LLU; + static_assert(is_same::value, ""); + static_assert(v21 == 1, ""); + + static constexpr auto v22 = 1LLu; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'LLu', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v22 = 1LLu; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LLU{{$}} + // CHECK-FIXES: static constexpr auto v22 = 1LLU; + static_assert(is_same::value, ""); + static_assert(v22 == 1, ""); + + static constexpr auto v23 = 1llU; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'llU', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v23 = 1llU; + // CHECK-MESSAGES-NEXT: ^~~~ + // CHECK-MESSAGES-NEXT: {{^ *}}LLU{{$}} + // CHECK-FIXES: static constexpr auto v23 = 1LLU; + static_assert(is_same::value, ""); + static_assert(v23 == 1, ""); + + static constexpr auto v24 = 1LLU; // OK. + static_assert(is_same::value, ""); + static_assert(v24 == 1, ""); +} + +void integer_complex_suffix() { + // _Complex, I + + static constexpr auto v25 = 1i; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'i', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v25 = 1i; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}I{{$}} + // CHECK-FIXES: static constexpr auto v25 = 1I; + static_assert(is_same::value, ""); + static_assert(v25 == 1I, ""); + + static constexpr auto v26 = 1I; // OK. + static_assert(is_same::value, ""); + static_assert(v26 == 1I, ""); + + // _Complex, J + + static constexpr auto v27 = 1j; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: integer literal has suffix 'j', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v27 = 1j; + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}J{{$}} + // CHECK-FIXES: static constexpr auto v27 = 1J; + static_assert(is_same::value, ""); + static_assert(v27 == 1J, ""); + + static constexpr auto v28 = 1J; // OK. + static_assert(is_same::value, ""); + static_assert(v28 == 1J, ""); +} + +void macros() { +#define PASSTHROUGH(X) X + static constexpr auto m0 = PASSTHROUGH(1u); + // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: integer literal has suffix 'u', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto m0 = PASSTHROUGH(1u); + // CHECK-MESSAGES-NEXT: ^~ + // CHECK-MESSAGES-NEXT: {{^ *}}U{{$}} + // CHECK-FIXES: static constexpr auto m0 = PASSTHROUGH(1U); + static_assert(is_same::value, ""); + static_assert(m0 == 1, ""); +} + +// Check that user-defined literals do not cause any diags. + +unsigned long long int operator"" _ull(unsigned long long int); +void user_defined_literals() { + 1_ull; +} + +template +void template_test() { + static_assert(alignment, ""); +} +void actual_template_test() { + template_test<4>(); +} + +const int table[6] = {}; +void read_test() { + for (auto i : table) { + } +} + +namespace { +enum a { b }; +constexpr bool operator&(a, a) { return int(); } +template +void c() { l &a(); } +void d(); +void d() { c(); } +} // namespace Index: clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix.h =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix.h +++ clang-tools-extra/trunk/test/clang-tidy/readability-uppercase-literal-suffix.h @@ -0,0 +1,16 @@ +template +struct integral_constant { + static constexpr T value = v; + typedef T value_type; + typedef integral_constant type; // using injected-class-name + constexpr operator value_type() const noexcept { return value; } +}; + +using false_type = integral_constant; +using true_type = integral_constant; + +template +struct is_same : false_type {}; + +template +struct is_same : true_type {};