[cfe-commits] r91252 - in /cfe/trunk: lib/Sema/TreeTransform.h test/SemaTemplate/instantiate-expr-1.cpp

Douglas Gregor dgregor at apple.com
Sun Dec 13 12:44:56 PST 2009


Author: dgregor
Date: Sun Dec 13 14:44:55 2009
New Revision: 91252

URL: http://llvm.org/viewvc/llvm-project?rev=91252&view=rev
Log:
Fix template instantiation for non-dependent calls to overloaded call
operators. Fixes PR5266.

Modified:
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=91252&r1=91251&r2=91252&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sun Dec 13 14:44:55 2009
@@ -4131,6 +4131,68 @@
 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();

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp?rev=91252&r1=91251&r2=91252&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp Sun Dec 13 14:44:55 2009
@@ -94,3 +94,21 @@
 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);
+}





More information about the cfe-commits mailing list