diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-04 16:44:47 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-04 16:44:47 +0000 |
commit | f680a0fe2dcab32b59fe6fdf71145b5313c40950 (patch) | |
tree | 5edd7174472b922d5c58a071f997c9cb33823b0c | |
parent | 09413dca1be4b3e78597bdf706de39ec70cf0ee4 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63735 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 19 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 73 | ||||
-rw-r--r-- | test/SemaCXX/overloaded-operator.cpp | 3 |
5 files changed, 50 insertions, 65 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 6b8d852db3..724a57ed42 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -488,9 +488,11 @@ public: 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 @@ public: 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 @@ public: /// 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 @@ public: 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); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c1e4c0ecdd..d408defbff 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1190,7 +1190,8 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, // 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 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, // 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 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, // 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 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, // 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; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 09431492b9..4cdd4abab3 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -313,6 +313,7 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, 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 @@ Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() { Decl ** I = reinterpret_cast<Decl**>(Current); ++I; Current = reinterpret_cast<uintptr_t>(I); + break; } case OverloadedDeclFromIdResolver: { @@ -587,7 +589,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, 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 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, 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"); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 01b9829c66..44cd5b5e53 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2258,9 +2258,11 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, /// 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 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, // 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 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, } } -/// 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 diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 6c7a8d7621..7a5e06e5fa 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -206,7 +206,6 @@ namespace M { namespace M { void test_X(N::X x) { - // FIXME: this should work! See comment in Sema::AddOperatorCandidates. - // (void)(x + x); + (void)(x + x); } } |