]> granicus.if.org Git - clang/commitdiff
PR18876: The special-case rule that ignores the destruction of a top-level
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 18 Feb 2014 03:51:47 +0000 (03:51 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 18 Feb 2014 03:51:47 +0000 (03:51 +0000)
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

lib/Sema/SemaExprCXX.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp
test/SemaCXX/decltype.cpp

index bd01cabd7e41e1d3562267572d52095c90b7c7cf..d364155c91839351ee181b16c8716f1d3399093c 100644 (file)
@@ -5082,8 +5082,11 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
   }
 
   CXXBindTemporaryExpr *TopBind = dyn_cast<CXXBindTemporaryExpr>(E);
-  if (TopBind)
-    E = TopBind->getSubExpr();
+  CallExpr *TopCall = TopBind ? dyn_cast<CallExpr>(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<CallExpr>(E);
   for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size();
        I != N; ++I) {
     CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I];
index 1ed93b137540fe1aaa6f1b65d586876d16f7f17e..7f1b3b0f240ed8bad20edfcf1d85e26100c479e5 100644 (file)
@@ -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
index d6e85d285dd143b50357e23f897c3bbc0e8dea31..8de5a9c3baee283a974a5fb680ac6d0a6b0c2055 100644 (file)
@@ -45,6 +45,16 @@ namespace PR16529 {
   U &r = S<int>::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<typename>
 class conditional {
 };