Index: clang/lib/CodeGen/CGExprAgg.cpp =================================================================== --- clang/lib/CodeGen/CGExprAgg.cpp +++ clang/lib/CodeGen/CGExprAgg.cpp @@ -678,16 +678,16 @@ /// 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; + while (CastExpr *castE = dyn_cast(op->IgnoreParens())) { + if (castE->getCastKind() == kind) + return castE->getSubExpr(); + + if (castE->getCastKind() != CK_NoOp || castE == op) + break; + + op = castE; } + return nullptr; } void AggExprEmitter::VisitCastExpr(CastExpr *E) { Index: clang/test/CodeGen/atomic-struct-bug.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/atomic-struct-bug.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}; +} +