diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index f108b49ceac1b..bb27f40994dcd 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3270,6 +3270,26 @@ namespace { bool hasSideEffects() const { return HasSideEffects; } + void VisitDecl(const Decl *D) { + if (!D) + return; + + // We assume the caller checks subexpressions (eg, the initializer, VLA + // bounds) for side-effects on our behalf. + if (auto *VD = dyn_cast(D)) { + // Registering a destructor is a side-effect. + if (IncludePossibleEffects && VD->isThisDeclarationADefinition() && + VD->needsDestruction(Context)) + HasSideEffects = true; + } + } + + void VisitDeclStmt(const DeclStmt *DS) { + for (auto *D : DS->decls()) + VisitDecl(D); + Inherited::VisitDeclStmt(DS); + } + void VisitExpr(const Expr *E) { if (!HasSideEffects && E->HasSideEffects(Context, IncludePossibleEffects)) diff --git a/clang/test/CodeGenCXX/builtin-constant-p.cpp b/clang/test/CodeGenCXX/builtin-constant-p.cpp index 6d853e8a68282..866faa5ec9761 100644 --- a/clang/test/CodeGenCXX/builtin-constant-p.cpp +++ b/clang/test/CodeGenCXX/builtin-constant-p.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s // Don't crash if the argument to __builtin_constant_p isn't scalar. template @@ -22,3 +22,27 @@ class numeric { bool bcp() { return is_constant(numeric(1)); } + +// PR45535 +struct with_dtor { + ~with_dtor(); +}; +// CHECK: define {{.*}}bcp_stmt_expr_1 +bool bcp_stmt_expr_1() { + // CHECK-NOT: call {{.*}}with_dtorD + return __builtin_constant_p(({with_dtor wd; 123;})); +} + +int do_not_call(); +// CHECK: define {{.*}}bcp_stmt_expr_2 +bool bcp_stmt_expr_2(int n) { + // CHECK-NOT: call {{.*}}do_not_call + return __builtin_constant_p(({ + // This has a side-effect due to the VLA bound, so CodeGen should fold it + // to false. + typedef int arr[do_not_call()]; + n; + })); + // CHECK-NOT: } + // CHECK: ret i1 false +}