[cfe-commits] r110959 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp test/Sema/warn-cast-align.c test/SemaCXX/warn-cast-align.cpp

John McCall rjmccall at apple.com
Thu Aug 12 14:44:57 PDT 2010


Author: rjmccall
Date: Thu Aug 12 16:44:57 2010
New Revision: 110959

URL: http://llvm.org/viewvc/llvm-project?rev=110959&view=rev
Log:
Implement -Wcast-align.  The initial design of this diagnostic diverges     
from GCC's in that we warn on *any* increase in alignment requirements, not
just those that are enforced by hardware.  Please let us know if this causes
major problems for you (which it shouldn't, since it's an optional warning).


Added:
    cfe/trunk/test/Sema/warn-cast-align.c
    cfe/trunk/test/SemaCXX/warn-cast-align.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=110959&r1=110958&r2=110959&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Aug 12 16:44:57 2010
@@ -26,7 +26,7 @@
 def : DiagGroup<"bad-function-cast">;
 def BoolConversions : DiagGroup<"bool-conversions">;
 def CXXCompat: DiagGroup<"c++-compat">;
-def : DiagGroup<"cast-align">;
+def CastAlign : DiagGroup<"cast-align">;
 def : DiagGroup<"cast-qual">;
 def : DiagGroup<"char-align">;
 def Comment : DiagGroup<"comment">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=110959&r1=110958&r2=110959&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Aug 12 16:44:57 2010
@@ -971,6 +971,10 @@
   "implicit conversion loses integer precision: %0 to %1">,
   InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
 
+def warn_cast_align : Warning<
+  "cast from %0 to %1 increases required alignment from %2 to %3">,
+  InGroup<CastAlign>, DefaultIgnore;
+
 def warn_attribute_ignored_for_field_of_type : Warning<
   "%0 attribute ignored for field of type %1">;
 def warn_transparent_union_attribute_field_size_align : Warning<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=110959&r1=110958&r2=110959&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Aug 12 16:44:57 2010
@@ -860,6 +860,7 @@
   void DiagnoseFunctionSpecifiers(Declarator& D);
   void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
   void CheckShadow(Scope *S, VarDecl *D);
+  void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                     QualType R, TypeSourceInfo *TInfo,
                                     LookupResult &Previous, bool &Redeclaration);

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=110959&r1=110958&r2=110959&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Thu Aug 12 16:44:57 2010
@@ -468,6 +468,8 @@
       != TC_Success && msg != 0)
     Self.Diag(OpRange.getBegin(), msg) << CT_Reinterpret
       << SrcExpr->getType() << DestType << OpRange;
+  else if (Kind == CastExpr::CK_Unknown || Kind == CastExpr::CK_BitCast)
+    Self.CheckCastAlign(SrcExpr, DestType, OpRange);
 }
 
 
@@ -494,6 +496,8 @@
                     Kind, BasePath) != TC_Success && msg != 0)
     Self.Diag(OpRange.getBegin(), msg) << CT_Static
       << SrcExpr->getType() << DestType << OpRange;
+  else if (Kind == CastExpr::CK_Unknown || Kind == CastExpr::CK_BitCast)
+    Self.CheckCastAlign(SrcExpr, DestType, OpRange);
 }
 
 /// TryStaticCast - Check if a static cast can be performed, and do so if
@@ -1303,6 +1307,8 @@
   if (tcr != TC_Success && msg != 0)
     Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle)
       << CastExpr->getType() << CastTy << R;
+  else if (Kind == CastExpr::CK_Unknown || Kind == CastExpr::CK_BitCast)
+    CheckCastAlign(CastExpr, CastTy, R);
 
   return tcr != TC_Success;
 }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=110959&r1=110958&r2=110959&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Aug 12 16:44:57 2010
@@ -2796,3 +2796,48 @@
 
   return HasInvalidParm;
 }
