diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 401 |
1 files changed, 0 insertions, 401 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e856e91ffcc..4d271a38309 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -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 @@ QualType Sema::InstantiateType(QualType T, 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. /// |

