[PATCH] Parse: ~decltype(expr) needs an object to reference a dtor

David Majnemer david.majnemer at gmail.com
Mon Jul 21 14:14:36 PDT 2014


Hi rsmith,

An expression of the form ~decltype(expr) requires an object when
attempting to perform member lookup on the destructor.

This fixes PR20378.

http://reviews.llvm.org/D4606

Files:
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/SemaExprCXX.cpp
  test/CXX/special/class.dtor/p10-0x.cpp

Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2439,6 +2439,18 @@
     if (SS.isEmpty() && Tok.is(tok::kw_decltype)) {
       DeclSpec DS(AttrFactory);
       SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
+
+      // There are two cases to consider with ~decltype(expr):
+      //  - If a base object isn't present, the '~' will not refer to a
+      //  destructor but instead a unary complement.
+      //  - If a base object is present, it will perform member access on the
+      //  destructor.
+      //
+      // Since we are parsing a destructor, we must have a base object.
+      if (!ObjectType) {
+        Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_tilde_identifier);
+        return true;
+      }
       if (ParsedType Type = Actions.getDestructorType(DS, ObjectType)) {
         Result.setDestructorName(TildeLoc, Type, EndLoc);
         return false;
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -319,7 +319,8 @@
 }
 
 ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
-    if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType)
+    assert(ObjectType && "expected an object type!");
+    if (DS.getTypeSpecType() == DeclSpec::TST_error)
       return ParsedType();
     assert(DS.getTypeSpecType() == DeclSpec::TST_decltype 
            && "only get destructor types from declspecs");
Index: test/CXX/special/class.dtor/p10-0x.cpp
===================================================================
--- test/CXX/special/class.dtor/p10-0x.cpp
+++ test/CXX/special/class.dtor/p10-0x.cpp
@@ -24,8 +24,8 @@
   x->~decltype(x)(); // expected-error{{destructor type 'decltype(x)' (aka 'const A *') in object destruction expression does not match the type 'const A' of the object being destroyed}}
   // this last one could be better, mentioning that the nested-name-specifier could be removed or a type name after the ~
   x->::A::~decltype(*x)(); // expected-error{{expected a class name after '~' to name a destructor}}
-  y->~decltype(A())(); // expected-error{{use of undeclared identifier 'y'}}
-
+  y->~decltype(A())(); // expected-error{{use of undeclared identifier 'y'}} \
+                       // expected-error{{expected a class name after '~' to name a destructor}}
   typedef int *intp;
   i->~decltype(int())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}}
   i.~decltype(int())();
@@ -37,3 +37,17 @@
   pi.~decltype(intp())();
   pi->~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}}
 }
+
+namespace PR20378 {
+struct S;
+
+S *f();
+
+struct S {
+  static S g();
+  void h() { this->~decltype(g())(); }
+  void i() { ~decltype(g())(); } // expected-error{{invalid argument type 'decltype(g())' (aka 'PR20378::S') to unary expression}}
+  ~decltype(*f());               // expected-error{{expected a class name after '~' to name a destructor}}
+  ~decltype(0) {}                // expected-error{{expected a class name after '~' to name a destructor}}
+};
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4606.11719.patch
Type: text/x-patch
Size: 3363 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140721/74b2131a/attachment.bin>


More information about the cfe-commits mailing list