[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