NorenaLeonetti updated this revision to Diff 116510.

Repository:
  rL LLVM

https://reviews.llvm.org/D33826

Files:
  clang-tidy/cert/AvoidPointerCastToMoreStrictAlignmentCheck.cpp
  clang-tidy/cert/AvoidPointerCastToMoreStrictAlignmentCheck.h
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cert-exp36-c.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.c
  test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.cpp

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<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.c
===================================================================
--- /dev/null
+++ test/clang-tidy/cert-avoid-pointer-cast-to-more-strict-alignment.c
@@ -0,0 +1,122 @@
+// 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] 
+}
+
+// Test from -Wcast-align check:
+
+// Simple casts.
+void test0(char *P) {
+  char *a  = (char*)  P;
+  short *b = (short*) P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c]
+  int *c   = (int*)   P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c]
+}
+
+// Casts from void* are a special case.
+void test1(void *P) {
+  char *a  = (char*)  P;
+  short *b = (short*) P;
+  int *c   = (int*)   P;
+
+  const volatile void *P2 = P;
+  char *d  = (char*)  P2;
+  short *e = (short*) P2;
+  int *f   = (int*)   P2;
+
+  const char *g  = (const char*)  P2;
+  const short *h = (const short*) P2;
+  const int *i   = (const int*)   P2;
+
+  const volatile char *j  = (const volatile char*)  P2;
+  const volatile short *k = (const volatile short*) P2;
+  const volatile int *l   = (const volatile int*)   P2;
+}
+
+// Aligned struct.
+struct __attribute__((aligned(16))) A {
+  char buffer[16];
+};
+void test2(char *P) {
+  struct A *a = (struct A*) P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c]
+}
+
+// Incomplete type.
+void test3(char *P) {
+  struct B *b = (struct B*) P;
+}
+
+// Do not issue a warning. The aligned attribute changes the alignment of the
+// variables and fields.
+char __attribute__((aligned(4))) a[16];
+
+struct S0 {
+  char a[16];
+};
+
+struct S {
+  char __attribute__((aligned(4))) a[16];
+  struct S0 __attribute__((aligned(4))) s0;
+};
+
+// same FIXME as in line 120
+void test4() {
+  struct S s;
+  int *i = (int *)s.a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c]
+  i = (int *)&s.s0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c]
+  i = (int *)a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not cast pointers into more strictly aligned pointer types [cert-exp36-c]
+}
+
+// No warnings.
+typedef int (*FnTy)(void);
+unsigned int func5(void);
+
+FnTy test5(void) {
+  return (FnTy)&func5;
+}
+
+
+// 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: 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-dcl03-c>
    cert-dcl21-cpp
    cert-dcl50-cpp
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
+<https://www.securecoding.cert.org/confluence/display/c/EXP36-C.+Do+not+cast+pointers+into+more+strictly+aligned+pointer+types>`_.
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -56,6 +56,10 @@
 
 Improvements to clang-tidy
 --------------------------
+- New `cert-exp36-c
+  <http://clang.llvm.org/extra/clang-tidy/checks/cert-exp36-c.html>`_ 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:
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: 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<misc::StaticAssertCheck>("cert-dcl03-c");
     // ENV
     CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
+    // EXP
+    CheckFactories.registerCheck<AvoidPointerCastToMoreStrictAlignmentCheck>(
+        "cert-exp36-c");
     // FLP
     CheckFactories.registerCheck<FloatLoopCounter>("cert-flp30-c");
     // FIO
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,59 @@
+//===--- 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<Expr>("source");
+  const auto *Target = Result.Nodes.getNodeAs<CastExpr>("target");
+
+  QualType SourceType = Source->getType();
+  QualType TargetType = Target->getType();
+
+  if (!SourceType->isPointerType() || !TargetType->isPointerType())
+    return;
+
+  if (SourceType->isDependentType() || TargetType->isDependentType())
+    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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to