Author: rsmith Date: Thu Oct 5 12:35:51 2017 New Revision: 315005 URL: http://llvm.org/viewvc/llvm-project?rev=315005&view=rev Log: Fix two-phase name lookup for non-dependent overloaded operators.
If we resolve an overloaded operator call to a specific function during template definition, don't perform ADL during template instantiation. Doing so finds overloads that we're not supposed to find. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/test/SemaCXX/overloaded-operator.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=315005&r1=315004&r2=315005&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Oct 5 12:35:51 2017 @@ -2914,12 +2914,13 @@ public: ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *input); + Expr *input, bool RequiresADL = true); ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS); + Expr *LHS, Expr *RHS, + bool RequiresADL = true); ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, SourceLocation RLoc, Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=315005&r1=315004&r2=315005&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Oct 5 12:35:51 2017 @@ -11927,7 +11927,7 @@ static bool IsOverloaded(const Unresolve ExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *Input) { + Expr *Input, bool PerformADL) { OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc); assert(Op != OO_None && "Invalid opcode for overloaded unary operator"); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); @@ -11978,9 +11978,11 @@ Sema::CreateOverloadedUnaryOp(SourceLoca AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); // Add candidates from ADL. - AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray, - /*ExplicitTemplateArgs*/nullptr, - CandidateSet); + if (PerformADL) { + AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray, + /*ExplicitTemplateArgs*/nullptr, + CandidateSet); + } // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -12118,7 +12120,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS) { + Expr *LHS, Expr *RHS, bool PerformADL) { Expr *Args[2] = { LHS, RHS }; LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple @@ -12149,7 +12151,7 @@ Sema::CreateOverloadedBinOp(SourceLocati UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, - /*ADL*/ true, IsOverloaded(Fns), + /*ADL*/PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end()); return new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy, @@ -12192,7 +12194,7 @@ Sema::CreateOverloadedBinOp(SourceLocati // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not // performed for an assignment operator (nor for operator[] nor operator->, // which don't get here). - if (Opc != BO_Assign) + if (Opc != BO_Assign && PerformADL) AddArgumentDependentLookupCandidates(OpName, OpLoc, Args, /*ExplicitTemplateArgs*/ nullptr, CandidateSet); Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=315005&r1=315004&r2=315005&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Oct 5 12:35:51 2017 @@ -12636,10 +12636,14 @@ TreeTransform<Derived>::RebuildCXXOperat // Compute the transformed set of functions (and function templates) to be // used during overload resolution. UnresolvedSet<16> Functions; + bool RequiresADL; if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) { - assert(ULE->requiresADL()); Functions.append(ULE->decls_begin(), ULE->decls_end()); + // If the overload could not be resolved in the template definition + // (because we had a dependent argument), ADL is performed as part of + // template instantiation. + RequiresADL = ULE->requiresADL(); } else { // If we've resolved this to a particular non-member function, just call // that function. If we resolved it to a member function, @@ -12647,6 +12651,7 @@ TreeTransform<Derived>::RebuildCXXOperat NamedDecl *ND = cast<DeclRefExpr>(Callee)->getDecl(); if (!isa<CXXMethodDecl>(ND)) Functions.addDecl(ND); + RequiresADL = false; } // Add any functions found via argument-dependent lookup. @@ -12657,7 +12662,8 @@ TreeTransform<Derived>::RebuildCXXOperat if (NumArgs == 1 || isPostIncDec) { UnaryOperatorKind Opc = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); - return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First); + return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First, + RequiresADL); } if (Op == OO_Subscript) { @@ -12681,8 +12687,8 @@ TreeTransform<Derived>::RebuildCXXOperat // Create the overloaded operator invocation for binary operators. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); - ExprResult Result - = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]); + ExprResult Result = SemaRef.CreateOverloadedBinOp( + OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL); if (Result.isInvalid()) return ExprError(); Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=315005&r1=315004&r2=315005&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original) +++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Thu Oct 5 12:35:51 2017 @@ -550,3 +550,38 @@ namespace PR27027 { bool test_global_1 = +a_global; // expected-error {{overload resolution selected deleted operator '+'}} bool test_global_2 = a_global + a_global; // expected-error {{overload resolution selected deleted operator '+'}} } + +namespace LateADLInNonDependentExpressions { + struct A {}; + struct B : A {}; + int &operator+(A, A); + int &operator!(A); + int &operator+=(A, A); + int &operator<<(A, A); + int &operator++(A); + int &operator++(A, int); + int &operator->*(A, A); + + template<typename T> void f() { + // An instantiation-dependent value of type B. + // These are all non-dependent operator calls of type int&. +#define idB ((void()), B()) + int &a = idB + idB, + &b = !idB, + &c = idB += idB, + &d = idB << idB, + &e = ++idB, + &f = idB++, + &g = idB ->* idB; + } + + // These should not be found by ADL in the template instantiation. + float &operator+(B, B); + float &operator!(B); + float &operator+=(B, B); + float &operator<<(B, B); + float &operator++(B); + float &operator++(B, int); + float &operator->*(B, B); + template void f<int>(); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits