From 5485cc15c37ef2b684ba442f6563ca8883d958cc Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 31 Jul 2017 00:24:28 +0000 Subject: [PATCH] [Sema] Fix operator lookup to consider local extern declarations. Summary: Previously Clang was not considering operator declarations that occur at function scope. This is incorrect according to [over.match.oper]p3 > The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls. This patch changes operator name lookup to consider block scope declarations. This patch fixes PR27027. Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D35297 llvm-svn: 309530 --- clang/lib/Sema/SemaLookup.cpp | 3 ++- clang/test/SemaCXX/overloaded-operator.cpp | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 85596ed52e9d..4f88edcb31f5 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1031,7 +1031,8 @@ struct FindLocalExternScope { FindLocalExternScope(LookupResult &R) : R(R), OldFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_LocalExtern) { - R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary); + R.setFindLocalExtern(R.getIdentifierNamespace() & + (Decl::IDNS_Ordinary | Decl::IDNS_NonMemberOperator)); } void restore() { R.setFindLocalExtern(OldFindLocalExtern); diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp index 369e9eb802a5..52d0bff3884c 100644 --- a/clang/test/SemaCXX/overloaded-operator.cpp +++ b/clang/test/SemaCXX/overloaded-operator.cpp @@ -531,3 +531,22 @@ namespace NoADLForMemberOnlyOperators { b3 / 0; // expected-note {{in instantiation of}} expected-error {{invalid operands to}} } } + + +namespace PR27027 { + template void operator+(T, T) = delete; // expected-note 4 {{candidate}} + template void operator+(T) = delete; // expected-note 4 {{candidate}} + + struct A {} a_global; + void f() { + A a; + +a; // expected-error {{overload resolution selected deleted operator '+'}} + a + a; // expected-error {{overload resolution selected deleted operator '+'}} + bool operator+(A); + extern bool operator+(A, A); + +a; // OK + a + a; + } + 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 '+'}} +}