Add parsing for references to member function templates with explicit

template argument lists, e.g., x.f<int>().

Semantic analysis will be a separate commit.

llvm-svn: 80624
This commit is contained in:
Douglas Gregor 2009-08-31 21:16:32 +00:00
parent cc2f1eb7fe
commit fbc1823451
6 changed files with 107 additions and 2 deletions

View File

@ -1321,6 +1321,53 @@ public:
return ExprEmpty();
}
/// \brief Parsed a reference to a member template-id.
///
/// This callback will occur instead of ActOnMemberReferenceExpr() when the
/// member in question is a template for which the code provides an
/// explicitly-specified template argument list, e.g.,
///
/// \code
/// x.f<int>()
/// \endcode
///
/// \param S the scope in which the member reference expression occurs
///
/// \param Base the expression to the left of the "." or "->".
///
/// \param OpLoc the location of the "." or "->".
///
/// \param OpKind the kind of operator, which will be "." or "->".
///
/// \param SS the scope specifier that precedes the template-id in, e.g.,
/// \c x.Base::f<int>().
///
/// \param Template the declaration of the template that is being referenced.
///
/// \param TemplateNameLoc the location of the template name referred to by
/// \p Template.
///
/// \param LAngleLoc the location of the left angle bracket ('<')
///
/// \param TemplateArgs the (possibly-empty) template argument list provided
/// as part of the member reference.
///
/// \param RAngleLoc the location of the right angle bracket ('>')
virtual OwningExprResult
ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
const CXXScopeSpec &SS,
// FIXME: "template" keyword?
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc) {
return ExprEmpty();
}
/// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
/// (C++ [intro.execution]p12).
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {

View File

@ -941,7 +941,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ObjCImpDecl, &SS);
ConsumeToken();
} else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
// We have a C++ pseudo-destructor.
// We have a C++ pseudo-destructor or a destructor call, e.g., t.~T()
// Consume the tilde.
ConsumeToken();
@ -961,6 +961,8 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
&SS);
ConsumeToken();
} else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
// We have a reference to a member operator, e.g., t.operator int or
// t.operator+.
if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
if (!LHS.isInvalid())
LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
@ -983,6 +985,27 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
// Don't emit a diagnostic; ParseConversionFunctionId does it for us
return ExprError();
}
} else if (getLang().CPlusPlus && Tok.is(tok::annot_template_id)) {
// We have a reference to a member template along with explicitly-
// specified template arguments, e.g., t.f<int>.
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
if (!LHS.isInvalid()) {
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
LHS = Actions.ActOnMemberTemplateIdReferenceExpr(CurScope, move(LHS),
OpLoc, OpKind, SS,
TemplateTy::make(TemplateId->Template),
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
}
ConsumeToken();
} else {
if (getLang().CPlusPlus)
Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);

View File

@ -1598,6 +1598,7 @@ public:
DeclarationName MemberName,
DeclPtrTy ImplDecl,
const CXXScopeSpec *SS = 0);
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
@ -1972,6 +1973,19 @@ public:
TypeTy *Ty,
const CXXScopeSpec *SS = 0);
virtual OwningExprResult
ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
const CXXScopeSpec &SS,
// FIXME: "template" keyword?
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc);
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.

View File

@ -2005,7 +2005,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
ImpCastExprToType(BaseExpr, BaseType);
}
} else if (BaseType->isObjCClassType() &&
BaseType != Context.ObjCClassRedefinitionType) {
BaseType != Context.ObjCClassRedefinitionType) {
BaseType = Context.ObjCClassRedefinitionType;
ImpCastExprToType(BaseExpr, BaseType);
}

View File

@ -1831,6 +1831,21 @@ Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
ConvName, DeclPtrTy(), SS);
}
Sema::OwningExprResult
Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
const CXXScopeSpec &SS,
TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation *TemplateArgLocs,
SourceLocation RAngleLoc) {
// FIXME: Implement!
return ExprError();
}
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)

View File

@ -40,5 +40,11 @@ void test_X_f1_address() {
int& (X::*pm3)(float, int) = &X::f1;
}
void test_X_f0_explicit(X x, int i, long l) {
int &ir1 = x.f0<int>(i);
int &ir2 = x.f0<>(i);
int &ir3 = x.f0<long>(i);
}
// PR4608
class A { template <class x> x a(x z) { return z+y; } int y; };