arphaman created this revision. arphaman added reviewers: dblaikie, majnemer. arphaman added a subscriber: cfe-commits. arphaman set the repository for this revision to rL LLVM.
This patch improves the mismatched destructor type error by detecting when the destructor call has used a '.' instead of a '->' on a pointer to the destructed type. For example, when given the code sample below: struct Bar { ~Bar(); }; void bar(Bar *object) { object.~Bar(); } Clang will now produce the following diagnostic: `error: member reference type 'Bar *' is a pointer; did you mean to use '->'?`. Repository: rL LLVM https://reviews.llvm.org/D25817 Files: lib/Sema/SemaExprCXX.cpp test/CXX/special/class.dtor/p10-0x.cpp test/SemaCXX/pseudo-destructors.cpp Index: test/SemaCXX/pseudo-destructors.cpp =================================================================== --- test/SemaCXX/pseudo-destructors.cpp +++ test/SemaCXX/pseudo-destructors.cpp @@ -89,3 +89,26 @@ void AliasTemplate(int *p) { p->~Id<int>(); } + +namespace dotPointerAccess { +struct Base { + virtual ~Base() {} +}; + +struct Derived : Base { + ~Derived() {} +}; + +void test() { + Derived d; + static_cast<Base *>(&d).~Base(); // expected-error {{member reference type 'dotPointerAccess::Base *' is a pointer; did you mean to use '->'}} + d->~Derived(); // expected-error {{member reference type 'dotPointerAccess::Derived' is not a pointer; did you mean to use '.'}} +} + +typedef Derived *Foo; + +void test2(Foo d) { + d.~Foo(); // This is ok + d.~Derived(); // expected-error {{member reference type 'Foo' (aka 'dotPointerAccess::Derived *') is a pointer; did you mean to use '->'}} +} +} 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 @@ -33,7 +33,7 @@ expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} i.~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}} pi->~decltype(int())(); - pi.~decltype(int())(); // expected-error{{the type of object expression ('int *') does not match the type being destroyed ('decltype(int())' (aka 'int')) in pseudo-destructor expression}} + pi.~decltype(int())(); // expected-error{{member reference type 'int *' is a pointer; did you mean to use '->'?}} 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}} } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -6279,9 +6279,20 @@ = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!DestructedType->isDependentType() && !ObjectType->isDependentType()) { if (!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { - Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) - << ObjectType << DestructedType << Base->getSourceRange() - << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + // Detect dot pseudo destructor calls on pointer objects, e.g.: + // Foo *foo; + // foo.~Foo(); + if (OpKind == tok::period && ObjectType->isPointerType() && + Context.hasSameUnqualifiedType(DestructedType, + ObjectType->getPointeeType())) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << /*IsArrow=*/0 << Base->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "->"); + } else { + Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) + << ObjectType << DestructedType << Base->getSourceRange() + << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + } // Recover by setting the destructed type to the object type. DestructedType = ObjectType;
Index: test/SemaCXX/pseudo-destructors.cpp =================================================================== --- test/SemaCXX/pseudo-destructors.cpp +++ test/SemaCXX/pseudo-destructors.cpp @@ -89,3 +89,26 @@ void AliasTemplate(int *p) { p->~Id<int>(); } + +namespace dotPointerAccess { +struct Base { + virtual ~Base() {} +}; + +struct Derived : Base { + ~Derived() {} +}; + +void test() { + Derived d; + static_cast<Base *>(&d).~Base(); // expected-error {{member reference type 'dotPointerAccess::Base *' is a pointer; did you mean to use '->'}} + d->~Derived(); // expected-error {{member reference type 'dotPointerAccess::Derived' is not a pointer; did you mean to use '.'}} +} + +typedef Derived *Foo; + +void test2(Foo d) { + d.~Foo(); // This is ok + d.~Derived(); // expected-error {{member reference type 'Foo' (aka 'dotPointerAccess::Derived *') is a pointer; did you mean to use '->'}} +} +} 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 @@ -33,7 +33,7 @@ expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} i.~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}} pi->~decltype(int())(); - pi.~decltype(int())(); // expected-error{{the type of object expression ('int *') does not match the type being destroyed ('decltype(int())' (aka 'int')) in pseudo-destructor expression}} + pi.~decltype(int())(); // expected-error{{member reference type 'int *' is a pointer; did you mean to use '->'?}} 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}} } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -6279,9 +6279,20 @@ = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!DestructedType->isDependentType() && !ObjectType->isDependentType()) { if (!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { - Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) - << ObjectType << DestructedType << Base->getSourceRange() - << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + // Detect dot pseudo destructor calls on pointer objects, e.g.: + // Foo *foo; + // foo.~Foo(); + if (OpKind == tok::period && ObjectType->isPointerType() && + Context.hasSameUnqualifiedType(DestructedType, + ObjectType->getPointeeType())) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << /*IsArrow=*/0 << Base->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "->"); + } else { + Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) + << ObjectType << DestructedType << Base->getSourceRange() + << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + } // Recover by setting the destructed type to the object type. DestructedType = ObjectType;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits