aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--include/clang/Sema/Sema.h1
-rw-r--r--lib/Sema/SemaExprMember.cpp10
-rw-r--r--lib/Sema/SemaExprObjC.cpp15
-rw-r--r--test/FixIt/fixit-objc.m14
5 files changed, 41 insertions, 4 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 22848bcb35..3134bdd406 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4320,6 +4320,11 @@ def err_typecheck_member_reference_ivar_suggest : Error<
"%0 does not have a member named %1; did you mean %2?">;
def err_property_not_found_suggest : Error<
"property %0 not found on object of type %1; did you mean %2?">;
+def err_ivar_access_using_property_syntax_suggest : Error<
+ "property %0 not found on object of type %1; did you mean to access ivar %2?">;
+def err_property_found_suggest : Error<
+ "property %0 found on object of type %1; did you mean to access "
+ "it with the \".\" operator?">;
def err_undef_interface_suggest : Error<
"cannot find interface declaration for %0; did you mean %1?">;
def warn_undef_interface_suggest : Warning<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index d38667253d..724e1ea29c 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -5056,6 +5056,7 @@ public:
ExprResult
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Expr *BaseExpr,
+ SourceLocation OpLoc,
DeclarationName MemberName,
SourceLocation MemberLoc,
SourceLocation SuperLoc, QualType SuperType,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 082691ffed..9509768205 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -1080,6 +1080,13 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
Diag(IV->getLocation(), diag::note_previous_decl)
<< IV->getDeclName();
} else {
+ if (IsArrow && IDecl->FindPropertyDeclaration(Member)) {
+ Diag(MemberLoc,
+ diag::err_property_found_suggest)
+ << Member << BaseExpr.get()->getType()
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ return ExprError();
+ }
Res.clear();
Res.setLookupName(Member);
@@ -1284,7 +1291,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
}
// Normal property access.
- return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), MemberName, MemberLoc,
+ return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc,
+ MemberName, MemberLoc,
SourceLocation(), QualType(), false);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 84ac897b37..80d3a7451d 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -516,7 +516,8 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
/// objective C interface. This is a property reference expression.
ExprResult Sema::
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
- Expr *BaseExpr, DeclarationName MemberName,
+ Expr *BaseExpr, SourceLocation OpLoc,
+ DeclarationName MemberName,
SourceLocation MemberLoc,
SourceLocation SuperLoc, QualType SuperType,
bool Super) {
@@ -672,7 +673,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();
Diag(Property->getLocation(), diag::note_previous_decl)
<< Property->getDeclName();
- return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc,
+ return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
+ TypoResult, MemberLoc,
SuperLoc, SuperType, Super);
}
ObjCInterfaceDecl *ClassDeclared;
@@ -690,6 +692,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
return ExprError();
}
}
+ Diag(MemberLoc,
+ diag::err_ivar_access_using_property_syntax_suggest)
+ << MemberName << QualType(OPT, 0) << Ivar->getDeclName()
+ << FixItHint::CreateReplacement(OpLoc, "->");
+ return ExprError();
}
Diag(MemberLoc, diag::err_property_not_found)
@@ -726,7 +733,9 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
T = Context.getObjCObjectPointerType(T);
return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
- /*BaseExpr*/0, &propertyName,
+ /*BaseExpr*/0,
+ SourceLocation()/*OpLoc*/,
+ &propertyName,
propertyNameLoc,
receiverNameLoc, T, true);
}
diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m
index bf704c66a0..2e8bfaea6a 100644
--- a/test/FixIt/fixit-objc.m
+++ b/test/FixIt/fixit-objc.m
@@ -39,3 +39,17 @@ void f(Test *t) {
[t test:@"Foo"]]; // expected-error{{extraneous ']' before ';'}}
g(@"Foo")); // expected-error{{extraneous ')' before ';'}}
}
+
+// rdar://7861841
+@interface Radar7861841 {
+@public
+ int x;
+}
+
+@property (assign) int y;
+@end
+
+int f0(Radar7861841 *a) { return a.x; } // expected-error {{property 'x' not found on object of type 'Radar7861841 *'; did you mean to access ivar 'x'}}
+
+int f1(Radar7861841 *a) { return a->y; } // expected-error {{property 'y' found on object of type 'Radar7861841 *'; did you mean to access it with the "." operator?}}
+