diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -18,6 +18,7 @@ #include "../performance/MoveConstructorInitCheck.h" #include "../readability/UppercaseLiteralSuffixCheck.h" #include "CommandProcessorCheck.h" +#include "DefaultOperatorNewCheck.h" #include "DontModifyStdNamespaceCheck.h" #include "FloatLoopCounter.h" #include "LimitedRandomnessCheck.h" @@ -48,6 +49,8 @@ CheckFactories.registerCheck( "cert-dcl59-cpp"); // OOP + CheckFactories.registerCheck( + "cert-default-operator-new"); CheckFactories.registerCheck( "cert-oop11-cpp"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt --- a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt @@ -3,6 +3,7 @@ add_clang_library(clangTidyCERTModule CERTTidyModule.cpp CommandProcessorCheck.cpp + DefaultOperatorNewCheck.cpp DontModifyStdNamespaceCheck.cpp FloatLoopCounter.cpp LimitedRandomnessCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewCheck.h b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewCheck.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewCheck.h @@ -0,0 +1,34 @@ +//===--- DefaultOperatorNewCheck.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_CERT_DEFAULTOPERATORNEWCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DEFAULTOPERATORNEWCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace cert { + +/// FIXME: Write a short description. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cert-default-operator-new.html +class DefaultOperatorNewCheck : public ClangTidyCheck { +public: + DefaultOperatorNewCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace cert +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DEFAULTOPERATORNEWCHECK_H diff --git a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewCheck.cpp b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewCheck.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewCheck.cpp @@ -0,0 +1,56 @@ +//===--- DefaultOperatorNewCheck.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 "DefaultOperatorNewCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cert { + +void DefaultOperatorNewCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(cxxNewExpr().bind("new"), this); +} + +void DefaultOperatorNewCheck::check(const MatchFinder::MatchResult &Result) { + const auto *NewExpr = Result.Nodes.getNodeAs("new"); + + if (NewExpr->getNumPlacementArgs() > 0) + return; + QualType T = NewExpr->getAllocatedType(); + if (T->isDependentType()) + return; + const TagDecl *D = T->getAsTagDecl(); + if (!D || !D->getDefinition() || !D->isCompleteDefinition()) + return; + + ASTContext &Context = D->getASTContext(); + + if (!Context.isAlignmentRequired(T)) + return; + + unsigned SpecifiedAlignment = D->getMaxAlignment(); + unsigned DefaultAlignment = Context.getTargetInfo().getCharAlign(); + if (!SpecifiedAlignment) + return; + + bool OverAligned = SpecifiedAlignment > DefaultAlignment; + bool HasDefaultOperatorNew = !NewExpr->getOperatorNew() || NewExpr->getOperatorNew()->isImplicit(); + + if (HasDefaultOperatorNew && OverAligned) + diag(NewExpr->getBeginLoc(), "using default 'operator new' with over-aligned type %0 may result in undefined behavior") + << D; +} + +} // namespace cert +} // namespace tidy +} // namespace clang + diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -73,6 +73,11 @@ Finds instances where variables with static storage are initialized dynamically in header files. +- New :doc:`cert-default-operator-new + ` check. + + FIXME: add release notes. + - New :doc:`linuxkernel-must-use-errs ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert-default-operator-new.rst b/clang-tools-extra/docs/clang-tidy/checks/cert-default-operator-new.rst new file mode 100644 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/cert-default-operator-new.rst @@ -0,0 +1,6 @@ +.. title:: clang-tidy - cert-default-operator-new + +cert-default-operator-new +========================= + +FIXME: Describe what patterns does the check detect and why. Give examples. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -4,7 +4,6 @@ ================= .. toctree:: - abseil-duration-addition abseil-duration-comparison abseil-duration-conversion-cast @@ -89,6 +88,7 @@ cert-dcl54-cpp (redirects to misc-new-delete-overloads) cert-dcl58-cpp cert-dcl59-cpp (redirects to google-build-namespaces) + cert-default-operator-new cert-env33-c cert-err09-cpp (redirects to misc-throw-by-value-catch-by-reference) cert-err34-c @@ -104,87 +104,87 @@ cert-msc51-cpp cert-oop11-cpp (redirects to performance-move-constructor-init) cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) - clang-analyzer-core.CallAndMessage - clang-analyzer-core.DivideZero + clang-analyzer-core.CallAndMessage (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.DivideZero (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-core.DynamicTypePropagation - clang-analyzer-core.NonNullParamChecker - clang-analyzer-core.NullDereference - clang-analyzer-core.StackAddressEscape - clang-analyzer-core.UndefinedBinaryOperatorResult - clang-analyzer-core.VLASize - clang-analyzer-core.uninitialized.ArraySubscript - clang-analyzer-core.uninitialized.Assign - clang-analyzer-core.uninitialized.Branch + clang-analyzer-core.NonNullParamChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.NullDereference (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.StackAddressEscape (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.UndefinedBinaryOperatorResult (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.VLASize (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.uninitialized.ArraySubscript (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.uninitialized.Assign (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-core.uninitialized.Branch (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-core.uninitialized.CapturedBlockVariable - clang-analyzer-core.uninitialized.UndefReturn + clang-analyzer-core.uninitialized.UndefReturn (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-cplusplus.InnerPointer - clang-analyzer-cplusplus.Move - clang-analyzer-cplusplus.NewDelete - clang-analyzer-cplusplus.NewDeleteLeaks - clang-analyzer-deadcode.DeadStores - clang-analyzer-nullability.NullPassedToNonnull - clang-analyzer-nullability.NullReturnedFromNonnull - clang-analyzer-nullability.NullableDereferenced - clang-analyzer-nullability.NullablePassedToNonnull + clang-analyzer-cplusplus.Move (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-cplusplus.NewDelete (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-cplusplus.NewDeleteLeaks (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-deadcode.DeadStores (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullPassedToNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullReturnedFromNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullableDereferenced (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-nullability.NullablePassedToNonnull (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-nullability.NullableReturnedFromNonnull - clang-analyzer-optin.cplusplus.UninitializedObject - clang-analyzer-optin.cplusplus.VirtualCall - clang-analyzer-optin.mpi.MPI-Checker + clang-analyzer-optin.cplusplus.UninitializedObject (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-optin.cplusplus.VirtualCall (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-optin.mpi.MPI-Checker (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-optin.osx.OSObjectCStyleCast - clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker - clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker + clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-optin.performance.GCDAntipattern clang-analyzer-optin.performance.Padding clang-analyzer-optin.portability.UnixAPI - clang-analyzer-osx.API + clang-analyzer-osx.API (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-osx.MIG clang-analyzer-osx.NumberObjectConversion clang-analyzer-osx.OSObjectRetainCount clang-analyzer-osx.ObjCProperty - clang-analyzer-osx.SecKeychainAPI - clang-analyzer-osx.cocoa.AtSync + clang-analyzer-osx.SecKeychainAPI (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.AtSync (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-osx.cocoa.AutoreleaseWrite - clang-analyzer-osx.cocoa.ClassRelease - clang-analyzer-osx.cocoa.Dealloc - clang-analyzer-osx.cocoa.IncompatibleMethodTypes + clang-analyzer-osx.cocoa.ClassRelease (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.Dealloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.IncompatibleMethodTypes (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-osx.cocoa.Loops clang-analyzer-osx.cocoa.MissingSuperCall - clang-analyzer-osx.cocoa.NSAutoreleasePool - clang-analyzer-osx.cocoa.NSError - clang-analyzer-osx.cocoa.NilArg + clang-analyzer-osx.cocoa.NSAutoreleasePool (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.NSError (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.NilArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-osx.cocoa.NonNilReturnValue - clang-analyzer-osx.cocoa.ObjCGenerics - clang-analyzer-osx.cocoa.RetainCount + clang-analyzer-osx.cocoa.ObjCGenerics (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.RetainCount (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak - clang-analyzer-osx.cocoa.SelfInit - clang-analyzer-osx.cocoa.SuperDealloc - clang-analyzer-osx.cocoa.UnusedIvars - clang-analyzer-osx.cocoa.VariadicMethodTypes - clang-analyzer-osx.coreFoundation.CFError - clang-analyzer-osx.coreFoundation.CFNumber - clang-analyzer-osx.coreFoundation.CFRetainRelease - clang-analyzer-osx.coreFoundation.containers.OutOfBounds - clang-analyzer-osx.coreFoundation.containers.PointerSizedValues - clang-analyzer-security.FloatLoopCounter - clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling - clang-analyzer-security.insecureAPI.UncheckedReturn - clang-analyzer-security.insecureAPI.bcmp - clang-analyzer-security.insecureAPI.bcopy - clang-analyzer-security.insecureAPI.bzero - clang-analyzer-security.insecureAPI.getpw - clang-analyzer-security.insecureAPI.gets - clang-analyzer-security.insecureAPI.mkstemp - clang-analyzer-security.insecureAPI.mktemp - clang-analyzer-security.insecureAPI.rand - clang-analyzer-security.insecureAPI.strcpy - clang-analyzer-security.insecureAPI.vfork - clang-analyzer-unix.API - clang-analyzer-unix.Malloc - clang-analyzer-unix.MallocSizeof - clang-analyzer-unix.MismatchedDeallocator - clang-analyzer-unix.Vfork - clang-analyzer-unix.cstring.BadSizeArg - clang-analyzer-unix.cstring.NullArg + clang-analyzer-osx.cocoa.SelfInit (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.SuperDealloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.UnusedIvars (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.cocoa.VariadicMethodTypes (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.CFError (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.CFNumber (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.CFRetainRelease (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.containers.OutOfBounds (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-osx.coreFoundation.containers.PointerSizedValues (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.FloatLoopCounter (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.UncheckedReturn (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.bcmp (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.bcopy (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.bzero (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.getpw (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.gets (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.mkstemp (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.mktemp (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.rand (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.strcpy (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-security.insecureAPI.vfork (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.API (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.Malloc (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.MallocSizeof (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.MismatchedDeallocator (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.Vfork (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.cstring.BadSizeArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) + clang-analyzer-unix.cstring.NullArg (redirects to https://clang.llvm.org/docs/analyzer/checkers) clang-analyzer-valist.CopyToSelf clang-analyzer-valist.Uninitialized clang-analyzer-valist.Unterminated diff --git a/clang-tools-extra/test/clang-tidy/cert-default-operator-new.cpp b/clang-tools-extra/test/clang-tidy/cert-default-operator-new.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cert-default-operator-new.cpp @@ -0,0 +1,32 @@ +// RUN: %check_clang_tidy %s cert-default-operator-new %t + +namespace std { +typedef __typeof(sizeof(int)) size_t; +void *aligned_alloc(size_t, size_t); +void free(void *); +} + +struct alignas(32) Vector1 { + char elems[32]; +}; + +struct Vector2 { + char elems[32]; +}; + +struct alignas(32) Vector3 { + char elems[32]; + static void *operator new(std::size_t nbytes) noexcept(true) { + return std::aligned_alloc(alignof(Vector3), nbytes); + } + static void operator delete(void *p) { + std::free(p); + } +}; + +void f() { + auto *V1 = new Vector1; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: using default 'operator new' with over-aligned type 'Vector1' may result in undefined behavior [cert-default-operator-new] + auto *V2 = new Vector2; + auto *V3 = new Vector3; +}