[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