From: Douglas Gregor Date: Fri, 4 Mar 2011 22:32:08 +0000 (+0000) Subject: When clearing a LookupResult structure, clear out the naming class, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ec1873d694cf870264694d2b61219a03492bc30;p=clang When clearing a LookupResult structure, clear out the naming class, 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 --- 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();