[cfe-commits] r86238 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp test/FixIt/fixit-errors.c test/SemaCXX/member-expr.cpp

Douglas Gregor dgregor at apple.com
Thu Nov 5 22:30:47 PST 2009


Author: dgregor
Date: Fri Nov  6 00:30:47 2009
New Revision: 86238

URL: http://llvm.org/viewvc/llvm-project?rev=86238&view=rev
Log:
Rework the fix-it hint for code like

  get_origin->x

where get_origin is actually a function and the user has forgotten the
parentheses. Instead of giving a lame note for the fix-it, give a
full-fledge error, early, then build the call expression to try to
recover. 

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/FixIt/fixit-errors.c
    cfe/trunk/test/SemaCXX/member-expr.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=86238&r1=86237&r2=86238&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Nov  6 00:30:47 2009
@@ -1447,8 +1447,9 @@
   "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_member_reference_needs_call : Error<
+  "base of member reference has function type %0; perhaps you meant to call "
+  "this function with '()'?">;
 def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
   InGroup<CharSubscript>, DefaultIgnore;
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=86238&r1=86237&r2=86238&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Nov  6 00:30:47 2009
@@ -1882,6 +1882,38 @@
   DefaultFunctionArrayConversion(BaseExpr);
 
   QualType BaseType = BaseExpr->getType();
+
+  // If the user is trying to apply -> or . to a function pointer
+  // type, it's probably because the forgot parentheses to call that
+  // function. Suggest the addition of those parentheses, build the
+  // call, and continue on.
+  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+    if (const FunctionProtoType *Fun
+          = Ptr->getPointeeType()->getAs<FunctionProtoType>()) {
+      QualType ResultTy = Fun->getResultType();
+      if (Fun->getNumArgs() == 0 &&
+          ((OpKind == tok::period && ResultTy->isRecordType()) ||
+           (OpKind == tok::arrow && ResultTy->isPointerType() &&
+            ResultTy->getAs<PointerType>()->getPointeeType()
+                                                          ->isRecordType()))) {
+        SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+        Diag(Loc, diag::err_member_reference_needs_call)
+          << QualType(Fun, 0)
+          << CodeModificationHint::CreateInsertion(Loc, "()");
+        
+        OwningExprResult NewBase
+          = ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc, 
+                          MultiExprArg(*this, 0, 0), 0, Loc);
+        if (NewBase.isInvalid())
+          return move(NewBase);
+        
+        BaseExpr = NewBase.takeAs<Expr>();
+        DefaultFunctionArrayConversion(BaseExpr);
+        BaseType = BaseExpr->getType();
+      }
+    }
+  }
+
   // If this is an Objective-C pseudo-builtin and a definition is provided then
   // use that.
   if (BaseType->isObjCIdType()) {
@@ -2437,18 +2469,6 @@
   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->getAs<PointerType>()->isFunctionType())) {
-    SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
-    Diag(Loc, diag::note_member_reference_needs_call)
-      << CodeModificationHint::CreateInsertion(Loc, "()");
-  }
-
   return ExprError();
 }
 

Modified: cfe/trunk/test/FixIt/fixit-errors.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-errors.c?rev=86238&r1=86237&r2=86238&view=diff

==============================================================================
--- cfe/trunk/test/FixIt/fixit-errors.c (original)
+++ cfe/trunk/test/FixIt/fixit-errors.c Fri Nov  6 00:30:47 2009
@@ -8,3 +8,13 @@
 struct s; // expected-note{{previous use is here}}
 
 union s *s1; // expected-error{{use of 's' with tag type that does not match previous declaration}}
+
+struct Point {
+  float x, y, z;
+};
+
+struct Point *get_origin();
+
+void test_point() {
+  (void)get_origin->x;
+}

Modified: cfe/trunk/test/SemaCXX/member-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-expr.cpp?rev=86238&r1=86237&r2=86238&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/member-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-expr.cpp Fri Nov  6 00:30:47 2009
@@ -28,8 +28,7 @@
  A *f0();
 };
 int f0(B *b) {
-  return b->f0->f0; // expected-error{{member reference base type 'struct A *()' is not a structure or union}} \
-  // expected-note{{perhaps you meant to call this function}}
+  return b->f0->f0; // expected-error{{perhaps you meant to call this function}}
 }
 
 int i;





More information about the cfe-commits mailing list