Index: clang-tidy/cert/AvoidPointerCastToMoreStrictAlignmentCheck.h =================================================================== --- /dev/null +++ clang-tidy/cert/AvoidPointerCastToMoreStrictAlignmentCheck.h @@ -0,0 +1,37 @@ +//===--- AvoidPointerCastToMoreStrictAlignmentCheck.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_CERT_AVOID_POINTER_CAST_TO_MORE_STRICT_ALIGNMENT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_AVOID_POINTER_CAST_TO_MORE_STRICT_ALIGNMENT_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace cert { + +/// This check will give a warning if a pointer value is +/// converted to a pointer type that is more strictly +/// aligned than the referenced type. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cert-exp36-c.html;; +class AvoidPointerCastToMoreStrictAlignmentCheck : public ClangTidyCheck { +public: + AvoidPointerCastToMoreStrictAlignmentCheck(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_AVOID_POINTER_CAST_TO_MORE_STRICT_ALIGNMENT_H Index: clang-tidy/cert/AvoidPointerCastToMoreStrictAlignmentCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/cert/AvoidPointerCastToMoreStrictAlignmentCheck.cpp @@ -0,0 +1,56 @@ +//===--- AvoidPointerCastToMoreStrictAlignmentCheck.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 "AvoidPointerCastToMoreStrictAlignmentCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cert { + +void AvoidPointerCastToMoreStrictAlignmentCheck::registerMatchers( + MatchFinder *Finder) { + Finder->addMatcher( + castExpr(hasSourceExpression(expr().bind("source"))).bind("target"), + this); +} + +void AvoidPointerCastToMoreStrictAlignmentCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *Source = Result.Nodes.getNodeAs("source"); + const auto *Target = Result.Nodes.getNodeAs("target"); + + QualType SourceType = Source->getType(); + QualType TargetType = Target->getType(); + + if (!SourceType->isPointerType() || !TargetType->isPointerType()) + return; + + QualType SourcePointedType = SourceType->getPointeeType(); + QualType TargetPointedType = TargetType->getPointeeType(); + + if (SourcePointedType->isIncompleteType() || + TargetPointedType->isIncompleteType()) + return; + + if (Result.Context->getTypeAlign(SourcePointedType) >= + Result.Context->getTypeAlign(TargetPointedType)) + return; + + if (Target->getCastKind() == CK_BitCast) + diag(Target->getLocStart(), + "do not cast pointers into more strictly aligned pointer types"); +} + +} // namespace cert +} // namespace tidy +} // namespace clang Index: clang-tidy/cert/CERTTidyModule.cpp =================================================================== --- clang-tidy/cert/CERTTidyModule.cpp +++ clang-tidy/cert/CERTTidyModule.cpp @@ -16,6 +16,7 @@ #include "../misc/NonCopyableObjects.h" #include "../misc/StaticAssertCheck.h" #include "../misc/ThrowByValueCatchByReferenceCheck.h" +#include "AvoidPointerCastToMoreStrictAlignmentCheck.h" #include "CommandProcessorCheck.h" #include "DontModifyStdNamespaceCheck.h" #include "FloatLoopCounter.h" @@ -64,6 +65,9 @@ CheckFactories.registerCheck("cert-dcl03-c"); // ENV CheckFactories.registerCheck("cert-env33-c"); + // EXP + CheckFactories.registerCheck( + "cert-exp36-c"); // FLP CheckFactories.registerCheck("cert-flp30-c"); // FIO Index: clang-tidy/cert/CMakeLists.txt =================================================================== --- clang-tidy/cert/CMakeLists.txt +++ clang-tidy/cert/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyCERTModule + AvoidPointerCastToMoreStrictAlignmentCheck.cpp CERTTidyModule.cpp CommandProcessorCheck.cpp DontModifyStdNamespaceCheck.cpp Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -56,6 +56,10 @@ Improvements to clang-tidy -------------------------- +- New `cert-exp36-c + `_ check + + Checks if a pointer value is casted to a more stricter alignment. - Renamed checks to use correct term "implicit conversion" instead of "implicit cast" and modified messages and option names accordingly: @@ -143,7 +147,7 @@ option. - Added alias `hicpp-braces-around-statements `_ - + Improvements to include-fixer ----------------------------- Index: docs/clang-tidy/checks/cert-exp36-c.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/cert-exp36-c.rst @@ -0,0 +1,45 @@ +.. title:: clang-tidy - cert-exp36-c + +cert-exp36-c +============ + +This check will give a warning if a pointer value is converted to +a pointer type that is more strictly aligned than the referenced type. + +This check is the same as `-Wcast-align`, except it checks for `reinterpret_cast` as well. + + Here's an example: + + .. code-block:: c + + char c = 'x'; + int *ip = (int *)&c; + // warning: do not cast pointers into more strictly aligned pointer types + + This check does not completely include warnings for types with explicitly + specified alignment, this remains a possible future extension. + + See the example: + + .. code-block:: c + + // Works fine: + struct x { + _Alignas(int) char c; + }; + + void function3(void) { + struct x c = {'x'}; + int *ip = (int *)&c; + } + + // Won't work: + void function4(void) { + _Alignas(int) char c = 'x'; + int *ip = (int *)&c; + // the check will give a warning for this + } + + This check corresponds to the CERT C Coding Standard rule + `EXP36-C. Do not cast pointers into more strictly aligned pointer types +`_. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -20,6 +20,7 @@ bugprone-integer-division bugprone-suspicious-memset-usage bugprone-undefined-memory-manipulation + cert-exp36-c cert-dcl03-c (redirects to misc-static-assert) cert-dcl21-cpp cert-dcl50-cpp Index: test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.c =================================================================== --- /dev/null +++ test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.c @@ -0,0 +1,45 @@ +// RUN: %check_clang_tidy %s cert-exp36-c %t -- -- -std=c11 + +void function(void) { + char c = 'x'; + int *ip = (int *)&c; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c] +} + +struct foo_header { + int len; +}; + +void function2(char *data, unsigned offset) { + struct foo_header *tmp; + struct foo_header header; + + tmp = (struct foo_header *)(data + offset); + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c] +} + + +// Something that does not trigger the check: + +struct w; + +void function3(struct w *v) { + int *ip = (int *)v; + struct w *u = (struct w *)ip; +} + +struct x { + _Alignas(int) char c; +}; + +void function4(void) { + struct x c = {'x'}; + int *ip = (int *)&c; +} + +// FIXME: we do not want a warning for this +void function5(void) { + _Alignas(int) char c = 'x'; + int *ip = (int *)&c; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c] +} Index: test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.cpp =================================================================== --- /dev/null +++ test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.cpp @@ -0,0 +1,7 @@ +// RUN: %check_clang_tidy %s cert-exp36-c %t + +void function(void) { + char c = 'x'; + int *ip = reinterpret_cast(&c); + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c] +}