[cfe-commits] r63735 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/overloaded-operator.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 4 08:44:47 PST 2009


Author: dgregor
Date: Wed Feb  4 10:44:47 2009
New Revision: 63735

URL: http://llvm.org/viewvc/llvm-project?rev=63735&view=rev
Log:
Bring operator name lookup (as required for C++ operator overloading)
into the general name-lookup fold. This cleans up some ugly,
not-quite-working code in the handling of operator overloading.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/overloaded-operator.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63735&r1=63734&r2=63735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb  4 10:44:47 2009
@@ -488,9 +488,11 @@
                              const FunctionTypeProto *Proto,
                              Expr *Object, Expr **Args, unsigned NumArgs,
                              OverloadCandidateSet& CandidateSet);
-  void AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+  bool AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+                             SourceLocation OpLoc,
                              Expr **Args, unsigned NumArgs,
-                             OverloadCandidateSet& CandidateSet);
+                             OverloadCandidateSet& CandidateSet,
+                             SourceRange OpRange = SourceRange());
   void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, 
                            Expr **Args, unsigned NumArgs,
                            OverloadCandidateSet& CandidateSet,
@@ -502,10 +504,6 @@
   void AddArgumentDependentLookupCandidates(DeclarationName Name,
                                             Expr **Args, unsigned NumArgs,
                                             OverloadCandidateSet& CandidateSet);
-  void AddOverloadCandidates(const OverloadedFunctionDecl *Ovl, 
-                             Expr **Args, unsigned NumArgs,
-                             OverloadCandidateSet& CandidateSet,
-                             bool SuppressUserConversions = false);
   bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
                                  const OverloadCandidate& Cand2);
   OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
@@ -585,6 +583,11 @@
     /// Member name lookup, which finds the names of
     /// class/struct/union members.
     LookupMemberName,
+    // Look up of an operator name (e.g., operator+) for use with
+    // operator overloading. This lookup is similar to ordinary name
+    // lookup, but will ignore any declarations that are class
+    // members.
+    LookupOperatorName,
     /// Look up of a name that precedes the '::' scope resolution
     /// operator in C++. This lookup completely ignores operator,
     /// function, and enumerator names (C++ [basic.lookup.qual]p1).
@@ -839,6 +842,10 @@
     case Sema::LookupMemberName:
       return D->isInIdentifierNamespace(IDNS);
       
+    case Sema::LookupOperatorName:
+      return D->isInIdentifierNamespace(IDNS) && 
+             !D->getDeclContext()->isRecord();
+
     case Sema::LookupNestedNameSpecifierName:
       return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
       

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=63735&r1=63734&r2=63735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb  4 10:44:47 2009
@@ -1190,7 +1190,8 @@
 
     // Build the candidate set for overloading
     OverloadCandidateSet CandidateSet;
-    AddOperatorCandidates(OverOp, S, Args, 2, CandidateSet);
+    if (AddOperatorCandidates(OverOp, S, OpLoc, Args, 2, CandidateSet))
+      return ExprError();
 
     // Perform overload resolution.
     OverloadCandidateSet::iterator Best;
@@ -1281,7 +1282,9 @@
     // to the candidate set.
     OverloadCandidateSet CandidateSet;
     Expr *Args[2] = { LHSExp, RHSExp };
-    AddOperatorCandidates(OO_Subscript, S, Args, 2, CandidateSet);
+    if (AddOperatorCandidates(OO_Subscript, S, LLoc, Args, 2, CandidateSet,
+                              SourceRange(LLoc, RLoc)))
+      return ExprError();
 
     // Perform overload resolution.
     OverloadCandidateSet::iterator Best;
@@ -3738,7 +3741,8 @@
     // to the candidate set.
     OverloadCandidateSet CandidateSet;
     Expr *Args[2] = { lhs, rhs };
-    AddOperatorCandidates(OverOp, S, Args, 2, CandidateSet);
+    if (AddOperatorCandidates(OverOp, S, TokLoc, Args, 2, CandidateSet))
+      return ExprError();
 
     // Perform overload resolution.
     OverloadCandidateSet::iterator Best;
@@ -3840,8 +3844,9 @@
     // Add the appropriate overloaded operators (C++ [over.match.oper]) 
     // to the candidate set.
     OverloadCandidateSet CandidateSet;
