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