diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 9 | ||||
-rw-r--r-- | include/clang/Sema/Lookup.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 16 | ||||
-rw-r--r-- | test/SemaCXX/destructor.cpp | 13 | ||||
-rw-r--r-- | test/SemaCXX/pseudo-destructors.cpp | 7 |
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(); |