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).
OpKind, Tok.getLocation(),
*Tok.getIdentifierInfo(),
ObjCImpDecl, &SS);
+ ConsumeToken();
} else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
// We have a C++ pseudo-destructor.
ConsumeToken();
if (!Tok.is(tok::identifier)) {
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
Diag(Tok, diag::err_expected_ident);
return ExprError();
}
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 '++'
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.
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)
--- /dev/null
+// 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'}}
+}
--- /dev/null
+// 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'}}
+}