]> granicus.if.org Git - clang/commitdiff
If the user is trying to apply the -> or . member reference operator
authorDouglas Gregor <dgregor@apple.com>
Fri, 27 Mar 2009 06:00:30 +0000 (06:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 27 Mar 2009 06:00:30 +0000 (06:00 +0000)
to a function or function pointer, it's probably because the user
forgot to put in parentheses () to call the function.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67826 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/SemaCXX/member-expr.cpp

index 62647ff51c555c3005044002e3213938d4e189c6..05b8f512e182ab7a677ca6da155b320937a278ef 100644 (file)
@@ -872,6 +872,9 @@ def err_typecheck_member_reference_type : Error<
   "cannot refer to type member %0 with '%select{.|->}1'">;
 def err_typecheck_member_reference_unknown : Error<
   "cannot refer to member %0 with '%select{.|->}1'">;
+def note_member_reference_needs_call : Note<
+  "perhaps you meant to call this function with '()'?">;
+
 def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
 def err_typecheck_no_member : Error<"no member named %0">;
 def err_member_redeclared : Error<"class member cannot be redeclared">;
index 8922abd20b9a7c23cde7947f4da44cd82caad7b0..8b646e9943f325c96ee2fca6cecc50c627b3aa61 100644 (file)
@@ -2101,9 +2101,22 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
                                                     MemberLoc));
   }
 
-  return ExprError(Diag(MemberLoc,
-                        diag::err_typecheck_member_reference_struct_union)
-                     << BaseType << BaseExpr->getSourceRange());
+  Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
+    << BaseType << BaseExpr->getSourceRange();
+
+  // If the user is trying to apply -> or . to a function or function
+  // pointer, it's probably because they forgot parentheses to call
+  // the function. Suggest the addition of those parentheses.
+  if (BaseType == Context.OverloadTy || 
+      BaseType->isFunctionType() ||
+      (BaseType->isPointerType() && 
+       BaseType->getAsPointerType()->isFunctionType())) {
+    SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+    Diag(Loc, diag::note_member_reference_needs_call)
+      << CodeModificationHint::CreateInsertion(Loc, "()");
+  }
+
+  return ExprError();
 }
 
 /// ConvertArgumentsForCall - Converts the arguments specified in
index 58e5be955f63b1f97c671a4e7087769bc15ecdf4..60ee10df7f6a65c489232501004ef7623a68cd2e 100644 (file)
@@ -20,3 +20,14 @@ void test(X* xp, X x) {
   float f1 = x.g();
   float f2 = xp->g();
 }
+
+struct A {
+ int f0;
+};
+struct B {
+ A *f0();
+};
+int f0(B *b) {
+  return b->f0->f0; // expected-error{{member reference base type 'struct A *(void)' is not a structure or union}} \
+  // expected-note{{perhaps you meant to call this function}}
+}