diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-13 18:40:31 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-13 18:40:31 +0000 |
commit | 063daf6e196c51f162e0485478355d8e280eef5c (patch) | |
tree | 96bfffedbfbbf33d16167cde703b691cf2e2a7dd /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 13135a6171e5eb1dd0b10f49305bb757b8f8b20c (diff) |
Refactor the way we handle operator overloading and template
instantiation for binary operators. This change moves most of the
operator-overloading code from the parser action ActOnBinOp to a new,
parser-independent semantic checking routine CreateOverloadedBinOp.
Of particular importance is the fact that CreateOverloadedBinOp does
*not* perform any name lookup based on the current parsing context (it
doesn't take a Scope*), since it has to be usable during template
instantiation, when there is no scope information. Rather, it takes a
pre-computed set of functions that are visible from the context or via
argument-dependent lookup, and adds to that set any member operators
and built-in operator candidates. The set of functions is computed in
the parser action ActOnBinOp based on the current context (both
operator name lookup and argument-dependent lookup). Within a
template, the set computed by ActOnBinOp is saved within the
type-dependent AST node and is augmented with the results of
argument-dependent name lookup at instantiation time (see
TemplateExprInstantiator::VisitCXXOperatorCallExpr).
Sadly, we can't fully test this yet. I'll follow up with template
instantiation for sizeof so that the real fun can begin.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66923 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 3f7756ef3e..aea03cc580 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -648,9 +648,11 @@ TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) { Sema::OwningExprResult TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - // FIXME: HACK HACK HACK. This is so utterly and completely wrong - // that I don't want to explain it here. I'll just fix it tomorrow - // instead. + // FIXME: Only handles binary operators at the moment. + + // FIXME: Can we optimize this further if neither the left- nor the + // right-hand sides are type-dependent? It depends on whether we + // need to perform ADL again Sema::OwningExprResult LHS = Visit(E->getArg(0)); if (LHS.isInvalid()) return SemaRef.ExprError(); @@ -659,11 +661,56 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { if (RHS.isInvalid()) return SemaRef.ExprError(); - Sema::OwningExprResult Result - = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), - BinaryOperator::Add, - (Expr *)LHS.get(), - (Expr *)RHS.get()); + Expr *lhs = (Expr *)LHS.get(), *rhs = (Expr *)RHS.get(); + Expr *Args[2] = { lhs, rhs }; + + if (!E->isTypeDependent()) { + // Since our original expression was not type-dependent, we do not + // perform lookup again at instantiation time (C++ [temp.dep]p1). + // Instead, we just build the new overloaded operator call + // expression. + LHS.release(); + RHS.release(); + return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr( + SemaRef.Context, + E->getOperator(), + E->getCallee(), + Args, 2, E->getType(), + E->getOperatorLoc())); + } + + BinaryOperator::Opcode Opc = + BinaryOperator::getOverloadedOpcode(E->getOperator()); + Sema::OwningExprResult Result(SemaRef); + if (!lhs->getType()->isOverloadableType() && + !rhs->getType()->isOverloadableType()) { + // Neither LHS nor RHS is an overloadable type, so try create a + // built-in binary operation. + Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc, + lhs, rhs); + } else { + // Compute the set of functions that were found at template + // definition time. + Sema::FunctionSet Functions; + DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee()); + OverloadedFunctionDecl *Overloads + = cast<OverloadedFunctionDecl>(DRE->getDecl()); + for (OverloadedFunctionDecl::function_iterator + F = Overloads->function_begin(), + FEnd = Overloads->function_end(); + F != FEnd; ++F) + Functions.insert(*F); + + // Add any functions found via argument-dependent lookup. + DeclarationName OpName + = SemaRef.Context.DeclarationNames.getCXXOperatorName(E->getOperator()); + SemaRef.ArgumentDependentLookup(OpName, Args, 2, Functions); + + // Create the overloaded operator. + Result = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc, + Functions, lhs, rhs); + } + if (Result.isInvalid()) return SemaRef.ExprError(); |