Template instantiation for call expressions.

llvm-svn: 72081
This commit is contained in:
Douglas Gregor 2009-05-19 00:38:01 +00:00
parent b27c94199f
commit be81045db7
4 changed files with 113 additions and 9 deletions

View File

@ -800,6 +800,8 @@ public:
virtual SourceRange getSourceRange() const { return SourceRange(Loc); } virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
UnresolvedFunctionNameExpr* Clone(ASTContext &C) const;
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedFunctionNameExprClass; return T->getStmtClass() == UnresolvedFunctionNameExprClass;
} }

View File

@ -131,6 +131,11 @@ Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() {
return child_iterator(); return child_iterator();
} }
UnresolvedFunctionNameExpr*
UnresolvedFunctionNameExpr::Clone(ASTContext &C) const {
return new (C) UnresolvedFunctionNameExpr(Name, getType(), Loc);
}
// UnaryTypeTraitExpr // UnaryTypeTraitExpr
Stmt::child_iterator UnaryTypeTraitExpr::child_begin() { Stmt::child_iterator UnaryTypeTraitExpr::child_begin() {
return child_iterator(); return child_iterator();

View File

@ -46,6 +46,7 @@ namespace {
OwningExprResult VisitParenExpr(ParenExpr *E); OwningExprResult VisitParenExpr(ParenExpr *E);
OwningExprResult VisitUnaryOperator(UnaryOperator *E); OwningExprResult VisitUnaryOperator(UnaryOperator *E);
OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E); OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E);
OwningExprResult VisitCallExpr(CallExpr *E);
OwningExprResult VisitBinaryOperator(BinaryOperator *E); OwningExprResult VisitBinaryOperator(BinaryOperator *E);
OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
OwningExprResult VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E); OwningExprResult VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E);
@ -58,6 +59,8 @@ namespace {
OwningExprResult VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); OwningExprResult VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
OwningExprResult VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); OwningExprResult VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
OwningExprResult VisitGNUNullExpr(GNUNullExpr *E); OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
OwningExprResult VisitUnresolvedFunctionNameExpr(
UnresolvedFunctionNameExpr *E);
// Base case. I'm supposed to ignore this. // Base case. I'm supposed to ignore this.
Sema::OwningExprResult VisitStmt(Stmt *S) { Sema::OwningExprResult VisitStmt(Stmt *S) {
@ -113,9 +116,16 @@ TemplateExprInstantiator::VisitGNUNullExpr(GNUNullExpr *E) {
return SemaRef.Clone(E); return SemaRef.Clone(E);
} }
Sema::OwningExprResult
TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
UnresolvedFunctionNameExpr *E) {
return SemaRef.Clone(E);
}
Sema::OwningExprResult Sema::OwningExprResult
TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
Decl *D = E->getDecl(); Decl *D = E->getDecl();
ValueDecl *NewD = 0;
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
assert(NTTP->getDepth() == 0 && "No nested templates yet"); assert(NTTP->getDepth() == 0 && "No nested templates yet");
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
@ -136,19 +146,23 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
*Arg.getAsIntegral(), *Arg.getAsIntegral(),
T, T,
E->getSourceRange().getBegin())); E->getSourceRange().getBegin()));
} else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
ParmVarDecl *ParmInst NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
= SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm); else if (isa<FunctionDecl>(D) || isa<OverloadedFunctionDecl>(D))
QualType T = ParmInst->getType(); // FIXME: Instantiate decl!
return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(ParmInst, NewD = cast<ValueDecl>(D);
else
assert(false && "Unhandled declaratrion reference kind");
if (!NewD)
return SemaRef.ExprError();
QualType T = NewD->getType();
return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(NewD,
T.getNonReferenceType(), T.getNonReferenceType(),
E->getLocation(), E->getLocation(),
T->isDependentType(), T->isDependentType(),
T->isDependentType())); T->isDependentType()));
} else
assert(false && "Can't handle arbitrary declaration references");
return SemaRef.ExprError();
} }
Sema::OwningExprResult Sema::OwningExprResult
@ -203,6 +217,39 @@ TemplateExprInstantiator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
E->getRBracketLoc()); E->getRBracketLoc());
} }
Sema::OwningExprResult TemplateExprInstantiator::VisitCallExpr(CallExpr *E) {
// Instantiate callee
OwningExprResult Callee = Visit(E->getCallee());
if (Callee.isInvalid())
return SemaRef.ExprError();
// Instantiate arguments
llvm::SmallVector<Expr*, 8> Args;
llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
OwningExprResult Arg = Visit(E->getArg(I));
if (Arg.isInvalid()) {
for (unsigned Victim = 0; Victim != I; ++Victim)
Args[Victim]->Destroy(SemaRef.Context);
return SemaRef.ExprError();
}
FakeCommaLocs.push_back(
SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd()));
Args.push_back(Arg.takeAs<Expr>());
}
SourceLocation FakeLParenLoc
= ((Expr *)Callee.get())->getSourceRange().getBegin();
return SemaRef.ActOnCallExpr(/*Scope=*/0, move(Callee),
/*FIXME:*/FakeLParenLoc,
Sema::MultiExprArg(SemaRef,
(void **)&Args.front(),
Args.size()),
/*FIXME:*/&FakeCommaLocs.front(),
E->getRParenLoc());
}
Sema::OwningExprResult Sema::OwningExprResult
TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) { TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
Sema::OwningExprResult LHS = Visit(E->getLHS()); Sema::OwningExprResult LHS = Visit(E->getLHS());

View File

@ -0,0 +1,50 @@
// RUN: clang-cc -fsyntax-only -verify %s
namespace N1 {
struct X0 { };
int& f0(X0);
}
namespace N2 {
char& f0(char);
template<typename T, typename Result>
struct call_f0 {
void test_f0(T t) {
Result result = f0(t);
}
};
}
template struct N2::call_f0<int, char&>;
template struct N2::call_f0<N1::X0, int&>;
namespace N3 {
template<typename T, typename Result>
struct call_f0 {
void test_f0(T t) {
Result &result = f0(t); // expected-error 2{{no matching}}
}
};
}
template struct N3::call_f0<int, char&>; // expected-note{{instantiation}}
template struct N3::call_f0<N1::X0, int&>;
short& f0(char);
namespace N4 {
template<typename T, typename Result>
struct call_f0 {
void test_f0(T t) {
Result &result = f0(t);
}
};
}
template struct N4::call_f0<int, short&>;
template struct N4::call_f0<N1::X0, int&>;
template struct N3::call_f0<int, short&>; // expected-note{{instantiation}}
// FIXME: test overloaded function call operators, calls to member
// functions, etc.