summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-08-12 21:44:57 +0000
committerJohn McCall <rjmccall@apple.com>2010-08-12 21:44:57 +0000
commit2b5c1b2516ca7e381ba00ef09787b824b30f77e6 (patch)
treee5946f80419e7bec536817d8658f7d9f66f82624 /clang/lib/Sema
parent112fd083fafabcda3e9ead58d2359fd9e3f987c3 (diff)
downloadbcm5719-llvm-2b5c1b2516ca7e381ba00ef09787b824b30f77e6.tar.gz
bcm5719-llvm-2b5c1b2516ca7e381ba00ef09787b824b30f77e6.zip
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). llvm-svn: 110959
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaCXXCast.cpp6
-rw-r--r--clang/lib/Sema/SemaChecking.cpp45
-rw-r--r--clang/lib/Sema/SemaExpr.cpp4
3 files changed, 55 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index 5753e7bce47..59df294772e 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -468,6 +468,8 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
!= 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 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
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 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
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;
}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7e1eebebdbf..14c0d87ffb7 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2796,3 +2796,48 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
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();
+}
+
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8643dd8386d..f87d39fd8f0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3995,6 +3995,10 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
}
Kind = getScalarCastKind(Context, castExpr->getType(), castType);
+
+ if (Kind == CastExpr::CK_Unknown || Kind == CastExpr::CK_BitCast)
+ CheckCastAlign(castExpr, castType, TyR);
+
return false;
}
OpenPOWER on IntegriCloud