]> granicus.if.org Git - clang/commitdiff
PR19452: Implement more of [over.match.oper]p3's restrictions on which non-member...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 17 Apr 2014 01:12:17 +0000 (01:12 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 17 Apr 2014 01:12:17 +0000 (01:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206435 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprCXX.h
include/clang/Sema/Sema.h
lib/Sema/SemaLookup.cpp
lib/Sema/TreeTransform.h
test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp

index 6ed55ca02d23f3e2d58a97455d8bb16392d77fdf..aff0021a77f4e646116d07c4e0423cb20ce22f8a 100644 (file)
@@ -2431,6 +2431,9 @@ public:
   decls_iterator decls_end() const {
     return UnresolvedSetIterator(Results + NumResults);
   }
+  llvm::iterator_range<decls_iterator> decls() const {
+    return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end());
+  }
 
   /// \brief Gets the number of declarations in the unresolved set.
   unsigned getNumDecls() const { return NumResults; }
index b3e3e43ffe67ddd2573db02e47a18b923ef5c197..2b48155abc9b7622e245bddb597c6d06da014337 100644 (file)
@@ -2564,6 +2564,9 @@ public:
   void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
                                     QualType T1, QualType T2,
                                     UnresolvedSetImpl &Functions);
+  void addOverloadedOperatorToUnresolvedSet(UnresolvedSetImpl &Functions,
+                                            DeclAccessPair Operator,
+                                            QualType T1, QualType T2);
 
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
                                  SourceLocation GnuLabelLoc = SourceLocation());
index 172a07906da014fdf4d38c6b32ad72cefdcc29d4..ba9bcd656117dcc65fcc885d54f7b6972b75bb44 100644 (file)
@@ -2390,20 +2390,24 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
   if (Operators.empty())
     return;
 
-  for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
-       Op != OpEnd; ++Op) {
-    NamedDecl *Found = (*Op)->getUnderlyingDecl();
-    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) {
-      if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
-        Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD
-    } else if (FunctionTemplateDecl *FunTmpl
-                 = dyn_cast<FunctionTemplateDecl>(Found)) {
-      // FIXME: friend operators?
-      // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
-      // later?
-      if (!FunTmpl->getDeclContext()->isRecord())
-        Functions.addDecl(*Op, Op.getAccess());
-    }
+  for (auto I = Operators.begin(), E = Operators.end(); I != E; ++I)
+    addOverloadedOperatorToUnresolvedSet(Functions, I.getPair(), T1, T2);
+}
+
+void Sema::addOverloadedOperatorToUnresolvedSet(UnresolvedSetImpl &Functions,
+                                                DeclAccessPair Op,
+                                                QualType T1, QualType T2) {
+  NamedDecl *Found = Op->getUnderlyingDecl();
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) {
+    if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
+      Functions.addDecl(Op, Op.getAccess()); // FIXME: canonical FD
+  } else if (FunctionTemplateDecl *FunTmpl
+               = dyn_cast<FunctionTemplateDecl>(Found)) {
+    // FIXME: friend operators?
+    // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
+    // later?
+    if (!FunTmpl->getDeclContext()->isRecord())
+      Functions.addDecl(Op, Op.getAccess());
   }
 }
 
index 27cf43fd74258aa27ddcedfdf339d451d4d06494..4094f5a7166f059a047dd1c4d0d0fdfa4bef500e 100644 (file)
@@ -9760,9 +9760,10 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
   if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
     assert(ULE->requiresADL());
 
-    // FIXME: Do we have to check
-    // IsAcceptableNonMemberOperatorCandidate for each of these?
-    Functions.append(ULE->decls_begin(), ULE->decls_end());
+    for (auto I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I)
+      SemaRef.addOverloadedOperatorToUnresolvedSet(
+          Functions, I.getPair(), First->getType(),
+          Second ? Second->getType() : QualType());
   } else {
     // If we've resolved this to a particular non-member function, just call
     // that function. If we resolved it to a member function,
index 35f8808fff88cb9b6cac6469c54e0928a314d644..b3cc3bf41c40d5b432e1f1776ca87d4376159874 100644 (file)
@@ -1,5 +1,29 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// expected-no-diagnostics
+
+namespace bullet2 {
+
+// For non-member candidates, if no operand has a class type, only those
+// non-member functions that have a matching enumeration parameter are
+// candidates.
+
+struct B { template<typename T> B(T); };
+int operator~(B); // expected-note {{declared prior to the call site}}
+template<typename T> int operator%(B, T);
+enum class E { e };
+
+// FIXME: This is the wrong diagnostic.
+template<typename T> int f(T t) { return ~t; } // expected-error {{call to}}
+template<typename T, typename U> int f(T t, U u) { return t % u; }
+
+int b1 = ~E::e; // expected-error {{invalid argument type}}
+int b2 = f(E::e); // expected-note {{in instantiation of}}
+int b3 = f(0, E::e);
+// FIXME: This should be rejected.
+int b4 = f(E::e, 0);
+
+}
+
+namespace bullet3 {
 
 // This is specifically testing the bullet:
 // "do not have the same parameter-type-list as any non-template
@@ -26,4 +50,6 @@ extern bool test2;
 extern decltype(a <= a) test2;
 
 extern A test3;
-extern decltype(a <= b) test3;
\ No newline at end of file
+extern decltype(a <= b) test3;
+
+}