From: Richard Smith Date: Fri, 15 Nov 2013 02:58:23 +0000 (+0000) Subject: PR17533 and duplicates: don't compute the return type of an overloaded operator X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f93ec7608aa79f9aac09304bfd3bc1918caf128f;p=clang PR17533 and duplicates: don't compute the return type of an overloaded operator 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 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d5ba089f73..211e8587d1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(); QualType Result = SubstAutoType(FPT->getResultType(), diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f4b75dac3a..802f2b7290 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(); } - // 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(); - // 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, diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index 3e19cb57f3..d3308b3fd5 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -457,3 +457,22 @@ void bar() { puts("bar"); } int main() { return foo(0); } } + +namespace OverloadedOperators { + template 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 a) { + int b = a(); + int c = a[0]; + int d = a + 0; + int e = +a; + int f = -a; + int g = a - a; + } +}