[cfe-commits] r102650 - in /cfe/trunk: lib/AST/Expr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp test/CodeGenCXX/address-of-fntemplate.cpp

Douglas Gregor dgregor at apple.com
Thu Apr 29 11:24:40 PDT 2010


Author: dgregor
Date: Thu Apr 29 13:24:40 2010
New Revision: 102650

URL: http://llvm.org/viewvc/llvm-project?rev=102650&view=rev
Log:
When determining a standard conversion sequence involves resolving the
address of an overloaded function (or function template), perform that
resolution prior to determining the implicit conversion
sequence. This resolution is not part of the implicit conversion
sequence itself.

Previously, we would always consider this resolution to be a
function pointer decay, which was a lie: there might be an explicit &
in the expression, in which case decay should not occur. This caused
the CodeGen assertion in PR6973 (where we created a 
pointer to a pointer to a function when we should have had a pointer
to a function), but it's likely that there are corner cases of
overload resolution where this would have failed.

Cleaned up the code involved in determining the type that will
produced afer resolving the overloaded function reference, and added
an assertion to make sure the result is correct. Fixes PR6973.



Modified:
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CodeGenCXX/address-of-fntemplate.cpp

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=102650&r1=102649&r2=102650&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Apr 29 13:24:40 2010
@@ -1345,6 +1345,7 @@
   case PredefinedExprClass:
     return LV_Valid;
   case UnresolvedLookupExprClass:
+  case UnresolvedMemberExprClass:
     return LV_Valid;
   case CXXDefaultArgExprClass:
     return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=102650&r1=102649&r2=102650&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Apr 29 13:24:40 2010
@@ -1660,6 +1660,21 @@
     return false;
   }
 
+  // Resolve overloaded function references.
+  if (Context.hasSameType(FromType, Context.OverloadTy)) {
+    DeclAccessPair Found;
+    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
+                                                          true, Found);
+    if (!Fn)
+      return true;
+
+    if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
+      return true;
+
+    From = FixOverloadedFunctionReference(From, Found, Fn);
+    FromType = From->getType();
+  }
+
   // Perform the first implicit conversion.
   switch (SCS.First) {
   case ICK_Identity:
@@ -1673,25 +1688,6 @@
     break;
 
   case ICK_Function_To_Pointer:
-    if (Context.getCanonicalType(FromType) == Context.OverloadTy) {
-      DeclAccessPair Found;
-      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
-                                                            true, Found);
-      if (!Fn)
-        return true;
-
-      if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
-        return true;
-
-      From = FixOverloadedFunctionReference(From, Found, Fn);
-      FromType = From->getType();
-        
-      // If there's already an address-of operator in the expression, we have
-      // the right type already, and the code below would just introduce an
-      // invalid additional pointer level.
-      if (FromType->isPointerType() || FromType->isMemberFunctionPointerType())
-        break;
-    }
     FromType = Context.getPointerType(FromType);
     ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay);
     break;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=102650&r1=102649&r2=102650&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Apr 29 13:24:40 2010
@@ -622,8 +622,36 @@
   // array-to-pointer conversion, or function-to-pointer conversion
   // (C++ 4p1).
 
-  DeclAccessPair AccessPair;
-
+  if (FromType == Context.OverloadTy) {
+    DeclAccessPair AccessPair;
+    if (FunctionDecl *Fn
+          = ResolveAddressOfOverloadedFunction(From, ToType, false, 
+                                               AccessPair)) {
+      // We were able to resolve the address of the overloaded function,
+      // so we can convert to the type of that function.
+      FromType = Fn->getType();
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+        if (!Method->isStatic()) {
+          Type *ClassType 
+            = Context.getTypeDeclType(Method->getParent()).getTypePtr();
+          FromType = Context.getMemberPointerType(FromType, ClassType);
+        }
+      }
+      
+      // If the "from" expression takes the address of the overloaded
+      // function, update the type of the resulting expression accordingly.
+      if (FromType->getAs<FunctionType>())
+        if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens()))
+          if (UnOp->getOpcode() == UnaryOperator::AddrOf)
+            FromType = Context.getPointerType(FromType);
+ 
+      // Check that we've computed the proper type after overload resolution.
+      assert(Context.hasSameType(FromType,
+              FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
+    } else {
+      return false;
+    }
+  } 
   // Lvalue-to-rvalue conversion (C++ 4.1):
   //   An lvalue (3.10) of a non-function, non-array type T can be
   //   converted to an rvalue.
@@ -668,36 +696,6 @@
     // type "pointer to T." The result is a pointer to the
     // function. (C++ 4.3p1).
     FromType = Context.getPointerType(FromType);
-  } else if (From->getType() == Context.OverloadTy) {
-    if (FunctionDecl *Fn
-          = ResolveAddressOfOverloadedFunction(From, ToType, false, 
-                                               AccessPair)) {
-      // Address of overloaded function (C++ [over.over]).
-      SCS.First = ICK_Function_To_Pointer;
-
-      // We were able to resolve the address of the overloaded function,
-      // so we can convert to the type of that function.
-      FromType = Fn->getType();
-      if (ToType->isLValueReferenceType())
-        FromType = Context.getLValueReferenceType(FromType);
-      else if (ToType->isRValueReferenceType())
-        FromType = Context.getRValueReferenceType(FromType);
-      else if (ToType->isMemberPointerType()) {
-        // Resolve address only succeeds if both sides are member pointers,
-        // but it doesn't have to be the same class. See DR 247.
-        // Note that this means that the type of &Derived::fn can be
-        // Ret (Base::*)(Args) if the fn overload actually found is from the
-        // base class, even if it was brought into the derived class via a
-        // using declaration. The standard isn't clear on this issue at all.
-        CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
-        FromType = Context.getMemberPointerType(FromType,
-                      Context.getTypeDeclType(M->getParent()).getTypePtr());
-      } else {
-        FromType = Context.getPointerType(FromType);
-      }
-    } else {
-      return false;
-    }
   } else {
     // We don't require any conversions for the first step.
     SCS.First = ICK_Identity;

Modified: cfe/trunk/test/CodeGenCXX/address-of-fntemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/address-of-fntemplate.cpp?rev=102650&r1=102649&r2=102650&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/address-of-fntemplate.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/address-of-fntemplate.cpp Thu Apr 29 13:24:40 2010
@@ -11,3 +11,17 @@
 }
 // CHECK: define linkonce_odr void @_Z1fIiEvT_
 // CHECK: define linkonce_odr void @_Z1fIiEvv
+
+namespace PR6973 {
+  template<typename T>
+  struct X {
+    void f(const T&);
+  };
+
+  template<typename T>
+  int g();
+
+  void h(X<int (*)()> xf) {
+    xf.f(&g<int>);
+  }
+}





More information about the cfe-commits mailing list