diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 45 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | 
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;  } | 

