[PATCH] D119095: [clang] Fix redundant functional cast in ConstantExpr
Evgeny Shulgin via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 6 13:57:59 PST 2022
Izaron created this revision.
Izaron added reviewers: aaron.ballman, cor3ntin.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
When removing nested ConstantExprs, the tree transformer
doesn't remove redundant CXXFunctionalCasts that were created
"above" consteval constructors. After a while it generates a call
to a constructor, therefore violating the C++17 mandatory copy
elision rule.
Fixes https://github.com/llvm/llvm-project/issues/53244
and https://github.com/llvm/llvm-project/issues/53245
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D119095
Files:
clang/lib/Sema/SemaExpr.cpp
clang/test/SemaCXX/cxx2a-consteval.cpp
Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===================================================================
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -613,6 +613,45 @@
} // namespace unevaluated
+namespace mandatory_copy_elision {
+
+struct A {
+ consteval A() {}
+ consteval A(const A &);
+ consteval A(A &&);
+ consteval void f() {}
+};
+
+struct B {
+ consteval B() {}
+ consteval B(const B &) = delete;
+ consteval B(B &&) = delete;
+ consteval void f() {}
+};
+
+struct C {
+ consteval C() {}
+ consteval void f() {}
+
+private:
+ consteval C(const C &){};
+ consteval C(C &&){};
+};
+
+void test() {
+ { A{}.f(); }
+ { A{A{}}.f(); }
+ { A{A{A{A{A{A{A{A{}}}}}}}}.f(); }
+ { B{}.f(); }
+ { B{B{}}.f(); }
+ { B{B{B{B{B{B{B{B{}}}}}}}}.f(); }
+ { C{}.f(); }
+ { C{C{}}.f(); }
+ { C{C{C{C{C{C{C{C{}}}}}}}}.f(); }
+}
+
+} // namespace mandatory_copy_elision
+
namespace PR50779 {
struct derp {
int b = 0;
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -16796,6 +16796,14 @@
DRSet.erase(cast<DeclRefExpr>(E->getCallee()->IgnoreImplicit()));
return Base::TransformCXXOperatorCallExpr(E);
}
+ /// Delete extra no-op functional casts to avoid calling a constructor
+ ExprResult TransformCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+ auto *CE = dyn_cast<ConstantExpr>(E->getSubExpr());
+ if (E->getCastKind() != CK_NoOp || !CE || !CE->isImmediateInvocation())
+ return Base::TransformCXXFunctionalCastExpr(E);
+ RemoveImmediateInvocation(CE);
+ return Base::TransformExpr(CE->getSubExpr());
+ }
/// Base::TransformInitializer skip ConstantExpr so we need to visit them
/// here.
ExprResult TransformInitializer(Expr *Init, bool NotCopyInit) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D119095.406280.patch
Type: text/x-patch
Size: 1920 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220206/0fb826bf/attachment-0001.bin>
More information about the cfe-commits
mailing list