[cfe-commits] r80608 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseExpr.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp test/SemaCXX/invalid-member-expr.cpp test/SemaCXX/member-operator-expr.cpp

Douglas Gregor dgregor at apple.com
Mon Aug 31 12:52:14 PDT 2009


Author: dgregor
Date: Mon Aug 31 14:52:13 2009
New Revision: 80608

URL: http://llvm.org/viewvc/llvm-project?rev=80608&view=rev
Log:
Support explicit C++ member operator syntax, from James Porter!

Added:
    cfe/trunk/test/SemaCXX/invalid-member-expr.cpp
    cfe/trunk/test/SemaCXX/member-operator-expr.cpp
Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=80608&r1=80607&r2=80608&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Aug 31 14:52:13 2009
@@ -1292,6 +1292,34 @@
                                const CXXScopeSpec *SS = 0) {
     return ExprEmpty();
   }
+
+  /// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
+  /// reference, for example:
+  ///
+  /// t.operator++();
+  virtual OwningExprResult
+  ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       SourceLocation ClassNameLoc,
+                                       OverloadedOperatorKind OverOpKind,
+                                       const CXXScopeSpec *SS = 0) {
+    return ExprEmpty();
+  }
+
+  /// ActOnConversionOperatorReferenceExpr - Parsed an overloaded conversion
+  /// function reference, for example:
+  ///
+  /// t.operator int();
+  virtual OwningExprResult
+  ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       SourceLocation ClassNameLoc,
+                                       TypeTy *Ty,
+                                       const CXXScopeSpec *SS = 0) {
+    return ExprEmpty();
+  }
   
   /// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
   /// (C++ [intro.execution]p12).

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=80608&r1=80607&r2=80608&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Aug 31 14:52:13 2009
@@ -939,6 +939,7 @@
                                                  OpKind, Tok.getLocation(),
                                                  *Tok.getIdentifierInfo(),
                                                  ObjCImpDecl, &SS);
+        ConsumeToken();
       } else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
         // We have a C++ pseudo-destructor.
         
@@ -946,6 +947,8 @@
         ConsumeToken();
         
         if (!Tok.is(tok::identifier)) {
+          if (getLang().CPlusPlus)
+            Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
           Diag(Tok, diag::err_expected_ident);
           return ExprError();
         }
@@ -956,15 +959,39 @@
                                                      Tok.getLocation(), 
                                                      Tok.getIdentifierInfo(),
                                                      &SS);
+        ConsumeToken();
+      } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
+        if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
+          if (!LHS.isInvalid())
+            LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
+                                                               move(LHS), OpLoc,
+                                                               OpKind,
+                                                           Tok.getLocation(),
+                                                               Op, &SS);
+          // TryParseOperatorFunctionId already consumed our token, so
+          // don't bother
+        } else if (TypeTy *ConvType = ParseConversionFunctionId()) {
+          if (!LHS.isInvalid())
+            LHS = Actions.ActOnConversionOperatorReferenceExpr(CurScope,
+                                                               move(LHS), OpLoc,
+                                                               OpKind,
+                                                           Tok.getLocation(),
+                                                               ConvType, &SS);
+        } else {
+          if (getLang().CPlusPlus)
+            Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
+          // Don't emit a diagnostic; ParseConversionFunctionId does it for us
+          return ExprError();
+        }
       } else {
+        if (getLang().CPlusPlus)
+          Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
         Diag(Tok, diag::err_expected_ident);
         return ExprError();
       }
 
       if (getLang().CPlusPlus)
         Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
-
-      ConsumeToken();
       break;
     }
     case tok::plusplus:    // postfix-expression: postfix-expression '++'

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80608&r1=80607&r2=80608&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Aug 31 14:52:13 2009
@@ -1956,6 +1956,21 @@
                                SourceLocation ClassNameLoc,
                                IdentifierInfo *ClassName,
                                const CXXScopeSpec *SS = 0);