+
+/// CheckCastAlign - Implements -Wcast-align, which warns when a
+/// pointer cast increases the alignment requirements.
+void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
+  // This is actually a lot of work to potentially be doing on every
+  // cast; don't do it if we're ignoring -Wcast_align (as is the default).
+  if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align)
+        == Diagnostic::Ignored)
+    return;
+
+  // Ignore dependent types.
+  if (T->isDependentType() || Op->getType()->isDependentType())
+    return;
+
+  // Require that the destination be a pointer type.
+  const PointerType *DestPtr = T->getAs<PointerType>();
+  if (!DestPtr) return;
+
+  // If the destination has alignment 1, we're done.
+  QualType DestPointee = DestPtr->getPointeeType();
+  if (DestPointee->isIncompleteType()) return;
+  CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee);
+  if (DestAlign.isOne()) return;
+
+  // Require that the source be a pointer type.
+  const PointerType *SrcPtr = Op->getType()->getAs<PointerType>();
+  if (!SrcPtr) return;
+  QualType SrcPointee = SrcPtr->getPointeeType();
+
+  // Whitelist casts from cv void*.  We already implicitly
+  // whitelisted casts to cv void*, since they have alignment 1.
+  // Also whitelist casts involving incomplete types, which implicitly
+  // includes 'void'.
+  if (SrcPointee->isIncompleteType()) return;
+
+  CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee);
+  if (SrcAlign >= DestAlign) return;
+
+  Diag(TRange.getBegin(), diag::warn_cast_align)
+    << Op->getType() << T
+    << static_cast<unsigned>(SrcAlign.getQuantity())
+    << static_cast<unsigned>(DestAlign.getQuantity())
+    << TRange << Op->getSourceRange();
+}
+

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=110959&r1=110958&r2=110959&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Aug 12 16:44:57 2010
@@ -3995,6 +3995,10 @@
   }
 
   Kind = getScalarCastKind(Context, castExpr->getType(), castType);
+
+  if (Kind == CastExpr::CK_Unknown || Kind == CastExpr::CK_BitCast)
+    CheckCastAlign(castExpr, castType, TyR);
+
   return false;
 }
 

Added: cfe/trunk/test/Sema/warn-cast-align.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-cast-align.c?rev=110959&view=auto
==============================================================================
--- cfe/trunk/test/Sema/warn-cast-align.c (added)
+++ cfe/trunk/test/Sema/warn-cast-align.c Thu Aug 12 16:44:57 2010
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -Wcast-align -verify %s
+
+// Simple casts.
+void test0(char *P) {
+  char *a  = (char*)  P;
+  short *b = (short*) P; // expected-warning {{cast from 'char *' to 'short *' increases required alignment from 1 to 2}}
+  int *c   = (int*)   P; // expected-warning {{cast from 'char *' to 'int *' increases required alignment from 1 to 4}}
+}
+
+// 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.
+__attribute__((align(16))) struct A {
+  char buffer[16];
+};
+void test2(char *P) {
+  struct A *a = (struct A*) P; // expected-warning {{cast from 'char *' to 'struct A *' increases required alignment from 1 to 16}}
+}
+
+// Incomplete type.
+void test3(char *P) {
+  struct B *b = (struct B*) P;
+}

Added: cfe/trunk/test/SemaCXX/warn-cast-align.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-cast-align.cpp?rev=110959&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-cast-align.cpp (added)
+++ cfe/trunk/test/SemaCXX/warn-cast-align.cpp Thu Aug 12 16:44:57 2010
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -Wcast-align -verify %s
+
+// Simple casts.
+void test0(char *P) {
+  char *a; short *b; int *c;
+
+  a = (char*) P;
+  a = static_cast<char*>(P);
+  a = reinterpret_cast<char*>(P);
+  typedef char *CharPtr;
+  a = CharPtr(P);
+
+  b = (short*) P; // expected-warning {{cast from 'char *' to 'short *' increases required alignment from 1 to 2}}
+  b = reinterpret_cast<short*>(P); // expected-warning {{cast from 'char *' to 'short *' increases required alignment from 1 to 2}}
+  typedef short *ShortPtr;
+  b = ShortPtr(P); // expected-warning {{cast from 'char *' to 'ShortPtr' (aka 'short *') increases required alignment from 1 to 2}}
+
+  c = (int*) P; // expected-warning {{cast from 'char *' to 'int *' increases required alignment from 1 to 4}}
+  c = reinterpret_cast<int*>(P); // expected-warning {{cast from 'char *' to 'int *' increases required alignment from 1 to 4}}
+  typedef int *IntPtr;
+  c = IntPtr(P); // expected-warning {{cast from 'char *' to 'IntPtr' (aka 'int *') increases required alignment from 1 to 4}}
+}
+
+// Casts from void* are a special case.
+void test1(void *P) {
+  char *a; short *b; int *c;
+
+  a = (char*) P;
+  a = static_cast<char*>(P);
+  a = reinterpret_cast<char*>(P);
+  typedef char *CharPtr;
+  a = CharPtr(P);
+
+  b = (short*) P;
+  b = static_cast<short*>(P);
+  b = reinterpret_cast<short*>(P);
+  typedef short *ShortPtr;
+  b = ShortPtr(P);
+
+  c = (int*) P;
+  c = static_cast<int*>(P);
+  c = reinterpret_cast<int*>(P);
+  typedef int *IntPtr;
+  c = IntPtr(P);
+}





More information about the cfe-commits mailing list