forked from OSchip/llvm-project
Preliminary AST representation and semantic analysis for
explicitly-specified template argument lists in member reference expressions, e.g., x->f<int>() llvm-svn: 80646
This commit is contained in:
parent
b1b2016b83
commit
84f14dd674
|
@ -1043,6 +1043,31 @@ struct NameQualifier {
|
||||||
SourceRange Range;
|
SourceRange Range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Represents an explicit template argument list in C++, e.g.,
|
||||||
|
/// the "<int>" in "sort<int>".
|
||||||
|
struct ExplicitTemplateArgumentList {
|
||||||
|
/// \brief The source location of the left angle bracket ('<');
|
||||||
|
SourceLocation LAngleLoc;
|
||||||
|
|
||||||
|
/// \brief The source location of the right angle bracket ('>');
|
||||||
|
SourceLocation RAngleLoc;
|
||||||
|
|
||||||
|
/// \brief The number of template arguments in TemplateArgs.
|
||||||
|
/// The actual template arguments (if any) are stored after the
|
||||||
|
/// ExplicitTemplateArgumentList structure.
|
||||||
|
unsigned NumTemplateArgs;
|
||||||
|
|
||||||
|
/// \brief Retrieve the template arguments
|
||||||
|
TemplateArgument *getTemplateArgs() {
|
||||||
|
return reinterpret_cast<TemplateArgument *> (this + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the template arguments
|
||||||
|
const TemplateArgument *getTemplateArgs() const {
|
||||||
|
return reinterpret_cast<const TemplateArgument *> (this + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
|
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
|
||||||
///
|
///
|
||||||
class MemberExpr : public Expr {
|
class MemberExpr : public Expr {
|
||||||
|
@ -1061,9 +1086,17 @@ class MemberExpr : public Expr {
|
||||||
bool IsArrow : 1;
|
bool IsArrow : 1;
|
||||||
|
|
||||||
/// \brief True if this member expression used a nested-name-specifier to
|
/// \brief True if this member expression used a nested-name-specifier to
|
||||||
/// refer to the member, e.g., "x->Base::f".
|
/// refer to the member, e.g., "x->Base::f". When true, a NameQualifier
|
||||||
|
/// structure is allocated immediately after the MemberExpr.
|
||||||
bool HasQualifier : 1;
|
bool HasQualifier : 1;
|
||||||
|
|
||||||
|
/// \brief True if this member expression specified a template argument list
|
||||||
|
/// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList
|
||||||
|
/// structure (and its TemplateArguments) are allocated immediately after
|
||||||
|
/// the MemberExpr or, if the member expression also has a qualifier, after
|
||||||
|
/// the NameQualifier structure.
|
||||||
|
bool HasExplicitTemplateArgumentList : 1;
|
||||||
|
|
||||||
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
||||||
NameQualifier *getMemberQualifier() {
|
NameQualifier *getMemberQualifier() {
|
||||||
if (!HasQualifier)
|
if (!HasQualifier)
|
||||||
|
@ -1074,15 +1107,33 @@ class MemberExpr : public Expr {
|
||||||
|
|
||||||
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
||||||
const NameQualifier *getMemberQualifier() const {
|
const NameQualifier *getMemberQualifier() const {
|
||||||
if (!HasQualifier)
|
return const_cast<MemberExpr *>(this)->getMemberQualifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the explicit template argument list that followed the
|
||||||
|
/// member template name, if any.
|
||||||
|
ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
|
||||||
|
if (!HasExplicitTemplateArgumentList)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return reinterpret_cast<const NameQualifier *> (this + 1);
|
if (!HasQualifier)
|
||||||
|
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
|
||||||
|
|
||||||
|
return reinterpret_cast<ExplicitTemplateArgumentList *>(
|
||||||
|
getMemberQualifier() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the explicit template argument list that followed the
|
||||||
|
/// member template name, if any.
|
||||||
|
const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
|
||||||
|
return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||||
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
|
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
|
||||||
QualType ty);
|
bool has_explicit, SourceLocation langle,
|
||||||
|
const TemplateArgument *targs, unsigned numtargs,
|
||||||
|
SourceLocation rangle, QualType ty);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
|
MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
|
||||||
|
@ -1090,7 +1141,7 @@ public:
|
||||||
: Expr(MemberExprClass, ty,
|
: Expr(MemberExprClass, ty,
|
||||||
base->isTypeDependent(), base->isValueDependent()),
|
base->isTypeDependent(), base->isValueDependent()),
|
||||||
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
|
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
|
||||||
HasQualifier(false) {}
|
HasQualifier(false), HasExplicitTemplateArgumentList(false) {}
|
||||||
|
|
||||||
/// \brief Build an empty member reference expression.
|
/// \brief Build an empty member reference expression.
|
||||||
explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { }
|
explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { }
|
||||||
|
@ -1098,7 +1149,13 @@ public:
|
||||||
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
|
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
|
||||||
NestedNameSpecifier *qual, SourceRange qualrange,
|
NestedNameSpecifier *qual, SourceRange qualrange,
|
||||||
NamedDecl *memberdecl,
|
NamedDecl *memberdecl,
|
||||||
SourceLocation l, QualType ty);
|
SourceLocation l,
|
||||||
|
bool has_explicit,
|
||||||
|
SourceLocation langle,
|
||||||
|
const TemplateArgument *targs,
|
||||||
|
unsigned numtargs,
|
||||||
|
SourceLocation rangle,
|
||||||
|
QualType ty);
|
||||||
|
|
||||||
void setBase(Expr *E) { Base = E; }
|
void setBase(Expr *E) { Base = E; }
|
||||||
Expr *getBase() const { return cast<Expr>(Base); }
|
Expr *getBase() const { return cast<Expr>(Base); }
|
||||||
|
@ -1110,7 +1167,7 @@ public:
|
||||||
NamedDecl *getMemberDecl() const { return MemberDecl; }
|
NamedDecl *getMemberDecl() const { return MemberDecl; }
|
||||||
void setMemberDecl(NamedDecl *D) { MemberDecl = D; }
|
void setMemberDecl(NamedDecl *D) { MemberDecl = D; }
|
||||||
|
|
||||||
/// \brief Determines whether this adorned member expression actually had
|
/// \brief Determines whether this member expression actually had
|
||||||
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
|
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
|
||||||
/// x->Base::foo.
|
/// x->Base::foo.
|
||||||
bool hasQualifier() const { return HasQualifier; }
|
bool hasQualifier() const { return HasQualifier; }
|
||||||
|
@ -1135,6 +1192,48 @@ public:
|
||||||
return getMemberQualifier()->NNS;
|
return getMemberQualifier()->NNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Determines whether this member expression actually had a C++
|
||||||
|
/// template argument list explicitly specified, e.g., x.f<int>.
|
||||||
|
bool hasExplicitTemplateArgumentList() {
|
||||||
|
return HasExplicitTemplateArgumentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the location of the left angle bracket following the
|
||||||
|
/// member name ('<'), if any.
|
||||||
|
SourceLocation getLAngleLoc() const {
|
||||||
|
if (!HasExplicitTemplateArgumentList)
|
||||||
|
return SourceLocation();
|
||||||
|
|
||||||
|
return getExplicitTemplateArgumentList()->LAngleLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the template arguments provided as part of this
|
||||||
|
/// template-id.
|
||||||
|
const TemplateArgument *getTemplateArgs() const {
|
||||||
|
if (!HasExplicitTemplateArgumentList)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return getExplicitTemplateArgumentList()->getTemplateArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the number of template arguments provided as part of this
|
||||||
|
/// template-id.
|
||||||
|
unsigned getNumTemplateArgs() const {
|
||||||
|
if (!HasExplicitTemplateArgumentList)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return getExplicitTemplateArgumentList()->NumTemplateArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the location of the right angle bracket following the
|
||||||
|
/// template arguments ('>').
|
||||||
|
SourceLocation getRAngleLoc() const {
|
||||||
|
if (!HasExplicitTemplateArgumentList)
|
||||||
|
return SourceLocation();
|
||||||
|
|
||||||
|
return getExplicitTemplateArgumentList()->RAngleLoc;
|
||||||
|
}
|
||||||
|
|
||||||
bool isArrow() const { return IsArrow; }
|
bool isArrow() const { return IsArrow; }
|
||||||
void setArrow(bool A) { IsArrow = A; }
|
void setArrow(bool A) { IsArrow = A; }
|
||||||
|
|
||||||
|
@ -1146,10 +1245,14 @@ public:
|
||||||
virtual SourceRange getSourceRange() const {
|
virtual SourceRange getSourceRange() const {
|
||||||
// If we have an implicit base (like a C++ implicit this),
|
// If we have an implicit base (like a C++ implicit this),
|
||||||
// make sure not to return its location
|
// make sure not to return its location
|
||||||
|
SourceLocation EndLoc = MemberLoc;
|
||||||
|
if (HasExplicitTemplateArgumentList)
|
||||||
|
EndLoc = getRAngleLoc();
|
||||||
|
|
||||||
SourceLocation BaseLoc = getBase()->getLocStart();
|
SourceLocation BaseLoc = getBase()->getLocStart();
|
||||||
if (BaseLoc.isInvalid())
|
if (BaseLoc.isInvalid())
|
||||||
return SourceRange(MemberLoc, MemberLoc);
|
return SourceRange(MemberLoc, EndLoc);
|
||||||
return SourceRange(BaseLoc, MemberLoc);
|
return SourceRange(BaseLoc, EndLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SourceLocation getExprLoc() const { return MemberLoc; }
|
virtual SourceLocation getExprLoc() const { return MemberLoc; }
|
||||||
|
|
|
@ -264,31 +264,58 @@ QualType CallExpr::getCallReturnType() const {
|
||||||
|
|
||||||
MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||||
SourceRange qualrange, NamedDecl *memberdecl,
|
SourceRange qualrange, NamedDecl *memberdecl,
|
||||||
SourceLocation l, QualType ty)
|
SourceLocation l, bool has_explicit,
|
||||||
|
SourceLocation langle,
|
||||||
|
const TemplateArgument *targs, unsigned numtargs,
|
||||||
|
SourceLocation rangle, QualType ty)
|
||||||
: Expr(MemberExprClass, ty,
|
: Expr(MemberExprClass, ty,
|
||||||
base->isTypeDependent() || (qual && qual->isDependent()),
|
base->isTypeDependent() || (qual && qual->isDependent()),
|
||||||
base->isValueDependent() || (qual && qual->isDependent())),
|
base->isValueDependent() || (qual && qual->isDependent())),
|
||||||
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
|
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
|
||||||
HasQualifier(qual != 0) {
|
HasQualifier(qual != 0), HasExplicitTemplateArgumentList(has_explicit) {
|
||||||
// Initialize the qualifier, if any.
|
// Initialize the qualifier, if any.
|
||||||
if (HasQualifier) {
|
if (HasQualifier) {
|
||||||
NameQualifier *NQ = getMemberQualifier();
|
NameQualifier *NQ = getMemberQualifier();
|
||||||
NQ->NNS = qual;
|
NQ->NNS = qual;
|
||||||
NQ->Range = qualrange;
|
NQ->Range = qualrange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the explicit template argument list, if any.
|
||||||
|
if (HasExplicitTemplateArgumentList) {
|
||||||
|
ExplicitTemplateArgumentList *ETemplateArgs
|
||||||
|
= getExplicitTemplateArgumentList();
|
||||||
|
ETemplateArgs->LAngleLoc = langle;
|
||||||
|
ETemplateArgs->RAngleLoc = rangle;
|
||||||
|
ETemplateArgs->NumTemplateArgs = numtargs;
|
||||||
|
|
||||||
|
TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs();
|
||||||
|
for (unsigned I = 0; I < numtargs; ++I)
|
||||||
|
new (TemplateArgs + I) TemplateArgument(targs[I]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
|
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
|
||||||
NestedNameSpecifier *qual,
|
NestedNameSpecifier *qual,
|
||||||
SourceRange qualrange,
|
SourceRange qualrange,
|
||||||
NamedDecl *memberdecl,
|
NamedDecl *memberdecl,
|
||||||
SourceLocation l, QualType ty) {
|
SourceLocation l,
|
||||||
|
bool has_explicit,
|
||||||
|
SourceLocation langle,
|
||||||
|
const TemplateArgument *targs,
|
||||||
|
unsigned numtargs,
|
||||||
|
SourceLocation rangle,
|
||||||
|
QualType ty) {
|
||||||
std::size_t Size = sizeof(MemberExpr);
|
std::size_t Size = sizeof(MemberExpr);
|
||||||
if (qual != 0)
|
if (qual != 0)
|
||||||
Size += sizeof(NameQualifier);
|
Size += sizeof(NameQualifier);
|
||||||
|
|
||||||
|
if (has_explicit)
|
||||||
|
Size += sizeof(ExplicitTemplateArgumentList) +
|
||||||
|
sizeof(TemplateArgument) * numtargs;
|
||||||
|
|
||||||
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
|
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
|
||||||
return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
|
return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
|
||||||
|
has_explicit, langle, targs, numtargs, rangle,
|
||||||
ty);
|
ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -743,6 +743,12 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
|
||||||
Qualifier->print(OS, Policy);
|
Qualifier->print(OS, Policy);
|
||||||
|
|
||||||
OS << Node->getMemberDecl()->getNameAsString();
|
OS << Node->getMemberDecl()->getNameAsString();
|
||||||
|
|
||||||
|
if (Node->hasExplicitTemplateArgumentList())
|
||||||
|
OS << TemplateSpecializationType::PrintTemplateArgumentList(
|
||||||
|
Node->getTemplateArgs(),
|
||||||
|
Node->getNumTemplateArgs(),
|
||||||
|
Policy);
|
||||||
}
|
}
|
||||||
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
|
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
|
||||||
PrintExpr(Node->getBase());
|
PrintExpr(Node->getBase());
|
||||||
|
|
|
@ -416,6 +416,7 @@ void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
|
||||||
Writer.AddSourceLocation(E->getMemberLoc(), Record);
|
Writer.AddSourceLocation(E->getMemberLoc(), Record);
|
||||||
Record.push_back(E->isArrow());
|
Record.push_back(E->isArrow());
|
||||||
// FIXME: C++ nested-name-specifier
|
// FIXME: C++ nested-name-specifier
|
||||||
|
// FIXME: C++ template argument list
|
||||||
Code = pch::EXPR_MEMBER;
|
Code = pch::EXPR_MEMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1609,6 +1609,26 @@ public:
|
||||||
SourceLocation MemberLoc,
|
SourceLocation MemberLoc,
|
||||||
DeclarationName MemberName,
|
DeclarationName MemberName,
|
||||||
DeclPtrTy ImplDecl,
|
DeclPtrTy ImplDecl,
|
||||||
|
const CXXScopeSpec *SS = 0) {
|
||||||
|
// FIXME: Temporary helper while we migrate existing calls to
|
||||||
|
// BuildMemberReferenceExpr to support explicitly-specified template
|
||||||
|
// arguments.
|
||||||
|
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
|
||||||
|
MemberName, false, SourceLocation(), 0, 0,
|
||||||
|
SourceLocation(), ImplDecl, SS);
|
||||||
|
}
|
||||||
|
|
||||||
|
OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
|
||||||
|
SourceLocation OpLoc,
|
||||||
|
tok::TokenKind OpKind,
|
||||||
|
SourceLocation MemberLoc,
|
||||||
|
DeclarationName MemberName,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
SourceLocation LAngleLoc,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
|
SourceLocation RAngleLoc,
|
||||||
|
DeclPtrTy ImplDecl,
|
||||||
const CXXScopeSpec *SS = 0);
|
const CXXScopeSpec *SS = 0);
|
||||||
|
|
||||||
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
||||||
|
|
|
@ -885,7 +885,10 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
|
||||||
if (SS && SS->isSet())
|
if (SS && SS->isSet())
|
||||||
return MemberExpr::Create(C, Base, isArrow,
|
return MemberExpr::Create(C, Base, isArrow,
|
||||||
(NestedNameSpecifier *)SS->getScopeRep(),
|
(NestedNameSpecifier *)SS->getScopeRep(),
|
||||||
SS->getRange(), Member, Loc, Ty);
|
SS->getRange(), Member, Loc,
|
||||||
|
// FIXME: Explicit template argument lists
|
||||||
|
false, SourceLocation(), 0, 0, SourceLocation(),
|
||||||
|
Ty);
|
||||||
|
|
||||||
return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
|
return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
|
||||||
}
|
}
|
||||||
|
@ -1980,6 +1983,11 @@ Action::OwningExprResult
|
||||||
Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
||||||
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
||||||
DeclarationName MemberName,
|
DeclarationName MemberName,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
SourceLocation LAngleLoc,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
|
SourceLocation RAngleLoc,
|
||||||
DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) {
|
DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) {
|
||||||
if (SS && SS->isInvalid())
|
if (SS && SS->isInvalid())
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
@ -2153,14 +2161,34 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
||||||
if (FunctionTemplateDecl *FunTmpl
|
if (FunctionTemplateDecl *FunTmpl
|
||||||
= dyn_cast<FunctionTemplateDecl>(MemberDecl)) {
|
= dyn_cast<FunctionTemplateDecl>(MemberDecl)) {
|
||||||
MarkDeclarationReferenced(MemberLoc, MemberDecl);
|
MarkDeclarationReferenced(MemberLoc, MemberDecl);
|
||||||
|
|
||||||
|
if (HasExplicitTemplateArgs)
|
||||||
|
return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow,
|
||||||
|
(NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
|
||||||
|
SS? SS->getRange() : SourceRange(),
|
||||||
|
FunTmpl, MemberLoc, true,
|
||||||
|
LAngleLoc, ExplicitTemplateArgs,
|
||||||
|
NumExplicitTemplateArgs, RAngleLoc,
|
||||||
|
Context.OverloadTy));
|
||||||
|
|
||||||
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
|
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
|
||||||
FunTmpl, MemberLoc,
|
FunTmpl, MemberLoc,
|
||||||
Context.OverloadTy));
|
Context.OverloadTy));
|
||||||
}
|
}
|
||||||
if (OverloadedFunctionDecl *Ovl
|
if (OverloadedFunctionDecl *Ovl
|
||||||
= dyn_cast<OverloadedFunctionDecl>(MemberDecl))
|
= dyn_cast<OverloadedFunctionDecl>(MemberDecl)) {
|
||||||
|
if (HasExplicitTemplateArgs)
|
||||||
|
return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow,
|
||||||
|
(NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
|
||||||
|
SS? SS->getRange() : SourceRange(),
|
||||||
|
Ovl, MemberLoc, true,
|
||||||
|
LAngleLoc, ExplicitTemplateArgs,
|
||||||
|
NumExplicitTemplateArgs, RAngleLoc,
|
||||||
|
Context.OverloadTy));
|
||||||
|
|
||||||
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
|
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
|
||||||
Ovl, MemberLoc, Context.OverloadTy));
|
Ovl, MemberLoc, Context.OverloadTy));
|
||||||
|
}
|
||||||
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
|
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
|
||||||
MarkDeclarationReferenced(MemberLoc, MemberDecl);
|
MarkDeclarationReferenced(MemberLoc, MemberDecl);
|
||||||
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
|
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
|
||||||
|
|
|
@ -1831,21 +1831,6 @@ 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)
|
||||||
|
|
|
@ -4564,8 +4564,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
|
||||||
/*SuppressUserConversions=*/false);
|
/*SuppressUserConversions=*/false);
|
||||||
else
|
else
|
||||||
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
|
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
|
||||||
/*FIXME:*/false, /*FIXME:*/0,
|
MemExpr->hasExplicitTemplateArgumentList(),
|
||||||
/*FIXME:*/0, ObjectArg, Args, NumArgs,
|
MemExpr->getTemplateArgs(),
|
||||||
|
MemExpr->getNumTemplateArgs(),
|
||||||
|
ObjectArg, Args, NumArgs,
|
||||||
CandidateSet,
|
CandidateSet,
|
||||||
/*SuppressUsedConversions=*/false);
|
/*SuppressUsedConversions=*/false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1084,6 +1084,41 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,
|
||||||
RAngleLoc);
|
RAngleLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sema::OwningExprResult
|
||||||
|
Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
|
||||||
|
SourceLocation OpLoc,
|
||||||
|
tok::TokenKind OpKind,
|
||||||
|
const CXXScopeSpec &SS,
|
||||||
|
TemplateTy TemplateD,
|
||||||
|
SourceLocation TemplateNameLoc,
|
||||||
|
SourceLocation LAngleLoc,
|
||||||
|
ASTTemplateArgsPtr TemplateArgsIn,
|
||||||
|
SourceLocation *TemplateArgLocs,
|
||||||
|
SourceLocation RAngleLoc) {
|
||||||
|
TemplateName Template = TemplateD.getAsVal<TemplateName>();
|
||||||
|
|
||||||
|
// FIXME: We're going to end up looking up the template based on its name,
|
||||||
|
// twice!
|
||||||
|
DeclarationName Name;
|
||||||
|
if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
|
||||||
|
Name = ActualTemplate->getDeclName();
|
||||||
|
else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
|
||||||
|
Name = Ovl->getDeclName();
|
||||||
|
else
|
||||||
|
assert(false && "Cannot support dependent template names yet");
|
||||||
|
|
||||||
|
// Translate the parser's template argument list in our AST format.
|
||||||
|
llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
|
||||||
|
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
|
||||||
|
TemplateArgsIn.release();
|
||||||
|
|
||||||
|
// Do we have the save the actual template name? We might need it...
|
||||||
|
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, TemplateNameLoc,
|
||||||
|
Name, true, LAngleLoc,
|
||||||
|
TemplateArgs.data(), TemplateArgs.size(),
|
||||||
|
RAngleLoc, DeclPtrTy(), &SS);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Form a dependent template name.
|
/// \brief Form a dependent template name.
|
||||||
///
|
///
|
||||||
/// This action forms a dependent template name given the template
|
/// This action forms a dependent template name given the template
|
||||||
|
|
|
@ -2964,7 +2964,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
|
||||||
Qualifier
|
Qualifier
|
||||||
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
|
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
|
||||||
E->getQualifierRange());
|
E->getQualifierRange());
|
||||||
if (Qualifier == 0);
|
if (Qualifier == 0)
|
||||||
return SemaRef.ExprError();
|
return SemaRef.ExprError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ void test_X_f1_address() {
|
||||||
void test_X_f0_explicit(X x, int i, long l) {
|
void test_X_f0_explicit(X x, int i, long l) {
|
||||||
int &ir1 = x.f0<int>(i);
|
int &ir1 = x.f0<int>(i);
|
||||||
int &ir2 = x.f0<>(i);
|
int &ir2 = x.f0<>(i);
|
||||||
int &ir3 = x.f0<long>(i);
|
long &il1 = x.f0<long>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PR4608
|
// PR4608
|
||||||
|
|
Loading…
Reference in New Issue