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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits