diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index fa2d228b7eeb..90d4f7e4e096 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -677,17 +677,13 @@ AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { /// Attempt to look through various unimportant expressions to find a /// cast of the given kind. -static Expr *findPeephole(Expr *op, CastKind kind) { - while (true) { - op = op->IgnoreParens(); - if (CastExpr *castE = dyn_cast(op)) { - if (castE->getCastKind() == kind) - return castE->getSubExpr(); - if (castE->getCastKind() == CK_NoOp) - continue; - } - return nullptr; +static Expr *findPeephole(Expr *op, CastKind kind, const ASTContext &ctx) { + op = op->IgnoreParenNoopCasts(ctx); + if (auto castE = dyn_cast(op)) { + if (castE->getCastKind() == kind) + return castE->getSubExpr(); } + return nullptr; } void AggExprEmitter::VisitCastExpr(CastExpr *E) { @@ -776,7 +772,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic); // These two cases are reverses of each other; try to peephole them. - if (Expr *op = findPeephole(E->getSubExpr(), peepholeTarget)) { + if (Expr *op = + findPeephole(E->getSubExpr(), peepholeTarget, CGF.getContext())) { assert(CGF.getContext().hasSameUnqualifiedType(op->getType(), E->getType()) && "peephole significantly changed types?"); diff --git a/clang/test/CodeGen/pr45476.cpp b/clang/test/CodeGen/pr45476.cpp new file mode 100644 index 000000000000..61f3f3649986 --- /dev/null +++ b/clang/test/CodeGen/pr45476.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// PR45476 + +// This test used to get into an infinite loop, +// which, in turn, caused clang to never finish execution. + +struct s3 { + char a, b, c; +}; + +_Atomic struct s3 a; + +extern "C" void foo() { + // CHECK-LABEL: @foo + // CHECK: store atomic i32 + + a = s3{1, 2, 3}; +} +