From: Richard Smith Date: Tue, 18 Feb 2014 03:51:47 +0000 (+0000) Subject: PR18876: The special-case rule that ignores the destruction of a top-level X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48788de5c8ff8ac4d2766ed9de3447984a2692c6;p=clang PR18876: The special-case rule that ignores the destruction of a top-level temporary in a decltype expression only applies if that temporary was created by a function call, not by a function-style cast or other flavour of expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201542 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index bd01cabd7e..d364155c91 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -5082,8 +5082,11 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { } CXXBindTemporaryExpr *TopBind = dyn_cast(E); - if (TopBind) - E = TopBind->getSubExpr(); + CallExpr *TopCall = TopBind ? dyn_cast(TopBind->getSubExpr()) : 0; + if (TopCall) + E = TopCall; + else + TopBind = 0; // Disable the special decltype handling now. ExprEvalContexts.back().IsDecltype = false; @@ -5094,7 +5097,6 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { return Owned(E); // Perform the semantic checks we delayed until this point. - CallExpr *TopCall = dyn_cast(E); for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size(); I != N; ++I) { CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I]; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp index 1ed93b1375..7f1b3b0f24 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp @@ -30,29 +30,33 @@ struct DD { typedef int n; }; +PD pd(); +DD dd(); + struct A { - decltype(PD()) s; // ok - decltype(PD())::n n; // ok - decltype(DD()) *p = new decltype(DD()); // ok + decltype(pd()) s; // ok + decltype(pd())::n n; // ok + decltype(dd()) *p = new decltype(dd()); // ok }; +A a(); // Two errors here: one for the decltype, one for the variable. decltype( - PD(), // expected-error {{private destructor}} - PD()) pd1; // expected-error {{private destructor}} -decltype(DD(), // expected-error {{deleted function}} - DD()) dd1; -decltype(A(), - DD()) dd2; // expected-error {{deleted function}} + pd(), // expected-error {{private destructor}} + pd()) pd1; // expected-error {{private destructor}} +decltype(dd(), // expected-error {{deleted function}} + dd()) dd1; +decltype(a(), + dd()) dd2; // expected-error {{deleted function}} decltype( - PD(), // expected-error {{temporary of type 'PD' has private destructor}} + pd(), // expected-error {{temporary of type 'PD' has private destructor}} 0) pd2; -decltype(((13, ((DD())))))::n dd_parens; // ok -decltype(((((42)), PD())))::n pd_parens_comma; // ok +decltype(((13, ((dd())))))::n dd_parens; // ok +decltype(((((42)), pd())))::n pd_parens_comma; // ok // Ensure parens aren't stripped from a decltype node. -extern decltype(PD()) pd_ref; // ok +extern decltype(pd()) pd_ref; // ok decltype((pd_ref)) pd_ref3 = pd_ref; // ok, PD & decltype(pd_ref) pd_ref2 = pd_ref; // expected-error {{private destructor}} @@ -107,7 +111,7 @@ namespace RequireCompleteType { namespace Overload { DD operator+(PD &a, PD &b); - decltype(PD()) *pd_ptr; + decltype(pd()) *pd_ptr; decltype(*pd_ptr + *pd_ptr) *dd_ptr; // ok decltype(0, *pd_ptr) pd_ref2 = pd_ref; // ok diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp index d6e85d285d..8de5a9c3ba 100644 --- a/test/SemaCXX/decltype.cpp +++ b/test/SemaCXX/decltype.cpp @@ -45,6 +45,16 @@ namespace PR16529 { U &r = S::f(); } +namespace PR18876 { + struct A { ~A() = delete; }; // expected-note +{{here}} + A f(); + decltype(f()) *a; // ok, function call + decltype(A()) *b; // expected-error {{attempt to use a deleted function}} + decltype(0, f()) *c; // ok, function call on RHS of comma + decltype(0, A()) *d; // expected-error {{attempt to use a deleted function}} + decltype(f(), 0) *e; // expected-error {{attempt to use a deleted function}} +} + template class conditional { };