diff options
Diffstat (limited to 'clang/lib/Sema/SemaCast.cpp')
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 3e06a6477d6..d28a24453e2 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -389,6 +389,33 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, S.Diag(opRange.getBegin(), msg) << castType << src->getType() << destType << opRange << src->getSourceRange(); + + // Detect if both types are (ptr to) class, and note any incompleteness. + int DifferentPtrness = 0; + QualType From = destType; + if (auto Ptr = From->getAs<PointerType>()) { + From = Ptr->getPointeeType(); + DifferentPtrness++; + } + QualType To = src->getType(); + if (auto Ptr = To->getAs<PointerType>()) { + To = Ptr->getPointeeType(); + DifferentPtrness--; + } + if (!DifferentPtrness) { + auto RecFrom = From->getAs<RecordType>(); + auto RecTo = To->getAs<RecordType>(); + if (RecFrom && RecTo) { + auto DeclFrom = RecFrom->getAsCXXRecordDecl(); + if (!DeclFrom->isCompleteDefinition()) + S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) + << DeclFrom->getDeclName(); + auto DeclTo = RecTo->getAsCXXRecordDecl(); + if (!DeclTo->isCompleteDefinition()) + S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) + << DeclTo->getDeclName(); + } + } } /// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, @@ -1079,6 +1106,14 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, if (!CStyle && Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind)) return TC_Success; + + // See if it looks like the user is trying to convert between + // related record types, and select a better diagnostic if so. + if (auto SrcPointer = SrcType->getAs<PointerType>()) + if (auto DestPointer = DestType->getAs<PointerType>()) + if (SrcPointer->getPointeeType()->getAs<RecordType>() && + DestPointer->getPointeeType()->getAs<RecordType>()) + msg = diag::err_bad_cxx_cast_unrelated_class; // We tried everything. Everything! Nothing works! :-( return TC_NotApplicable; |