[cfe-commits] r67660 - in /cfe/trunk/lib/Sema: CMakeLists.txt SemaTemplateInstantiate.cpp SemaTemplateInstantiateExpr.cpp
Douglas Gregor
dgregor at apple.com
Tue Mar 24 17:27:30 PDT 2009
Author: dgregor
Date: Tue Mar 24 19:27:28 2009
New Revision: 67660
URL: http://llvm.org/viewvc/llvm-project?rev=67660&view=rev
Log:
Move template instantiation for expressions into a separate file
Added:
cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
Modified:
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=67660&r1=67659&r2=67660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Mar 24 19:27:28 2009
@@ -23,6 +23,7 @@
SemaTemplate.cpp
SemaTemplateInstantiate.cpp
SemaTemplateInstantiateDecl.cpp
+ SemaTemplateInstantiateExpr.cpp
SemaType.cpp
)
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=67660&r1=67659&r2=67660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 24 19:27:28 2009
@@ -13,11 +13,8 @@
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/Parse/DeclSpec.h"
-#include "clang/Lex/Preprocessor.h" // for the identifier table
#include "clang/Basic/LangOptions.h"
#include "llvm/Support/Compiler.h"
@@ -587,404 +584,6 @@
return Instantiator(T);
}
-//===----------------------------------------------------------------------===/
-// Template Instantiation for Expressions
-//===----------------------------------------------------------------------===/
-namespace {
- class VISIBILITY_HIDDEN TemplateExprInstantiator
- : public StmtVisitor<TemplateExprInstantiator, Sema::OwningExprResult> {
- Sema &SemaRef;
- const TemplateArgument *TemplateArgs;
- unsigned NumTemplateArgs;
-
- public:
- typedef Sema::OwningExprResult OwningExprResult;
-
- TemplateExprInstantiator(Sema &SemaRef,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs)
- : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
- NumTemplateArgs(NumTemplateArgs) { }
-
- // FIXME: Once we get closer to completion, replace these
- // manually-written declarations with automatically-generated ones
- // from clang/AST/StmtNodes.def.
- OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
- OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
- OwningExprResult VisitParenExpr(ParenExpr *E);
- OwningExprResult VisitUnaryOperator(UnaryOperator *E);
- OwningExprResult VisitBinaryOperator(BinaryOperator *E);
- OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
- OwningExprResult VisitConditionalOperator(ConditionalOperator *E);
- OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
- OwningExprResult VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E);
- OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
- OwningExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
-
- // Base case. I'm supposed to ignore this.
- Sema::OwningExprResult VisitStmt(Stmt *S) {
- S->dump();
- assert(false && "Cannot instantiate this kind of expression");
- return SemaRef.ExprError();
- }
- };
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitIntegerLiteral(IntegerLiteral *E) {
- return SemaRef.Clone(E);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
- Decl *D = E->getDecl();
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- assert(NTTP->getDepth() == 0 && "No nested templates yet");
- const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
- QualType T = Arg.getIntegralType();
- if (T->isCharType() || T->isWideCharType())
- return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
- Arg.getAsIntegral()->getZExtValue(),
- T->isWideCharType(),
- T,
- E->getSourceRange().getBegin()));
- else if (T->isBooleanType())
- return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
- Arg.getAsIntegral()->getBoolValue(),
- T,
- E->getSourceRange().getBegin()));
-
- return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
- *Arg.getAsIntegral(),
- T,
- E->getSourceRange().getBegin()));
- } else
- assert(false && "Can't handle arbitrary declaration references");
-
- return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) {
- Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
- if (SubExpr.isInvalid())
- return SemaRef.ExprError();
-
- return SemaRef.Owned(new (SemaRef.Context) ParenExpr(
- E->getLParen(), E->getRParen(),
- (Expr *)SubExpr.release()));
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitUnaryOperator(UnaryOperator *E) {
- Sema::OwningExprResult Arg = Visit(E->getSubExpr());
- if (Arg.isInvalid())
- return SemaRef.ExprError();
-
- return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(),
- E->getOpcode(),
- move(Arg));
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
- Sema::OwningExprResult LHS = Visit(E->getLHS());
- if (LHS.isInvalid())
- return SemaRef.ExprError();
-
- Sema::OwningExprResult RHS = Visit(E->getRHS());
- if (RHS.isInvalid())
- return SemaRef.ExprError();
-
- Sema::OwningExprResult Result
- = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(),
- E->getOpcode(),
- (Expr *)LHS.get(),
- (Expr *)RHS.get());
- if (Result.isInvalid())
- return SemaRef.ExprError();
-
- LHS.release();
- RHS.release();
- return move(Result);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
- Sema::OwningExprResult First = Visit(E->getArg(0));
- if (First.isInvalid())
- return SemaRef.ExprError();
-
- Expr *Args[2] = { (Expr *)First.get(), 0 };
-
- Sema::OwningExprResult Second(SemaRef);
- if (E->getNumArgs() == 2) {
- Second = Visit(E->getArg(1));
-
- if (Second.isInvalid())
- return SemaRef.ExprError();
-
- Args[1] = (Expr *)Second.get();
- }
-
- 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.
- First.release();
- Second.release();
- // FIXME: Don't reuse the callee here. We need to instantiate it.
- return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr(
- SemaRef.Context,
- E->getOperator(),
- E->getCallee(),
- Args, E->getNumArgs(),
- E->getType(),
- E->getOperatorLoc()));
- }
-
- bool isPostIncDec = E->getNumArgs() == 2 &&
- (E->getOperator() == OO_PlusPlus || E->getOperator() == OO_MinusMinus);
- if (E->getNumArgs() == 1 || isPostIncDec) {
- if (!Args[0]->getType()->isOverloadableType()) {
- // The argument is not of overloadable type, so try to create a
- // built-in unary operation.
- UnaryOperator::Opcode Opc
- = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
-
- return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(), Opc,
- move(First));
- }
-
- // Fall through to perform overload resolution
- } else {
- assert(E->getNumArgs() == 2 && "Expected binary operation");
-
- Sema::OwningExprResult Result(SemaRef);
- if (!Args[0]->getType()->isOverloadableType() &&
- !Args[1]->getType()->isOverloadableType()) {
- // Neither of the arguments is an overloadable type, so try to
- // create a built-in binary operation.
- BinaryOperator::Opcode Opc =
- BinaryOperator::getOverloadedOpcode(E->getOperator());
- Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc,
- Args[0], Args[1]);
- if (Result.isInvalid())
- return SemaRef.ExprError();
-
- First.release();
- Second.release();
- return move(Result);
- }
-
- // Fall through to perform overload resolution.
- }
-
- // 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());
-
- // FIXME: Do we have to check
- // IsAcceptableNonMemberOperatorCandidate for each of these?
- 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, E->getNumArgs(), Functions);
-
- // Create the overloaded operator invocation.
- if (E->getNumArgs() == 1 || isPostIncDec) {
- UnaryOperator::Opcode Opc
- = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
- return SemaRef.CreateOverloadedUnaryOp(E->getOperatorLoc(), Opc,
- Functions, move(First));
- }
-
- // FIXME: This would be far less ugly if CreateOverloadedBinOp took
- // in ExprArg arguments!
- BinaryOperator::Opcode Opc =
- BinaryOperator::getOverloadedOpcode(E->getOperator());
- OwningExprResult Result
- = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc,
- Functions, Args[0], Args[1]);
-
- if (Result.isInvalid())
- return SemaRef.ExprError();
-
- First.release();
- Second.release();
- return move(Result);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) {
- Sema::OwningExprResult Cond = Visit(E->getCond());
- if (Cond.isInvalid())
- return SemaRef.ExprError();
-
- // FIXME: use getLHS() and cope with NULLness
- Sema::OwningExprResult True = Visit(E->getTrueExpr());
- if (True.isInvalid())
- return SemaRef.ExprError();
-
- Sema::OwningExprResult False = Visit(E->getFalseExpr());
- if (False.isInvalid())
- return SemaRef.ExprError();
-
- 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 conditional operator call expression.
- return SemaRef.Owned(new (SemaRef.Context) ConditionalOperator(
- Cond.takeAs<Expr>(),
- True.takeAs<Expr>(),
- False.takeAs<Expr>(),
- E->getType()));
- }
-
-
- return SemaRef.ActOnConditionalOp(/*FIXME*/E->getCond()->getLocEnd(),
- /*FIXME*/E->getFalseExpr()->getLocStart(),
- move(Cond), move(True), move(False));
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
- bool isSizeOf = E->isSizeOf();
-
- if (E->isArgumentType()) {
- QualType T = E->getArgumentType();
- if (T->isDependentType()) {
- T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
- /*FIXME*/E->getOperatorLoc(),
- &SemaRef.PP.getIdentifierTable().get("sizeof"));
- if (T.isNull())
- return SemaRef.ExprError();
- }
-
- return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
- E->getSourceRange());
- }
-
- Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
- if (Arg.isInvalid())
- return SemaRef.ExprError();
-
- Sema::OwningExprResult Result
- = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
- isSizeOf, E->getSourceRange());
- if (Result.isInvalid())
- return SemaRef.ExprError();
-
- Arg.release();
- return move(Result);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) {
- CXXScopeSpec SS = SemaRef.InstantiateScopeSpecifier(E->begin(), E->size(),
- E->getQualifierRange(),
- TemplateArgs,
- NumTemplateArgs);
- if (SS.isInvalid() || SS.isEmpty())
- return SemaRef.ExprError();
-
- // FIXME: We're passing in a NULL scope, because
- // ActOnDeclarationNameExpr doesn't actually use the scope when we
- // give it a non-empty scope specifier. Investigate whether it would
- // be better to refactor ActOnDeclarationNameExpr.
- return SemaRef.ActOnDeclarationNameExpr(/*Scope=*/0, E->getLocation(),
- E->getDeclName(),
- /*HasTrailingLParen=*/false,
- &SS,
- /*FIXME:isAddressOfOperand=*/false);
-}
-
-Sema::OwningExprResult
-TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
- CXXTemporaryObjectExpr *E) {
- QualType T = E->getType();
- if (T->isDependentType()) {
- T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
- E->getTypeBeginLoc(), DeclarationName());
- if (T.isNull())
- return SemaRef.ExprError();
- }
-
- llvm::SmallVector<Expr *, 16> Args;
- Args.reserve(E->getNumArgs());
- bool Invalid = false;
- for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
- ArgEnd = E->arg_end();
- Arg != ArgEnd; ++Arg) {
- OwningExprResult InstantiatedArg = Visit(*Arg);
- if (InstantiatedArg.isInvalid()) {
- Invalid = true;
- break;
- }
-
- Args.push_back((Expr *)InstantiatedArg.release());
- }
-
- if (!Invalid) {
- SourceLocation CommaLoc;
- // FIXME: HACK!
- if (Args.size() > 1)
- CommaLoc
- = SemaRef.PP.getLocForEndOfToken(Args[0]->getSourceRange().getEnd());
- Sema::OwningExprResult Result(
- SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
- /*, FIXME*/),
- T.getAsOpaquePtr(),
- /*FIXME*/E->getTypeBeginLoc(),
- Sema::MultiExprArg(SemaRef,
- (void**)&Args[0],
- Args.size()),
- /*HACK*/&CommaLoc,
- E->getSourceRange().getEnd()));
- // At this point, Args no longer owns the arguments, no matter what.
- return move(Result);
- }
-
- // Clean up the instantiated arguments.
- // FIXME: Would rather do this with RAII.
- for (unsigned Idx = 0; Idx < Args.size(); ++Idx)
- SemaRef.DeleteExpr(Args[Idx]);
-
- return SemaRef.ExprError();
-}
-
-Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr(
- ImplicitCastExpr *E) {
- assert(!E->isTypeDependent() && "Implicit casts must have known types");
-
- Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
- if (SubExpr.isInvalid())
- return SemaRef.ExprError();
-
- ImplicitCastExpr *ICE =
- new (SemaRef.Context) ImplicitCastExpr(E->getType(),
- (Expr *)SubExpr.release(),
- E->isLvalueCast());
- return SemaRef.Owned(ICE);
-}
-
-Sema::OwningExprResult
-Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);
- return Instantiator.Visit(E);
-}
-
/// \brief Instantiate the base class specifiers of the given class
/// template specialization.
///
Added: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=67660&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (added)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Tue Mar 24 19:27:28 2009
@@ -0,0 +1,416 @@
+//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements C++ template instantiation for declarations.
+//
+//===----------------------------------------------------------------------===/
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/Preprocessor.h" // for the identifier table
+#include "llvm/Support/Compiler.h"
+using namespace clang;
+
+namespace {
+ class VISIBILITY_HIDDEN TemplateExprInstantiator
+ : public StmtVisitor<TemplateExprInstantiator, Sema::OwningExprResult> {
+ Sema &SemaRef;
+ const TemplateArgument *TemplateArgs;
+ unsigned NumTemplateArgs;
+
+ public:
+ typedef Sema::OwningExprResult OwningExprResult;
+
+ TemplateExprInstantiator(Sema &SemaRef,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs)
+ : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
+ NumTemplateArgs(NumTemplateArgs) { }
+
+ // FIXME: Once we get closer to completion, replace these
+ // manually-written declarations with automatically-generated ones
+ // from clang/AST/StmtNodes.def.
+ OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
+ OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
+ OwningExprResult VisitParenExpr(ParenExpr *E);
+ OwningExprResult VisitUnaryOperator(UnaryOperator *E);
+ OwningExprResult VisitBinaryOperator(BinaryOperator *E);
+ OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ OwningExprResult VisitConditionalOperator(ConditionalOperator *E);
+ OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ OwningExprResult VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E);
+ OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
+ OwningExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
+
+ // Base case. I'm supposed to ignore this.
+ Sema::OwningExprResult VisitStmt(Stmt *S) {
+ S->dump();
+ assert(false && "Cannot instantiate this kind of expression");
+ return SemaRef.ExprError();
+ }
+ };
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitIntegerLiteral(IntegerLiteral *E) {
+ return SemaRef.Clone(E);
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
+ Decl *D = E->getDecl();
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ assert(NTTP->getDepth() == 0 && "No nested templates yet");
+ const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
+ QualType T = Arg.getIntegralType();
+ if (T->isCharType() || T->isWideCharType())
+ return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
+ Arg.getAsIntegral()->getZExtValue(),
+ T->isWideCharType(),
+ T,
+ E->getSourceRange().getBegin()));
+ else if (T->isBooleanType())
+ return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
+ Arg.getAsIntegral()->getBoolValue(),
+ T,
+ E->getSourceRange().getBegin()));
+
+ return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+ *Arg.getAsIntegral(),
+ T,
+ E->getSourceRange().getBegin()));
+ } else
+ assert(false && "Can't handle arbitrary declaration references");
+
+ return SemaRef.ExprError();
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) {
+ Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return SemaRef.ExprError();
+
+ return SemaRef.Owned(new (SemaRef.Context) ParenExpr(
+ E->getLParen(), E->getRParen(),
+ (Expr *)SubExpr.release()));
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitUnaryOperator(UnaryOperator *E) {
+ Sema::OwningExprResult Arg = Visit(E->getSubExpr());
+ if (Arg.isInvalid())
+ return SemaRef.ExprError();
+
+ return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(),
+ E->getOpcode(),
+ move(Arg));
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
+ Sema::OwningExprResult LHS = Visit(E->getLHS());
+ if (LHS.isInvalid())
+ return SemaRef.ExprError();
+
+ Sema::OwningExprResult RHS = Visit(E->getRHS());
+ if (RHS.isInvalid())
+ return SemaRef.ExprError();
+
+ Sema::OwningExprResult Result
+ = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(),
+ E->getOpcode(),
+ (Expr *)LHS.get(),
+ (Expr *)RHS.get());
+ if (Result.isInvalid())
+ return SemaRef.ExprError();
+
+ LHS.release();
+ RHS.release();
+ return move(Result);
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ Sema::OwningExprResult First = Visit(E->getArg(0));
+ if (First.isInvalid())
+ return SemaRef.ExprError();
+
+ Expr *Args[2] = { (Expr *)First.get(), 0 };
+
+ Sema::OwningExprResult Second(SemaRef);
+ if (E->getNumArgs() == 2) {
+ Second = Visit(E->getArg(1));
+
+ if (Second.isInvalid())
+ return SemaRef.ExprError();
+
+ Args[1] = (Expr *)Second.get();
+ }
+
+ 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.
+ First.release();
+ Second.release();
+ // FIXME: Don't reuse the callee here. We need to instantiate it.
+ return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr(
+ SemaRef.Context,
+ E->getOperator(),
+ E->getCallee(),
+ Args, E->getNumArgs(),
+ E->getType(),
+ E->getOperatorLoc()));
+ }
+
+ bool isPostIncDec = E->getNumArgs() == 2 &&
+ (E->getOperator() == OO_PlusPlus || E->getOperator() == OO_MinusMinus);
+ if (E->getNumArgs() == 1 || isPostIncDec) {
+ if (!Args[0]->getType()->isOverloadableType()) {
+ // The argument is not of overloadable type, so try to create a
+ // built-in unary operation.
+ UnaryOperator::Opcode Opc
+ = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
+
+ return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(), Opc,
+ move(First));
+ }
+
+ // Fall through to perform overload resolution
+ } else {
+ assert(E->getNumArgs() == 2 && "Expected binary operation");
+
+ Sema::OwningExprResult Result(SemaRef);
+ if (!Args[0]->getType()->isOverloadableType() &&
+ !Args[1]->getType()->isOverloadableType()) {
+ // Neither of the arguments is an overloadable type, so try to
+ // create a built-in binary operation.
+ BinaryOperator::Opcode Opc =
+ BinaryOperator::getOverloadedOpcode(E->getOperator());
+ Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc,
+ Args[0], Args[1]);
+ if (Result.isInvalid())
+ return SemaRef.ExprError();
+
+ First.release();
+ Second.release();
+ return move(Result);
+ }
+
+ // Fall through to perform overload resolution.
+ }
+
+ // 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());
+
+ // FIXME: Do we have to check
+ // IsAcceptableNonMemberOperatorCandidate for each of these?
+ 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, E->getNumArgs(), Functions);
+
+ // Create the overloaded operator invocation.
+ if (E->getNumArgs() == 1 || isPostIncDec) {
+ UnaryOperator::Opcode Opc
+ = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec);
+ return SemaRef.CreateOverloadedUnaryOp(E->getOperatorLoc(), Opc,
+ Functions, move(First));
+ }
+
+ // FIXME: This would be far less ugly if CreateOverloadedBinOp took
+ // in ExprArg arguments!
+ BinaryOperator::Opcode Opc =
+ BinaryOperator::getOverloadedOpcode(E->getOperator());
+ OwningExprResult Result
+ = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc,
+ Functions, Args[0], Args[1]);
+
+ if (Result.isInvalid())
+ return SemaRef.ExprError();
+
+ First.release();
+ Second.release();
+ return move(Result);
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) {
+ Sema::OwningExprResult Cond = Visit(E->getCond());
+ if (Cond.isInvalid())
+ return SemaRef.ExprError();
+
+ // FIXME: use getLHS() and cope with NULLness
+ Sema::OwningExprResult True = Visit(E->getTrueExpr());
+ if (True.isInvalid())
+ return SemaRef.ExprError();
+
+ Sema::OwningExprResult False = Visit(E->getFalseExpr());
+ if (False.isInvalid())
+ return SemaRef.ExprError();
+
+ 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 conditional operator call expression.
+ return SemaRef.Owned(new (SemaRef.Context) ConditionalOperator(
+ Cond.takeAs<Expr>(),
+ True.takeAs<Expr>(),
+ False.takeAs<Expr>(),
+ E->getType()));
+ }
+
+
+ return SemaRef.ActOnConditionalOp(/*FIXME*/E->getCond()->getLocEnd(),
+ /*FIXME*/E->getFalseExpr()->getLocStart(),
+ move(Cond), move(True), move(False));
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ bool isSizeOf = E->isSizeOf();
+
+ if (E->isArgumentType()) {
+ QualType T = E->getArgumentType();
+ if (T->isDependentType()) {
+ T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+ /*FIXME*/E->getOperatorLoc(),
+ &SemaRef.PP.getIdentifierTable().get("sizeof"));
+ if (T.isNull())
+ return SemaRef.ExprError();
+ }
+
+ return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
+ E->getSourceRange());
+ }
+
+ Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
+ if (Arg.isInvalid())
+ return SemaRef.ExprError();
+
+ Sema::OwningExprResult Result
+ = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
+ isSizeOf, E->getSourceRange());
+ if (Result.isInvalid())
+ return SemaRef.ExprError();
+
+ Arg.release();
+ return move(Result);
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) {
+ CXXScopeSpec SS = SemaRef.InstantiateScopeSpecifier(E->begin(), E->size(),
+ E->getQualifierRange(),
+ TemplateArgs,
+ NumTemplateArgs);
+ if (SS.isInvalid() || SS.isEmpty())
+ return SemaRef.ExprError();
+
+ // FIXME: We're passing in a NULL scope, because
+ // ActOnDeclarationNameExpr doesn't actually use the scope when we
+ // give it a non-empty scope specifier. Investigate whether it would
+ // be better to refactor ActOnDeclarationNameExpr.
+ return SemaRef.ActOnDeclarationNameExpr(/*Scope=*/0, E->getLocation(),
+ E->getDeclName(),
+ /*HasTrailingLParen=*/false,
+ &SS,
+ /*FIXME:isAddressOfOperand=*/false);
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
+ CXXTemporaryObjectExpr *E) {
+ QualType T = E->getType();
+ if (T->isDependentType()) {
+ T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+ E->getTypeBeginLoc(), DeclarationName());
+ if (T.isNull())
+ return SemaRef.ExprError();
+ }
+
+ llvm::SmallVector<Expr *, 16> Args;
+ Args.reserve(E->getNumArgs());
+ bool Invalid = false;
+ for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
+ ArgEnd = E->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ OwningExprResult InstantiatedArg = Visit(*Arg);
+ if (InstantiatedArg.isInvalid()) {
+ Invalid = true;
+ break;
+ }
+
+ Args.push_back((Expr *)InstantiatedArg.release());
+ }
+
+ if (!Invalid) {
+ SourceLocation CommaLoc;
+ // FIXME: HACK!
+ if (Args.size() > 1)
+ CommaLoc
+ = SemaRef.PP.getLocForEndOfToken(Args[0]->getSourceRange().getEnd());
+ Sema::OwningExprResult Result(
+ SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
+ /*, FIXME*/),
+ T.getAsOpaquePtr(),
+ /*FIXME*/E->getTypeBeginLoc(),
+ Sema::MultiExprArg(SemaRef,
+ (void**)&Args[0],
+ Args.size()),
+ /*HACK*/&CommaLoc,
+ E->getSourceRange().getEnd()));
+ // At this point, Args no longer owns the arguments, no matter what.
+ return move(Result);
+ }
+
+ // Clean up the instantiated arguments.
+ // FIXME: Would rather do this with RAII.
+ for (unsigned Idx = 0; Idx < Args.size(); ++Idx)
+ SemaRef.DeleteExpr(Args[Idx]);
+
+ return SemaRef.ExprError();
+}
+
+Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr(
+ ImplicitCastExpr *E) {
+ assert(!E->isTypeDependent() && "Implicit casts must have known types");
+
+ Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return SemaRef.ExprError();
+
+ ImplicitCastExpr *ICE =
+ new (SemaRef.Context) ImplicitCastExpr(E->getType(),
+ (Expr *)SubExpr.release(),
+ E->isLvalueCast());
+ return SemaRef.Owned(ICE);
+}
+
+Sema::OwningExprResult
+Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);
+ return Instantiator.Visit(E);
+}
More information about the cfe-commits
mailing list