[cfe-commits] r80646 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/AST/StmtPrinter.cpp lib/Frontend/PCHWriterStmt.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/TreeTransform.h test/SemaTemplate/member-function-template.cpp
Douglas Gregor
dgregor at apple.com
Mon Aug 31 17:37:14 PDT 2009
Author: dgregor
Date: Mon Aug 31 19:37:14 2009
New Revision: 80646
URL: http://llvm.org/viewvc/llvm-project?rev=80646&view=rev
Log:
Preliminary AST representation and semantic analysis for
explicitly-specified template argument lists in member reference
expressions, e.g.,
x->f<int>()
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaTemplate/member-function-template.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Aug 31 19:37:14 2009
@@ -1042,6 +1042,31 @@
/// \brief The source range covered by the nested name specifier.
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.
///
@@ -1061,9 +1086,17 @@
bool IsArrow : 1;
/// \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;
+ /// \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.
NameQualifier *getMemberQualifier() {
if (!HasQualifier)
@@ -1074,15 +1107,33 @@
/// \brief Retrieve the qualifier that preceded the member name, if any.
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 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,
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
- QualType ty);
+ bool has_explicit, SourceLocation langle,
+ const TemplateArgument *targs, unsigned numtargs,
+ SourceLocation rangle, QualType ty);
public:
MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
@@ -1090,7 +1141,7 @@
: Expr(MemberExprClass, ty,
base->isTypeDependent(), base->isValueDependent()),
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
- HasQualifier(false) {}
+ HasQualifier(false), HasExplicitTemplateArgumentList(false) {}
/// \brief Build an empty member reference expression.
explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { }
@@ -1098,7 +1149,13 @@
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual, SourceRange qualrange,
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; }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -1110,7 +1167,7 @@
NamedDecl *getMemberDecl() const { return MemberDecl; }
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.,
/// x->Base::foo.
bool hasQualifier() const { return HasQualifier; }
@@ -1134,6 +1191,48 @@
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; }
void setArrow(bool A) { IsArrow = A; }
@@ -1146,10 +1245,14 @@
virtual SourceRange getSourceRange() const {
// If we have an implicit base (like a C++ implicit this),
// make sure not to return its location
+ SourceLocation EndLoc = MemberLoc;
+ if (HasExplicitTemplateArgumentList)
+ EndLoc = getRAngleLoc();
+
SourceLocation BaseLoc = getBase()->getLocStart();
if (BaseLoc.isInvalid())
- return SourceRange(MemberLoc, MemberLoc);
- return SourceRange(BaseLoc, MemberLoc);
+ return SourceRange(MemberLoc, EndLoc);
+ return SourceRange(BaseLoc, EndLoc);
}
virtual SourceLocation getExprLoc() const { return MemberLoc; }
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Aug 31 19:37:14 2009
@@ -264,31 +264,58 @@
MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
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,
base->isTypeDependent() || (qual && qual->isDependent()),
base->isValueDependent() || (qual && qual->isDependent())),
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
- HasQualifier(qual != 0) {
+ HasQualifier(qual != 0), HasExplicitTemplateArgumentList(has_explicit) {
// Initialize the qualifier, if any.
if (HasQualifier) {
NameQualifier *NQ = getMemberQualifier();
NQ->NNS = qual;
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,
NestedNameSpecifier *qual,
SourceRange qualrange,
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);
if (qual != 0)
Size += sizeof(NameQualifier);
+ if (has_explicit)
+ Size += sizeof(ExplicitTemplateArgumentList) +
+ sizeof(TemplateArgument) * numtargs;
+
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);
}
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Aug 31 19:37:14 2009
@@ -743,6 +743,12 @@
Qualifier->print(OS, Policy);
OS << Node->getMemberDecl()->getNameAsString();
+
+ if (Node->hasExplicitTemplateArgumentList())
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
}
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
PrintExpr(Node->getBase());
Modified: cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterStmt.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterStmt.cpp Mon Aug 31 19:37:14 2009
@@ -416,6 +416,7 @@
Writer.AddSourceLocation(E->getMemberLoc(), Record);
Record.push_back(E->isArrow());
// FIXME: C++ nested-name-specifier
+ // FIXME: C++ template argument list
Code = pch::EXPR_MEMBER;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Aug 31 19:37:14 2009
@@ -1602,12 +1602,32 @@
SourceLocation LLoc,
ExprArg Idx,
SourceLocation RLoc);
+
+ OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceLocation MemberLoc,
+ DeclarationName MemberName,
+ 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);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 31 19:37:14 2009
@@ -885,7 +885,10 @@
if (SS && SS->isSet())
return MemberExpr::Create(C, Base, isArrow,
(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);
}
@@ -1980,6 +1983,11 @@
Sema::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 ObjCImpDecl, const CXXScopeSpec *SS) {
if (SS && SS->isInvalid())
return ExprError();
@@ -2153,14 +2161,34 @@
if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(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,
FunTmpl, MemberLoc,
Context.OverloadTy));
}
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,
Ovl, MemberLoc, Context.OverloadTy));
+ }
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS,
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Aug 31 19:37:14 2009
@@ -1831,21 +1831,6 @@
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)
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Aug 31 19:37:14 2009
@@ -4563,9 +4563,11 @@
AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/false);
else
- AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
- /*FIXME:*/false, /*FIXME:*/0,
- /*FIXME:*/0, ObjectArg, Args, NumArgs,
+ AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
+ MemExpr->hasExplicitTemplateArgumentList(),
+ MemExpr->getTemplateArgs(),
+ MemExpr->getNumTemplateArgs(),
+ ObjectArg, Args, NumArgs,
CandidateSet,
/*SuppressUsedConversions=*/false);
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Aug 31 19:37:14 2009
@@ -1084,6 +1084,41 @@
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.
///
/// This action forms a dependent template name given the template
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Aug 31 19:37:14 2009
@@ -2964,7 +2964,7 @@
Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange());
- if (Qualifier == 0);
+ if (Qualifier == 0)
return SemaRef.ExprError();
}
Modified: cfe/trunk/test/SemaTemplate/member-function-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-function-template.cpp?rev=80646&r1=80645&r2=80646&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/member-function-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-function-template.cpp Mon Aug 31 19:37:14 2009
@@ -43,7 +43,7 @@
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);
+ long &il1 = x.f0<long>(i);
}
// PR4608
More information about the cfe-commits
mailing list