]> granicus.if.org Git - clang/commitdiff
Add parsing for references to member function templates with explicit
authorDouglas Gregor <dgregor@apple.com>
Mon, 31 Aug 2009 21:16:32 +0000 (21:16 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 31 Aug 2009 21:16:32 +0000 (21:16 +0000)
template argument lists, e.g., x.f<int>().

Semantic analysis will be a separate commit.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80624 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Action.h
lib/Parse/ParseExpr.cpp
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
test/SemaTemplate/member-function-template.cpp

index f3364352aa4ceb7728fea1f47f2e8b76f2f12e88..0c70441083da710d25f11c14cb2bc2c97883356a 100644 (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) {
index d00d6d2e33d95a403619d09419d027a9913fc0f9..36b6dd4a930e49bacfcf55a1eb05b5027f538ca7 100644 (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);
index 2a2515ff1142bcfe7958c35b64c24860156d96d9..ce56eb46379f9de27b2f560d0cf388336b97ca73 100644 (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.
index f304ac30945c8df48a1a02c88aac4ba85a118033..026ff43d2d24a53b2f20716e7c3a43e9a50c66c8 100644 (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);
   }
index 35938260c6564f9b9579eaf1af7cb343c868e7de..dc58ecc16c7d7cfb0dd6687d91cfae3cf184e3fd 100644 (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)
index 91eb53beffc101feeb6d4624761a5757083b77e3..087f3952aba3b84a3291c1c16886405f744f6fa1 100644 (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; };