Index: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -35,6 +35,7 @@ #include "MoveForwardingReferenceCheck.h" #include "MultipleStatementMacroCheck.h" #include "NoEscapeCheck.h" +#include "NonportableintegerconstantCheck.h" #include "NotNullTerminatedResultCheck.h" #include "ParentVirtualCallCheck.h" #include "PosixReturnCheck.h" @@ -120,6 +121,8 @@ "bugprone-move-forwarding-reference"); CheckFactories.registerCheck( "bugprone-multiple-statement-macro"); + CheckFactories.registerCheck( + "bugprone-non-portable-integer-constant"); CheckFactories.registerCheck( "bugprone-redundant-branch-condition"); CheckFactories.registerCheck( Index: clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -31,6 +31,7 @@ MultipleStatementMacroCheck.cpp NoEscapeCheck.cpp NotNullTerminatedResultCheck.cpp + NonportableintegerconstantCheck.cpp ParentVirtualCallCheck.cpp PosixReturnCheck.cpp RedundantBranchConditionCheck.cpp Index: clang-tools-extra/clang-tidy/bugprone/NonportableintegerconstantCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/bugprone/NonportableintegerconstantCheck.h @@ -0,0 +1,34 @@ +//===--- NonportableintegerconstantCheck.h - clang-tidy ---------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NON_PORTABLE_INTEGER_CONSTANT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NON_PORTABLE_INTEGER_CONSTANT_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace bugprone { + +/// Finds masks that are being used in a nonportable manner +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-non-portable-integer-constant.html +class NonportableintegerconstantCheck : public ClangTidyCheck { +public: + NonportableintegerconstantCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace bugprone +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NON_PORTABLE_INTEGER_CONSTANT_H Index: clang-tools-extra/clang-tidy/bugprone/NonportableintegerconstantCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/bugprone/NonportableintegerconstantCheck.cpp @@ -0,0 +1,70 @@ +//===--- NonportableintegerconstantCheck.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 "NonportableintegerconstantCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace bugprone { + +/// The mask is problematic if: +/// - The highest bit is set and everything else are zeroes, for example: `0x80000000`. +/// - All the bits are set to one, for example: `0xFFFFFFFF`. +bool isProblematicMask(StringRef HexNumber) { + + // Check whether only the highest bit is set. + if (HexNumber[0] == '8' && HexNumber[1] == '0') { + // Consume the first non-zero. + HexNumber = HexNumber.drop_front(); + // Consume all the left zeroes. + HexNumber = HexNumber.drop_while([](char C) { return C == '0'; }); + return HexNumber.empty(); + } + + // Check whether all the bits are set to one by consuming all the 'F's. + HexNumber = HexNumber.drop_while([](char C) { return C == 'F' || C == 'f'; }); + return HexNumber.empty(); +} + +void NonportableintegerconstantCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(integerLiteral().bind("integer"), this); +} + +void NonportableintegerconstantCheck::check(const MatchFinder::MatchResult &Result) { + + const auto *MatchedInt = Result.Nodes.getNodeAs("integer"); + + if (MatchedInt) { + + StringRef MaskStr = Lexer::getSourceText( + CharSourceRange::getTokenRange(MatchedInt->getSourceRange()), + *Result.SourceManager, Result.Context->getLangOpts(), 0); + + MaskStr = StringRef(MaskStr.lower()); + if (!MaskStr.consume_front("0x")) + return; + + MaskStr = MaskStr.take_while(llvm::isHexDigit); + + if (!isProblematicMask(MaskStr)) + return; + + diag(MatchedInt->getBeginLoc(), + "integer is being used in a non-portable manner "); + } +} + +} // namespace bugprone +} // namespace tidy +} // namespace clang \ No newline at end of file Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -10,6 +10,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" #include "../bugprone/BadSignalToKillThreadCheck.h" +#include "../bugprone/NonPortableIntegerConstant.h" #include "../bugprone/ReservedIdentifierCheck.h" #include "../bugprone/SignedCharMisuseCheck.h" #include "../bugprone/SpuriouslyWakeUpFunctionsCheck.h" @@ -102,6 +103,9 @@ CheckFactories.registerCheck("cert-fio38-c"); // ERR CheckFactories.registerCheck("cert-err34-c"); + // INT + CheckFactories.registerCheck( + "cert-int17-c"); // MSC CheckFactories.registerCheck("cert-msc30-c"); CheckFactories.registerCheck( Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -72,7 +72,7 @@ :doc:`cppcoreguidelines-init-variables ` and :doc:`modernize-make-unique `. - + New modules ^^^^^^^^^^^ @@ -110,6 +110,19 @@ ` check. Flags functions with Cognitive Complexity metric exceeding the configured limit. + +- New :doc:`bugprone-non-portable-integer-constant + ` check. + + Finds masks that are being used in a non-portable manner. + +New check aliases +^^^^^^^^^^^^^^^^^ + +- New alias :doc:`cert-int17-c + ` to + :doc:`bugprone-non-portable-integer-constant + ` was added. Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-non-portable-integer-constant.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/bugprone-non-portable-integer-constant.rst @@ -0,0 +1,14 @@ +.. title:: clang-tidy - bugprone-non-portable-integer-constant + +bugprone-non-portable-integer-constant +=================================== + +Finds masks that are being used in a non-portable manner. + +.. code-block: + + const unsigned long mask = 0xFFFFFFFF; + + unsigned long flipbits(unsigned long x) { + return x ^ mask; + } \ No newline at end of file Index: clang-tools-extra/docs/clang-tidy/checks/cert-int17-c.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/cert-int17-c.rst @@ -0,0 +1,10 @@ +.. title:: clang-tidy - cert-int17-c +.. meta:: + :http-equiv=refresh: 5;URL=bugprone-non-portable-integer-constant.html + +cert-int17-c +============== + +The cert-int17-c check is an alias, please see +`bugprone-non-portable-integer-constant `_ +for more information. Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -72,6 +72,7 @@ `bugprone-move-forwarding-reference `_, "Yes" `bugprone-multiple-statement-macro `_, `bugprone-no-escape `_, + `bugprone-non-portable-integer-constant `_, `bugprone-not-null-terminated-result `_, "Yes" `bugprone-parent-virtual-call `_, "Yes" `bugprone-posix-return `_, "Yes" @@ -110,6 +111,7 @@ `cert-err58-cpp `_, `cert-err60-cpp `_, `cert-flp30-c `_, + `cert-int17-c `_, `cert-mem57-cpp `_, `cert-msc50-cpp `_, `cert-msc51-cpp `_, Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-non-portable-integer-constant.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone-non-portable-integer-constant.cpp @@ -0,0 +1,33 @@ +// RUN: %check_clang_tidy %s bugprone-non-portable-integer-constant %t + +// #define ULONG_MAX 0xFFFFFFFFUL +#include +#include + +const unsigned long mask = 0xFFFFFFFF; +// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: integer is being used in a non-portable manner + +const unsigned long mask1 = 0xffffffffUL; +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: integer is being used in a non-portable manner + +const unsigned long mask2 = 0x80000000; +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: integer is being used in a non-portable manner + +int stuff() { + int mask3 = 0xff; + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: integer is being used in a non-portable manner + int value = 0x55; + return mask3; +} + +const unsigned long g = 0xC0; +// no warnings + +const unsigned long x = -1; +// no warnings + +const unsigned long y = ~(ULONG_MAX >> 1); +// no warnings + +const unsigned long z = 0x11111111; +// no warnings