summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-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