]> granicus.if.org Git - clang/commitdiff
Be sure to build a dependent expression when we see
authorJohn McCall <rjmccall@apple.com>
Fri, 28 Oct 2011 01:04:34 +0000 (01:04 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 28 Oct 2011 01:04:34 +0000 (01:04 +0000)
a binary operator involving a dependently-typed overload set.

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

lib/Sema/SemaExpr.cpp
test/CodeGenCXX/assign-operator.cpp

index 880199bc7ac55f0c76cca31f06c8f4557b1f7174..a733b81361657269d288ea9d5a8e2eafe02a0f15 100644 (file)
@@ -8007,6 +8007,12 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
 ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
                             BinaryOperatorKind Opc,
                             Expr *LHSExpr, Expr *RHSExpr) {
+  // We want to end up calling one of checkPseudoObjectAssignment
+  // (if the LHS is a pseudo-object), BuildOverloadedBinOp (if
+  // both expressions are overloadable or either is type-dependent),
+  // or CreateBuiltinBinOp (in any other case).  We also want to get
+  // any placeholder types out of the way.
+
   // Handle pseudo-objects in the LHS.
   if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
     // Assignments with a pseudo-object l-value need special analysis.
@@ -8018,12 +8024,15 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
     if (pty->getKind() == BuiltinType::Overload) {
       // We can't actually test that if we still have a placeholder,
       // though.  Fortunately, none of the exceptions we see in that
-      // code below are valid when the LHS is an overload set.
+      // code below are valid when the LHS is an overload set.  Note
+      // that an overload set can be dependently-typed, but it never
+      // instantiates to having an overloadable type.
       ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
       if (resolvedRHS.isInvalid()) return ExprError();
       RHSExpr = resolvedRHS.take();
 
-      if (RHSExpr->getType()->isOverloadableType())
+      if (RHSExpr->isTypeDependent() ||
+          RHSExpr->getType()->isOverloadableType())
         return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
     }
         
@@ -8036,8 +8045,12 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
   if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) {
     // An overload in the RHS can potentially be resolved by the type
     // being assigned to.
-    if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload)
+    if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) {
+      if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
+        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
       return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
+    }
 
     // Don't resolve overloads if the other type is overloadable.
     if (pty->getKind() == BuiltinType::Overload &&
@@ -8050,16 +8063,15 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
   }
 
   if (getLangOptions().CPlusPlus) {
-    bool UseBuiltinOperator;
-
-    if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) {
-      UseBuiltinOperator = false;
-    } else {
-      UseBuiltinOperator = !LHSExpr->getType()->isOverloadableType() &&
-                           !RHSExpr->getType()->isOverloadableType();
-    }
+    // If either expression is type-dependent, always build an
+    // overloaded op.
+    if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
+      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
 
-    if (!UseBuiltinOperator)
+    // Otherwise, build an overloaded op if either expression has an
+    // overloadable type.
+    if (LHSExpr->getType()->isOverloadableType() ||
+        RHSExpr->getType()->isOverloadableType())
       return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
   }
 
index c4b64e6e51addf1154436bc1977cf1c2feb579f1..e19df272c9ad08f44e13846232ce94a3e7dc7af0 100644 (file)
@@ -17,3 +17,14 @@ void f(int i, int j) {
   // CHECK: ret
   (i += j) = 17;
 }
+
+// Taken from g++.old-deja/g++.jason/net.C
+namespace test1 {
+  template <class T> void fn (T t) { }
+  template <class T> struct A {
+    void (*p)(T);
+    A() { p = fn; }
+  };
+
+  A<int> a;
+}