]> granicus.if.org Git - clang/commitdiff
Fix template instantiation for non-dependent calls to overloaded call
authorDouglas Gregor <dgregor@apple.com>
Sun, 13 Dec 2009 20:44:55 +0000 (20:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 13 Dec 2009 20:44:55 +0000 (20:44 +0000)
operators. Fixes PR5266.

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

lib/Sema/TreeTransform.h
test/SemaTemplate/instantiate-expr-1.cpp

index f8e8f947be376f662a637a0f8ec4339c68141902..dc848a53ab5cbed58071f86f5f4ed5bdb88899a9 100644 (file)
@@ -4131,6 +4131,68 @@ TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
 template<typename Derived>
 Sema::OwningExprResult
 TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  switch (E->getOperator()) {
+  case OO_New:
+  case OO_Delete:
+  case OO_Array_New:
+  case OO_Array_Delete:
+    llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr");
+    return SemaRef.ExprError();
+    
+  case OO_Call: {
+    // This is a call to an object's operator().
+    assert(E->getNumArgs() >= 1 && "Object call is missing arguments");
+
+    // Transform the object itself.
+    OwningExprResult Object = getDerived().TransformExpr(E->getArg(0));
+    if (Object.isInvalid())
+      return SemaRef.ExprError();
+
+    // FIXME: Poor location information
+    SourceLocation FakeLParenLoc
+      = SemaRef.PP.getLocForEndOfToken(
+                              static_cast<Expr *>(Object.get())->getLocEnd());
+
+    // Transform the call arguments.
+    ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+    llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
+    for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) {
+      OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+      if (Arg.isInvalid())
+        return SemaRef.ExprError();
+
+      // FIXME: Poor source location information.
+      SourceLocation FakeCommaLoc
+        = SemaRef.PP.getLocForEndOfToken(
+                                 static_cast<Expr *>(Arg.get())->getLocEnd());
+      FakeCommaLocs.push_back(FakeCommaLoc);
+      Args.push_back(Arg.release());
+    }
+
+    return getDerived().RebuildCallExpr(move(Object), FakeLParenLoc,
+                                        move_arg(Args),
+                                        FakeCommaLocs.data(),
+                                        E->getLocEnd());
+  }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+  case OO_##Name:
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+  case OO_Subscript:
+    // Handled below.
+    break;
+
+  case OO_Conditional:
+    llvm_unreachable("conditional operator is not actually overloadable");
+    return SemaRef.ExprError();
+
+  case OO_None:
+  case NUM_OVERLOADED_OPERATORS:
+    llvm_unreachable("not an overloaded operator?");
+    return SemaRef.ExprError();
+  }
+
   OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
   if (Callee.isInvalid())
     return SemaRef.ExprError();
index fb88213c401be1f0f5f1709f06955984bde148fc..1cd55d9ad257e8964fa0997879213a06533e4d5b 100644 (file)
@@ -94,3 +94,21 @@ struct Addable {
 void test_add(Addable &a) {
   add(a);
 }
+
+struct CallOperator {
+  int &operator()(int);
+  double &operator()(double);
+};
+
+template<typename Result, typename F, typename Arg1>
+Result test_call_operator(F f, Arg1 arg1) {
+  // PR5266: non-dependent invocations of a function call operator.
+  CallOperator call_op;
+  int &ir = call_op(17);
+  return f(arg1);
+}
+
+void test_call_operator(CallOperator call_op, int i, double d) {
+  int &ir = test_call_operator<int&>(call_op, i);
+  double &dr = test_call_operator<double&>(call_op, d);
+}