r206435 - PR19452: Implement more of [over.match.oper]p3's restrictions on which non-member overloaded operators can be found when no operand is of class type. We used to fail to implement this rule if there was an operand of dependent type.

Richard Smith richard-llvm at metafoo.co.uk
Wed Apr 16 18:12:17 PDT 2014


Author: rsmith
Date: Wed Apr 16 20:12:17 2014
New Revision: 206435

URL: http://llvm.org/viewvc/llvm-project?rev=206435&view=rev
Log:
PR19452: Implement more of [over.match.oper]p3's restrictions on which non-member overloaded operators can be found when no operand is of class type. We used to fail to implement this rule if there was an operand of dependent type.

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

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=206435&r1=206434&r2=206435&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Apr 16 20:12:17 2014
@@ -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; }

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=206435&r1=206434&r2=206435&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 16 20:12:17 2014
@@ -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());

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=206435&r1=206434&r2=206435&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Apr 16 20:12:17 2014
@@ -2390,20 +2390,24 @@ void Sema::LookupOverloadedOperatorName(
   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());
   }
 }
 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=206435&r1=206434&r2=206435&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Apr 16 20:12:17 2014
@@ -9760,9 +9760,10 @@ TreeTransform<Derived>::RebuildCXXOperat
   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,

Modified: cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp?rev=206435&r1=206434&r2=206435&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp (original)
+++ cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp Wed Apr 16 20:12:17 2014
@@ -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;
+
+}





More information about the cfe-commits mailing list