forked from OSchip/llvm-project
Template instantiation for call expressions.
llvm-svn: 72081
This commit is contained in:
parent
b27c94199f
commit
be81045db7
|
@ -800,6 +800,8 @@ public:
|
|||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
UnresolvedFunctionNameExpr* Clone(ASTContext &C) const;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == UnresolvedFunctionNameExprClass;
|
||||
}
|
||||
|
|
|
@ -131,6 +131,11 @@ Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() {
|
|||
return child_iterator();
|
||||
}
|
||||
|
||||
UnresolvedFunctionNameExpr*
|
||||
UnresolvedFunctionNameExpr::Clone(ASTContext &C) const {
|
||||
return new (C) UnresolvedFunctionNameExpr(Name, getType(), Loc);
|
||||
}
|
||||
|
||||
// UnaryTypeTraitExpr
|
||||
Stmt::child_iterator UnaryTypeTraitExpr::child_begin() {
|
||||
return child_iterator();
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace {
|
|||
OwningExprResult VisitParenExpr(ParenExpr *E);
|
||||
OwningExprResult VisitUnaryOperator(UnaryOperator *E);
|
||||
OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E);
|
||||
OwningExprResult VisitCallExpr(CallExpr *E);
|
||||
OwningExprResult VisitBinaryOperator(BinaryOperator *E);
|
||||
OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
|
||||
OwningExprResult VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E);
|
||||
|
@ -58,6 +59,8 @@ namespace {
|
|||
OwningExprResult VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
|
||||
OwningExprResult VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
|
||||
OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
|
||||
OwningExprResult VisitUnresolvedFunctionNameExpr(
|
||||
UnresolvedFunctionNameExpr *E);
|
||||
|
||||
// Base case. I'm supposed to ignore this.
|
||||
Sema::OwningExprResult VisitStmt(Stmt *S) {
|
||||
|
@ -113,9 +116,16 @@ TemplateExprInstantiator::VisitGNUNullExpr(GNUNullExpr *E) {
|
|||
return SemaRef.Clone(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
|
||||
UnresolvedFunctionNameExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
Decl *D = E->getDecl();
|
||||
ValueDecl *NewD = 0;
|
||||
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
||||
assert(NTTP->getDepth() == 0 && "No nested templates yet");
|
||||
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
|
||||
|
@ -136,19 +146,23 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
|
|||
*Arg.getAsIntegral(),
|
||||
T,
|
||||
E->getSourceRange().getBegin()));
|
||||
} else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
|
||||
ParmVarDecl *ParmInst
|
||||
= SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
|
||||
QualType T = ParmInst->getType();
|
||||
return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(ParmInst,
|
||||
} else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
|
||||
NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
|
||||
else if (isa<FunctionDecl>(D) || isa<OverloadedFunctionDecl>(D))
|
||||
// FIXME: Instantiate decl!
|
||||
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(),
|
||||
E->getLocation(),
|
||||
T->isDependentType(),
|
||||
T->isDependentType()));
|
||||
} else
|
||||
assert(false && "Can't handle arbitrary declaration references");
|
||||
|
||||
return SemaRef.ExprError();
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
@ -203,6 +217,39 @@ TemplateExprInstantiator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
|||
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
|
||||
TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
|
||||
Sema::OwningExprResult LHS = Visit(E->getLHS());
|
||||
|
|
|
@ -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.
|
Loading…
Reference in New Issue