forked from OSchip/llvm-project
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:
parent
cc2f1eb7fe
commit
fbc1823451
|
@ -1321,6 +1321,53 @@ public:
|
||||||
return ExprEmpty();
|
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.
|
/// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
|
||||||
/// (C++ [intro.execution]p12).
|
/// (C++ [intro.execution]p12).
|
||||||
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
|
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
|
||||||
|
|
|
@ -941,7 +941,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
||||||
ObjCImpDecl, &SS);
|
ObjCImpDecl, &SS);
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
} else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
|
} 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.
|
// Consume the tilde.
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
@ -961,6 +961,8 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
||||||
&SS);
|
&SS);
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
} else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
|
} 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 (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
|
||||||
if (!LHS.isInvalid())
|
if (!LHS.isInvalid())
|
||||||
LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
|
LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
|
||||||
|
@ -983,6 +985,27 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
||||||
// Don't emit a diagnostic; ParseConversionFunctionId does it for us
|
// Don't emit a diagnostic; ParseConversionFunctionId does it for us
|
||||||
return ExprError();
|
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 {
|
} else {
|
||||||
if (getLang().CPlusPlus)
|
if (getLang().CPlusPlus)
|
||||||
Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
|
Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
|
||||||
|
|
|
@ -1598,6 +1598,7 @@ public:
|
||||||
DeclarationName MemberName,
|
DeclarationName MemberName,
|
||||||
DeclPtrTy ImplDecl,
|
DeclPtrTy ImplDecl,
|
||||||
const CXXScopeSpec *SS = 0);
|
const CXXScopeSpec *SS = 0);
|
||||||
|
|
||||||
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
||||||
SourceLocation OpLoc,
|
SourceLocation OpLoc,
|
||||||
tok::TokenKind OpKind,
|
tok::TokenKind OpKind,
|
||||||
|
@ -1972,6 +1973,19 @@ public:
|
||||||
TypeTy *Ty,
|
TypeTy *Ty,
|
||||||
const CXXScopeSpec *SS = 0);
|
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
|
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
|
||||||
/// non-empty, will create a new CXXExprWithTemporaries expression.
|
/// non-empty, will create a new CXXExprWithTemporaries expression.
|
||||||
/// Otherwise, just returs the passed in expression.
|
/// Otherwise, just returs the passed in expression.
|
||||||
|
|
|
@ -2005,7 +2005,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
||||||
ImpCastExprToType(BaseExpr, BaseType);
|
ImpCastExprToType(BaseExpr, BaseType);
|
||||||
}
|
}
|
||||||
} else if (BaseType->isObjCClassType() &&
|
} else if (BaseType->isObjCClassType() &&
|
||||||
BaseType != Context.ObjCClassRedefinitionType) {
|
BaseType != Context.ObjCClassRedefinitionType) {
|
||||||
BaseType = Context.ObjCClassRedefinitionType;
|
BaseType = Context.ObjCClassRedefinitionType;
|
||||||
ImpCastExprToType(BaseExpr, BaseType);
|
ImpCastExprToType(BaseExpr, BaseType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1831,6 +1831,21 @@ Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||||
ConvName, DeclPtrTy(), SS);
|
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) {
|
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
|
||||||
Expr *FullExpr = Arg.takeAs<Expr>();
|
Expr *FullExpr = Arg.takeAs<Expr>();
|
||||||
if (FullExpr)
|
if (FullExpr)
|
||||||
|
|
|
@ -40,5 +40,11 @@ void test_X_f1_address() {
|
||||||
int& (X::*pm3)(float, int) = &X::f1;
|
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
|
// PR4608
|
||||||
class A { template <class x> x a(x z) { return z+y; } int y; };
|
class A { template <class x> x a(x z) { return z+y; } int y; };
|
||||||
|
|
Loading…
Reference in New Issue