aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td9
-rw-r--r--include/clang/Sema/Lookup.h1
-rw-r--r--lib/Sema/SemaExprCXX.cpp16
-rw-r--r--test/SemaCXX/destructor.cpp13
-rw-r--r--test/SemaCXX/pseudo-destructors.cpp7
5 files changed, 37 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 1fc3d7b104..38e072e8de 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index aa58d14fac..400a7cc919 100644
--- a/include/clang/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -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
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 7d029cbd35..eee02096ac 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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);
diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp
index 14a4fb891c..01f21de6de 100644
--- a/test/SemaCXX/destructor.cpp
+++ b/test/SemaCXX/destructor.cpp
@@ -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}}
+ }
+}
diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp
index 30d9faac2e..d71304e28b 100644
--- a/test/SemaCXX/pseudo-destructors.cpp
+++ b/test/SemaCXX/pseudo-destructors.cpp
@@ -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();