diff options
author | John McCall <rjmccall@apple.com> | 2009-12-07 22:46:59 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-12-07 22:46:59 +0000 |
commit | 812c15476c9dddb72a8fd48deb7ca86402664b94 (patch) | |
tree | 4126e8e54cab2de525cf3f47ce6bf24bb8cb5296 | |
parent | b40d06dec23b53bbc1157a9adae7f887be31aa3b (diff) |
Recover from dot accesses to record pointers and arrow accesses to records.
Patch by Nicola Gigante!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90814 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | TODO.txt | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 35 |
4 files changed, 35 insertions, 5 deletions
@@ -65,7 +65,6 @@ More ideas for code modification hints: - If no member of a given name is found in a class/struct, search through the names of entities that do exist in the class and suggest the closest candidate. e.g., if I write "DS.setTypeSpecType", it would suggest "DS.SetTypeSpecType" (edit distance = 1). - If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration. - Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid) - - Change "foo.bar" to "foo->bar" when "foo" is a pointer. //===---------------------------------------------------------------------===// diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d20da85ab3..57e1d33717 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1520,6 +1520,8 @@ def err_typecheck_member_reference_ivar : Error< "%0 does not have a member named %1">; def err_typecheck_member_reference_arrow : Error< "member reference type %0 is not a pointer">; +def err_typecheck_member_reference_suggestion : Error< + "member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">; def err_typecheck_member_reference_type : Error< "cannot refer to type member %0 with '%select{.|->}1'">; def err_typecheck_member_reference_unknown : Error< diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 4295655528..fbf1c41410 100644 --- a/lib/Sema/Sema.h +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8332bf8f7b..a63ce1e598 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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>()) { |