diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 35 |
2 files changed, 33 insertions, 4 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 4295655528c..fbf1c414104 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1550,7 +1550,7 @@ public: const TemplateArgumentListInfo *TemplateArgs); OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, - bool IsArrow, SourceLocation OpLoc, + bool &IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, NamedDecl *FirstQualifierInScope, DeclPtrTy ObjCImpDecl); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8332bf8f7b1..a63ce1e598d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2473,7 +2473,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, /// fixed for ObjC++. Sema::OwningExprResult Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, - bool IsArrow, SourceLocation OpLoc, + bool &IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, NamedDecl *FirstQualifierInScope, DeclPtrTy ObjCImpDecl) { @@ -2614,13 +2614,42 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, BaseType = PT->getPointeeType(); else if (BaseType->isObjCObjectPointerType()) ; - else { + else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now. + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << CodeModificationHint::CreateReplacement(OpLoc, "."); + IsArrow = false; + } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr->getSourceRange(); return ExprError(); } + } else { + // Recover from dot accesses to pointers, e.g.: + // type *foo; + // foo.bar + // This is actually well-formed in two cases: + // - 'type' is an Objective C type + // - 'bar' is a pseudo-destructor name which happens to refer to + // the appropriate pointer type + if (MemberName.getNameKind() != DeclarationName::CXXDestructorName) { + const PointerType *PT = BaseType->getAs<PointerType>(); + if (PT && PT->getPointeeType()->isRecordType()) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << CodeModificationHint::CreateReplacement(OpLoc, "->"); + BaseType = PT->getPointeeType(); + IsArrow = true; + } + } } - + // Handle field access to simple records. This also handles access // to fields of the ObjC 'id' struct. if (const RecordType *RTy = BaseType->getAs<RecordType>()) { |