Implement template instantiation for several more kinds of expressions:
- C++ function casts, e.g., T(foo)
- sizeof(), alignof()
More importantly, this allows us to verify that we're performing
overload resolution during template instantiation, with
argument-dependent lookup and the "cached" results of name lookup from
the template definition.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66947 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index b3e4148..4bd7ad4 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -17,6 +17,7 @@
#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"
@@ -441,7 +442,12 @@
break;
case TemplateArgument::Expression:
- assert(false && "Cannot instantiate expressions yet");
+ Sema::OwningExprResult E
+ = SemaRef.InstantiateExpr(Arg->getAsExpr(), TemplateArgs,
+ NumTemplateArgs);
+ if (E.isInvalid())
+ return QualType();
+ InstantiatedTemplateArgs.push_back((Expr *)E.release());
break;
}
}
@@ -564,6 +570,8 @@
unsigned NumTemplateArgs;
public:
+ typedef Sema::OwningExprResult OwningExprResult;
+
TemplateExprInstantiator(Sema &SemaRef,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs)
@@ -573,11 +581,13 @@
// FIXME: Once we get closer to completion, replace these
// manually-written declarations with automatically-generated ones
// from clang/AST/StmtNodes.def.
- Sema::OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
- Sema::OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
- Sema::OwningExprResult VisitParenExpr(ParenExpr *E);
- Sema::OwningExprResult VisitBinaryOperator(BinaryOperator *E);
- Sema::OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
+ OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
+ OwningExprResult VisitParenExpr(ParenExpr *E);
+ OwningExprResult VisitBinaryOperator(BinaryOperator *E);
+ OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
// Base case. I'm supposed to ignore this.
Sema::OwningExprResult VisitStmt(Stmt *) {
@@ -692,6 +702,9 @@
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();
@@ -717,6 +730,90 @@
}
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::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::ExprResult Result
+ = SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
+ /*, FIXME*/),
+ T.getAsOpaquePtr(),
+ /*FIXME*/E->getTypeBeginLoc(),
+ (void**)&Args[0], Args.size(),
+ /*HACK*/&CommaLoc,
+ E->getSourceRange().getEnd());
+ if (!Result.isInvalid())
+ return SemaRef.Owned(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
Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);