diff options
| author | Alex Lorenz <arphaman@gmail.com> | 2017-01-20 15:38:58 +0000 |
|---|---|---|
| committer | Alex Lorenz <arphaman@gmail.com> | 2017-01-20 15:38:58 +0000 |
| commit | 56fb6fef50070d92d3137bcf912580f607e465b8 (patch) | |
| tree | cd2e93513cebbef16d9e24a647a487f030f83a53 /clang/lib | |
| parent | 94b999b9df15661742fdce96e14ea694f3b8f9a5 (diff) | |
| download | bcm5719-llvm-56fb6fef50070d92d3137bcf912580f607e465b8.tar.gz bcm5719-llvm-56fb6fef50070d92d3137bcf912580f607e465b8.zip | |
[Sema] Improve the error diagnostic for dot destructor calls on pointer objects
This commit 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. The diagnostic now suggests to use '->' instead of '.', and adds a fixit
where appropriate.
rdar://28766702
Differential Revision: https://reviews.llvm.org/D25817
llvm-svn: 292615
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 191bb28df46..2bf1c739395 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6403,6 +6403,23 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, return false; } +/// \brief Check if it's ok to try and recover dot pseudo destructor calls on +/// pointer objects. +static bool +canRecoverDotPseudoDestructorCallsOnPointerObjects(Sema &SemaRef, + QualType DestructedType) { + // If this is a record type, check if its destructor is callable. + if (auto *RD = DestructedType->getAsCXXRecordDecl()) { + if (CXXDestructorDecl *D = SemaRef.LookupDestructor(RD)) + return SemaRef.CanUseDecl(D, /*TreatUnavailableAsInvalid=*/false); + return false; + } + + // Otherwise, check if it's a type for which it's valid to use a pseudo-dtor. + return DestructedType->isDependentType() || DestructedType->isScalarType() || + DestructedType->isVectorType(); +} + ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, @@ -6437,15 +6454,36 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, = 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(); - - // Recover by setting the destructed type to the object type. - DestructedType = ObjectType; - DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType, - DestructedTypeStart); - Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + // 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())) { + auto Diagnostic = + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << /*IsArrow=*/0 << Base->getSourceRange(); + + // Issue a fixit only when the destructor is valid. + if (canRecoverDotPseudoDestructorCallsOnPointerObjects( + *this, DestructedType)) + Diagnostic << FixItHint::CreateReplacement(OpLoc, "->"); + + // Recover by setting the object type to the destructed type and the + // operator to '->'. + ObjectType = DestructedType; + OpKind = tok::arrow; + } 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; + DestructedTypeInfo = + Context.getTrivialTypeSourceInfo(ObjectType, DestructedTypeStart); + Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + } } else if (DestructedType.getObjCLifetime() != ObjectType.getObjCLifetime()) { |

