]> granicus.if.org Git - clang/commitdiff
When clearing a LookupResult structure, clear out the naming class,
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Mar 2011 22:32:08 +0000 (22:32 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Mar 2011 22:32:08 +0000 (22:32 +0000)
too. Fixes PR7900.

While I'm in this area, improve the diagnostic when the type being
destroyed doesn't match either of the types we found.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127041 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Lookup.h
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/destructor.cpp
test/SemaCXX/pseudo-destructors.cpp

index 1fc3d7b104bf7fab299a0bbed5e373ddf6bb338e..38e072e8de4a7340c411888c9736253f292a42f3 100644 (file)
@@ -791,8 +791,13 @@ def err_destructor_name : Error<
   "expected the class name after '~' to name the enclosing class">;
 def err_destructor_class_name : Error<
   "expected the class name after '~' to name a destructor">;
-def err_ident_in_pseudo_dtor_not_a_type : Error<
-  "identifier %0 in pseudo-destructor expression does not name a type">;
+def err_ident_in_dtor_not_a_type : Error<
+  "identifier %0 in object destruction expression does not name a type">;
+def err_destructor_expr_type_mismatch : Error<
+  "destructor type %0 in object destruction expression does not match the "
+  "type %1 of the object being destroyed">;
+def note_destructor_type_here : Note<
+  "type %0 is declared here">;
 
 // C++ initialization
 def err_init_conversion_failed : Error<
index aa58d14fac73167e35acbb0fe0cedd66cdad5ac6..400a7cc9194deacea2b0fd0832b3bb09d304643e 100644 (file)
@@ -439,6 +439,7 @@ public:
     Decls.clear();
     if (Paths) deletePaths(Paths);
     Paths = NULL;
+    NamingClass = 0;
   }
 
   /// \brief Clears out any current state and re-initializes for a
index 7d029cbd35ded5896496b7ee4f6764364260d8e1..eee02096ac794cb67b9a429fdf49337641402070 100644 (file)
@@ -138,10 +138,11 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
     LookInScope = true;
   }
 
+  TypeDecl *NonMatchingTypeDecl = 0;
   LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
   for (unsigned Step = 0; Step != 2; ++Step) {
     // Look for the name first in the computed lookup context (if we
-    // have one) and, if that fails to find a match, in the sope (if
+    // have one) and, if that fails to find a match, in the scope (if
     // we're allowed to look there).
     Found.clear();
     if (Step == 0 && LookupCtx)
@@ -164,6 +165,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
 
         return ParsedType::make(T);
       }
+      
+      if (!SearchType.isNull())
+        NonMatchingTypeDecl = Type;
     }
 
     // If the name that we found is a class template name, and it is
@@ -244,8 +248,14 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
     return ParsedType::make(T);
   }
 
-  if (ObjectTypePtr)
-    Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+  if (NonMatchingTypeDecl) {
+    QualType T = Context.getTypeDeclType(NonMatchingTypeDecl);
+    Diag(NameLoc, diag::err_destructor_expr_type_mismatch)
+      << T << SearchType;
+    Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here)
+      << T;
+  } else if (ObjectTypePtr)
+    Diag(NameLoc, diag::err_ident_in_dtor_not_a_type)
       << &II;
   else
     Diag(NameLoc, diag::err_destructor_class_name);
index 14a4fb891cd3b2e145b9d937512654658892bbae..01f21de6de17cd2e89fb88569a250b1e3598d105 100644 (file)
@@ -177,3 +177,16 @@ namespace PR9238 {
   class B { public: ~B(); };
   class C : virtual B { public: ~C() { } };
 }
+
+namespace PR7900 {
+  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
+  };
+  struct B : public A {
+  };
+  void foo() {
+    B b;
+    b.~B();
+    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
+    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
+  }
+}
index 30d9faac2e284a0b58a6281ea632ad5b61d0c959..d71304e28b11200cb6a1a0c7d0d2d53e89b13ccf 100644 (file)
@@ -2,7 +2,7 @@
 struct A {};
 
 enum Foo { F };
-typedef Foo Bar;
+typedef Foo Bar; // expected-note{{type 'Bar' (aka 'Foo') is declared here}}
 
 typedef int Integer;
 typedef double Double;
@@ -23,10 +23,9 @@ void f(A* a, Foo *f, int *i, double *d) {
   a->~A();
   a->A::~A();
   
-  a->~foo(); // expected-error{{identifier 'foo' in pseudo-destructor expression does not name a type}}
+  a->~foo(); // expected-error{{identifier 'foo' in object destruction expression does not name a type}}
   
-  // FIXME: the diagnostic below isn't wonderful
-  a->~Bar(); // expected-error{{does not name a type}}
+  a->~Bar(); // expected-error{{destructor type 'Bar' (aka 'Foo') in object destruction expression does not match the type 'A' of the object being destroyed}}
   
   f->~Bar();
   f->~Foo();