-    if (OverOp != OO_None)
-      AddOperatorCandidates(OverOp, S, &Input, 1, CandidateSet);    
+    if (OverOp != OO_None &&
+        AddOperatorCandidates(OverOp, S, OpLoc, &Input, 1, CandidateSet))
+      return ExprError();
 
     // Perform overload resolution.
     OverloadCandidateSet::iterator Best;

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=63735&r1=63734&r2=63735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Feb  4 10:44:47 2009
@@ -313,6 +313,7 @@
   unsigned IDNS = 0;
   switch (NameKind) {
   case Sema::LookupOrdinaryName:
+  case Sema::LookupOperatorName:
     IDNS = Decl::IDNS_Ordinary;
     if (CPlusPlus)
       IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
@@ -531,6 +532,7 @@
     Decl ** I = reinterpret_cast<Decl**>(Current);
     ++I;
     Current = reinterpret_cast<uintptr_t>(I);
+    break;
   }
 
   case OverloadedDeclFromIdResolver: {
@@ -587,7 +589,7 @@
                     LookupNameKind NameKind, bool RedeclarationOnly) {
   assert(getLangOptions().CPlusPlus &&
          "Can perform only C++ lookup");
-unsigned IDNS 
+  unsigned IDNS 
       = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
   Scope *Initial = S;
   IdentifierResolver::iterator 
@@ -841,6 +843,7 @@
       IDNS = Decl::IDNS_Member;
       break;
 
+    case Sema::LookupOperatorName:
     case Sema::LookupNestedNameSpecifierName:
     case Sema::LookupNamespaceName:
       assert(false && "C does not perform these kinds of name lookup");

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=63735&r1=63734&r2=63735&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb  4 10:44:47 2009
@@ -2258,9 +2258,11 @@
 /// name lookup of the operator), Args/NumArgs provides the operator
 /// arguments, and CandidateSet will store the added overload
 /// candidates. (C++ [over.match.oper]).
-void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+bool Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+                                 SourceLocation OpLoc,
                                  Expr **Args, unsigned NumArgs,
-                                 OverloadCandidateSet& CandidateSet) {
+                                 OverloadCandidateSet& CandidateSet,
+                                 SourceRange OpRange) {
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
 
   // C++ [over.match.oper]p3:
@@ -2300,45 +2302,29 @@
   //        type, or (if there is a right operand) a second parameter
   //        of type T2 or “reference to (possibly cv-qualified) T2”,
   //        when T2 is an enumeration type, are candidate functions.
-  {
-    // FIXME: Don't use the IdentifierResolver here! We need to
-    // perform proper, unqualified lookup starting with the first
-    // enclosing non-class scope.
-    IdentifierResolver::iterator I = IdResolver.begin(OpName),
-                              IEnd = IdResolver.end();
-    for (; I != IEnd; ++I) {
-      // We don't need to check the identifier namespace, because
-      // operator names can only be ordinary identifiers.
-
-      // Ignore member functions. 
-      if ((*I)->getDeclContext()->isRecord())
-        continue;
-
-      // We found something with this name. We're done.
-      break;
-    }
-
-    if (I != IEnd) {
-      Decl *FirstDecl = *I;
-      for (; I != IEnd; ++I) {
-        if (FirstDecl->getDeclContext() != (*I)->getDeclContext())
-          break;
-
-        if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
-          if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
-            AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
-                                 /*SuppressUserConversions=*/false);
-      }
+  LookupResult Operators = LookupName(S, OpName, LookupOperatorName);
+  
+  if (Operators.isAmbiguous())
+    return DiagnoseAmbiguousLookup(Operators, OpName, OpLoc, OpRange);
+  else if (Operators) {
+    for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
+         Op != OpEnd; ++Op) {
+      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op))
+        if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
+          AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
+                               /*SuppressUserConversions=*/false);
     }
-
-    // Since the set of non-member candidates corresponds to
-    // *unqualified* lookup of the operator name, we also perform
-    // argument-dependent lookup.
-    AddArgumentDependentLookupCandidates(OpName, Args, NumArgs, CandidateSet);
   }
 
+  // Since the set of non-member candidates corresponds to
+  // *unqualified* lookup of the operator name, we also perform
+  // argument-dependent lookup (C++ [basic.lookup.argdep]).
+  AddArgumentDependentLookupCandidates(OpName, Args, NumArgs, CandidateSet);
+
   // Add builtin overload candidates (C++ [over.built]).
   AddBuiltinOperatorCandidates(Op, Args, NumArgs, CandidateSet);
+
+  return false;
 }
 
 /// AddBuiltinCandidate - Add a candidate for a built-in
@@ -3230,21 +3216,6 @@
   }
 }
 
-/// AddOverloadCandidates - Add all of the function overloads in Ovl
-/// to the candidate set.
-void 
-Sema::AddOverloadCandidates(const OverloadedFunctionDecl *Ovl, 
-                            Expr **Args, unsigned NumArgs,
-                            OverloadCandidateSet& CandidateSet,
-                            bool SuppressUserConversions)
-{
-  for (OverloadedFunctionDecl::function_const_iterator Func 
-         = Ovl->function_begin();
-       Func != Ovl->function_end(); ++Func)
-    AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet,
-                         SuppressUserConversions);
-}
-
 /// isBetterOverloadCandidate - Determines whether the first overload
 /// candidate is a better candidate than the second (C++ 13.3.3p1).
 bool 

Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=63735&r1=63734&r2=63735&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Wed Feb  4 10:44:47 2009
@@ -206,7 +206,6 @@
 
 namespace M {
   void test_X(N::X x) {
-    // FIXME: this should work! See comment in Sema::AddOperatorCandidates.
-    //    (void)(x + x);
+    (void)(x + x);
   }
 }





More information about the cfe-commits mailing list