]> granicus.if.org Git - clang/commitdiff
PR17533 and duplicates: don't compute the return type of an overloaded operator
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 15 Nov 2013 02:58:23 +0000 (02:58 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 15 Nov 2013 02:58:23 +0000 (02:58 +0000)
until after we've referenced the operator; otherwise, we might pick up a
not-yet-deduced type.

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

lib/Sema/SemaDecl.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/cxx1y-deduced-return-type.cpp

index d5ba089f73315155fb2d6433a06dd00500bc29f5..211e8587d16d0c9e294d17d2e20244b9f207cd22 100644 (file)
@@ -6737,12 +6737,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
         Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
     }
 
-    if (getLangOpts().CPlusPlus1y && NewFD->isDependentContext() &&
+    if (getLangOpts().CPlusPlus1y &&
+        (NewFD->isDependentContext() ||
+         (isFriend && CurContext->isDependentContext())) &&
         NewFD->getResultType()->isUndeducedType()) {
       // If the function template is referenced directly (for instance, as a
       // member of the current instantiation), pretend it has a dependent type.
       // This is not really justified by the standard, but is the only sane
       // thing to do.
+      // FIXME: For a friend function, we have not marked the function as being
+      // a friend yet, so 'isDependentContext' on the FD doesn't work.
       const FunctionProtoType *FPT =
           NewFD->getType()->castAs<FunctionProtoType>();
       QualType Result = SubstAutoType(FPT->getResultType(),
index f4b75dac3a6a6948e2e09d232a2d8ba11036e9a0..802f2b7290b31612655aed14366fda389a95cbc5 100644 (file)
@@ -10523,17 +10523,17 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
         Input = InputInit.take();
       }
 
-      // Determine the result type.
-      QualType ResultTy = FnDecl->getResultType();
-      ExprValueKind VK = Expr::getValueKindForType(ResultTy);
-      ResultTy = ResultTy.getNonLValueExprType(Context);
-
       // Build the actual expression node.
       ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl,
                                                 HadMultipleCandidates, OpLoc);
       if (FnExpr.isInvalid())
         return ExprError();
 
+      // Determine the result type.
+      QualType ResultTy = FnDecl->getResultType();
+      ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+      ResultTy = ResultTy.getNonLValueExprType(Context);
+
       Args[0] = Input;
       CallExpr *TheCall =
         new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), ArgsArray,
@@ -10757,11 +10757,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
           Args[1] = RHS = Arg1.takeAs<Expr>();
         }
 
-        // Determine the result type.
-        QualType ResultTy = FnDecl->getResultType();
-        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
-        ResultTy = ResultTy.getNonLValueExprType(Context);
-
         // Build the actual expression node.
         ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
                                                   Best->FoundDecl,
@@ -10769,6 +10764,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
         if (FnExpr.isInvalid())
           return ExprError();
 
+        // Determine the result type.
+        QualType ResultTy = FnDecl->getResultType();
+        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+        ResultTy = ResultTy.getNonLValueExprType(Context);
+
         CXXOperatorCallExpr *TheCall =
           new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
                                             Args, ResultTy, VK, OpLoc,
@@ -10969,11 +10969,6 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
 
         Args[1] = InputInit.takeAs<Expr>();
 
-        // Determine the result type
-        QualType ResultTy = FnDecl->getResultType();
-        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
-        ResultTy = ResultTy.getNonLValueExprType(Context);
-
         // Build the actual expression node.
         DeclarationNameInfo OpLocInfo(OpName, LLoc);
         OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
@@ -10985,6 +10980,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
         if (FnExpr.isInvalid())
           return ExprError();
 
+        // Determine the result type
+        QualType ResultTy = FnDecl->getResultType();
+        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+        ResultTy = ResultTy.getNonLValueExprType(Context);
+
         CXXOperatorCallExpr *TheCall =
           new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
                                             FnExpr.take(), Args,
index 3e19cb57f3fe7f1ff3da7a6a2f30de8d47f149cb..d3308b3fd50bfd8924703ceddee828ab37ced381 100644 (file)
@@ -457,3 +457,22 @@ void bar() { puts("bar"); }
 int main() { return foo(0); }
 
 }
+
+namespace OverloadedOperators {
+  template<typename T> struct A {
+    auto operator()() { return T{}; }
+    auto operator[](int) { return T{}; }
+    auto operator+(int) { return T{}; }
+    auto operator+() { return T{}; }
+    friend auto operator-(A) { return T{}; }
+    friend auto operator-(A, A) { return T{}; }
+  };
+  void f(A<int> a) {
+    int b = a();
+    int c = a[0];
+    int d = a + 0;
+    int e = +a;
+    int f = -a;
+    int g = a - a;
+  }
+}