+
+  virtual OwningExprResult
+  ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       SourceLocation ClassNameLoc,
+                                       OverloadedOperatorKind OverOpKind,
+                                       const CXXScopeSpec *SS = 0);
+  virtual OwningExprResult
+  ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       SourceLocation ClassNameLoc,
+                                       TypeTy *Ty,
+                                       const CXXScopeSpec *SS = 0);
   
   /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is 
   /// non-empty, will create a new CXXExprWithTemporaries expression.

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=80608&r1=80607&r2=80608&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Aug 31 14:52:13 2009
@@ -1794,6 +1794,43 @@
                                   DtorName, DeclPtrTy(), SS);
 }
 
+Sema::OwningExprResult
+Sema::ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
+                                           SourceLocation OpLoc,
+                                           tok::TokenKind OpKind,
+                                           SourceLocation ClassNameLoc,
+                                           OverloadedOperatorKind OverOpKind,
+                                           const CXXScopeSpec *SS) {
+  if (SS && SS->isInvalid())
+    return ExprError();
+
+  DeclarationName Name =
+    Context.DeclarationNames.getCXXOperatorName(OverOpKind);
+
+  return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
+                                  Name, DeclPtrTy(), SS);
+}
+
+Sema::OwningExprResult
+Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
+                                           SourceLocation OpLoc,
+                                           tok::TokenKind OpKind,
+                                           SourceLocation ClassNameLoc,
+                                           TypeTy *Ty,
+                                           const CXXScopeSpec *SS) {
+  if (SS && SS->isInvalid())
+    return ExprError();
+
+  //FIXME: Preserve type source info.
+  QualType ConvType = GetTypeFromParser(Ty);
+  CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
+  DeclarationName ConvName =
+    Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
+
+  return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
+                                  ConvName, DeclPtrTy(), SS);
+}
+
 Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
   Expr *FullExpr = Arg.takeAs<Expr>();
   if (FullExpr)

Added: cfe/trunk/test/SemaCXX/invalid-member-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/invalid-member-expr.cpp?rev=80608&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/invalid-member-expr.cpp (added)
+++ cfe/trunk/test/SemaCXX/invalid-member-expr.cpp Mon Aug 31 14:52:13 2009
@@ -0,0 +1,21 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class X {};
+
+void test() {
+  X x;
+
+  x.int; // expected-error{{expected identifier}}
+  x.~int(); // expected-error{{expected identifier}}
+  x.operator; // expected-error{{missing type specifier after 'operator'}}
+  x.operator typedef; // expected-error{{missing type specifier after 'operator'}}
+}
+
+void test2() {
+  X *x;
+
+  x->int; // expected-error{{expected identifier}}
+  x->~int(); // expected-error{{expected identifier}}
+  x->operator; // expected-error{{missing type specifier after 'operator'}}
+  x->operator typedef; // expected-error{{missing type specifier after 'operator'}}
+}

Added: cfe/trunk/test/SemaCXX/member-operator-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-operator-expr.cpp?rev=80608&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/member-operator-expr.cpp (added)
+++ cfe/trunk/test/SemaCXX/member-operator-expr.cpp Mon Aug 31 14:52:13 2009
@@ -0,0 +1,29 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class X {
+public:
+  int operator++();
+  operator int();
+};
+
+void test() {
+  X x;
+  int i;
+
+  i = x.operator++();
+  i = x.operator int();
+  x.operator--(); // expected-error{{no member named 'operator--'}}
+  x.operator float(); // expected-error{{no member named 'operator float'}}
+  x.operator; // expected-error{{missing type specifier after 'operator'}}
+}
+
+void test2() {
+  X *x;
+  int i;
+
+  i = x->operator++();
+  i = x->operator int();
+  x->operator--(); // expected-error{{no member named 'operator--'}}
+  x->operator float(); // expected-error{{no member named 'operator float'}}
+  x->operator; // expected-error{{missing type specifier after 'operator'}}
+}





More information about the cfe-commits mailing list