ahatanak created this revision.
ahatanak added reviewers: arphaman, erik.pilkington, rjmccall.
ahatanak added a project: clang.
Herald added subscribers: ributzka, dexonsmith, jkorous.

This improves upon https://reviews.llvm.org/D21099, which taught -Wcast-align 
to look at the aligned attribute of variables. I added a function that computes 
a more accurate alignment to `ExprConstant.cpp`.

rdar://problem/59242343


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D78767

Files:
  clang/include/clang/AST/Expr.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/warn-cast-align.c

Index: clang/test/Sema/warn-cast-align.c
===================================================================
--- clang/test/Sema/warn-cast-align.c
+++ clang/test/Sema/warn-cast-align.c
@@ -67,3 +67,14 @@
 FnTy test5(void) {
   return (FnTy)&func5;
 }
+
+void test6(int n) {
+  __attribute__((aligned(16))) char m[sizeof(struct A) * 2];
+  struct A *a = (struct A *)&m;
+  a = (struct A *)(m + sizeof(struct A));
+  a = (struct A *)(sizeof(struct A) + m);
+  a = (struct A *)(m + 1); // expected-warning {{cast from 'char *' to 'struct A *'}}
+  a = (struct A *)(1 + m); // expected-warning {{cast from 'char *' to 'struct A *'}}
+  a = (struct A *)(m + n); // expected-warning {{cast from 'char *' to 'struct A *'}}
+  a = (struct A *)&m[sizeof(struct A)];
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -13055,19 +13055,6 @@
   return HasInvalidParm;
 }
 
-/// A helper function to get the alignment of a Decl referred to by DeclRefExpr
-/// or MemberExpr.
-static CharUnits getDeclAlign(Expr *E, CharUnits TypeAlign,
-                              ASTContext &Context) {
-  if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
-    return Context.getDeclAlign(DRE->getDecl());
-
-  if (const auto *ME = dyn_cast<MemberExpr>(E))
-    return Context.getDeclAlign(ME->getMemberDecl());
-
-  return TypeAlign;
-}
-
 /// CheckCastAlign - Implements -Wcast-align, which warns when a
 /// pointer cast increases the alignment requirements.
 void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
@@ -13101,15 +13088,13 @@
   // includes 'void'.
   if (SrcPointee->isIncompleteType()) return;
 
-  CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee);
+  // Try to compute an accurate alignment using the alignment of the ValueDecls
+  // in the expression.
+  CharUnits SrcAlign = Op->getAlignmentFromDecl(Context);
 
-  if (auto *CE = dyn_cast<CastExpr>(Op)) {
-    if (CE->getCastKind() == CK_ArrayToPointerDecay)
-      SrcAlign = getDeclAlign(CE->getSubExpr(), SrcAlign, Context);
-  } else if (auto *UO = dyn_cast<UnaryOperator>(Op)) {
-    if (UO->getOpcode() == UO_AddrOf)
-      SrcAlign = getDeclAlign(UO->getSubExpr(), SrcAlign, Context);
-  }
+  // If that failed, just use the type's alignment.
+  if (SrcAlign.isZero())
+    SrcAlign = Context.getTypeAlignInChars(SrcPointee);
 
   if (SrcAlign >= DestAlign) return;
 
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14827,3 +14827,21 @@
   EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
   return tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
 }
+
+CharUnits Expr::getAlignmentFromDecl(ASTContext &Ctx) const {
+  assert(getType()->getAs<PointerType>() &&
+         "expression must be a pointer type");
+
+  Expr::EvalStatus Status;
+  EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects);
+  LValue Result;
+  PointerExprEvaluator Eval(Info, Result, false);
+
+  if (!Eval.Visit(this) || !Result.Base)
+    return CharUnits::Zero();
+
+  if (auto *VD = Result.Base.dyn_cast<const ValueDecl *>())
+    return Ctx.getDeclAlign(VD).alignmentAtOffset(Result.Offset);
+
+  return CharUnits::Zero();
+}
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -704,6 +704,11 @@
   bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
                              unsigned Type) const;
 
+  /// Compute the alignment of an expression of a pointer type using the
+  /// alignment of a ValueDecl referenced in the expression. If it's not
+  /// possible to compute the alignment, return zero.
+  CharUnits getAlignmentFromDecl(ASTContext &Ctx) const;
+
   /// Enumeration used to describe the kind of Null pointer constant
   /// returned from \c isNullPointerConstant().
   enum NullPointerConstantKind {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to