From d3ff325a8d95a58783a3ea2675e2d59a393bd637 Mon Sep 17 00:00:00 2001 From: Richard Smith <richard-llvm@metafoo.co.uk> Date: Wed, 12 Jun 2013 22:56:54 +0000 Subject: [PATCH] Don't suggest putting 'operator new' or 'operator delete' in a namespace to fix a two-phase lookup issue. That's not permitted. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183874 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 45 ++++++++++++++++++--------- test/SemaTemplate/dependent-names.cpp | 12 +++++++ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9e3ca9dd406..b9983ef0559 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -9766,6 +9766,19 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, CandidateSet, PartialOverloading); } +/// Determine whether a declaration with the specified name could be moved into +/// a different namespace. +static bool canBeDeclaredInNamespace(const DeclarationName &Name) { + switch (Name.getCXXOverloadedOperator()) { + case OO_New: case OO_Array_New: + case OO_Delete: case OO_Array_Delete: + return false; + + default: + return true; + } +} + /// Attempt to recover from an ill-formed use of a non-dependent name in a /// template, where the non-dependent name was declared after the template /// was defined. This is common in code written for a compilers which do not @@ -9818,22 +9831,24 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, AssociatedNamespaces, AssociatedClasses); Sema::AssociatedNamespaceSet SuggestedNamespaces; - DeclContext *Std = SemaRef.getStdNamespace(); - for (Sema::AssociatedNamespaceSet::iterator - it = AssociatedNamespaces.begin(), - end = AssociatedNamespaces.end(); it != end; ++it) { - // Never suggest declaring a function within namespace 'std'. - if (Std && Std->Encloses(*it)) - continue; - - // Never suggest declaring a function within a namespace with a reserved - // name, like __gnu_cxx. - NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it); - if (NS && - NS->getQualifiedNameAsString().find("__") != std::string::npos) - continue; + if (canBeDeclaredInNamespace(R.getLookupName())) { + DeclContext *Std = SemaRef.getStdNamespace(); + for (Sema::AssociatedNamespaceSet::iterator + it = AssociatedNamespaces.begin(), + end = AssociatedNamespaces.end(); it != end; ++it) { + // Never suggest declaring a function within namespace 'std'. + if (Std && Std->Encloses(*it)) + continue; - SuggestedNamespaces.insert(*it); + // Never suggest declaring a function within a namespace with a + // reserved name, like __gnu_cxx. + NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it); + if (NS && + NS->getQualifiedNameAsString().find("__") != std::string::npos) + continue; + + SuggestedNamespaces.insert(*it); + } } SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup) diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp index 769584d93ca..4d4aafa918c 100644 --- a/test/SemaTemplate/dependent-names.cpp +++ b/test/SemaTemplate/dependent-names.cpp @@ -387,3 +387,15 @@ namespace PR14695_A { void PR14695_f(PR14695_X); } // expected-note {{'PR14695_f template<typename T> void PR14695_g(T t) { PR14695_f(t); } // expected-error {{call to function 'PR14695_f' that is neither visible in the template definition nor found by argument-dependent lookup}} using namespace PR14695_A; template void PR14695_g(PR14695_X); // expected-note{{requested here}} + +namespace OperatorNew { + template<typename T> void f(T t) { + operator new(100, t); // expected-error{{call to function 'operator new' that is neither visible in the template definition nor found by argument-dependent lookup}} + // FIXME: This should give the same error. + new (t) int; + } + struct X {}; +}; +using size_t = decltype(sizeof(0)); +void *operator new(size_t, OperatorNew::X); // expected-note-re {{should be declared prior to the call site$}} +template void OperatorNew::f(OperatorNew::X); // expected-note {{instantiation of}} -- GitLab