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); }
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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