diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2010-09-03 01:26:16 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2010-09-03 01:26:16 +0000 |
commit | be74740cc246ce08d42804a684385a42eb814edb (patch) | |
tree | 1fda5a03d04b57d582ef7a9f2f5efcfcbfae964d | |
parent | 4938f2385f82e54df019b2fb1128a58ebad98bec (diff) |
Patch to allow alternative representation of c++
operators (and, or, etc.) to be used as selectors
to match g++'s behavior.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112935 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Lex/Token.h | 10 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 57 | ||||
-rw-r--r-- | test/SemaObjCXX/cxxoperator-selector.mm | 24 |
4 files changed, 92 insertions, 3 deletions
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index bd9b46869a..dc4acd46e2 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -76,7 +76,9 @@ public: StartOfLine = 0x01, // At start of line or only after whitespace. LeadingSpace = 0x02, // Whitespace exists before this token. DisableExpand = 0x04, // This identifier may never be macro expanded. - NeedsCleaning = 0x08 // Contained an escaped newline or trigraph. + NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. + CPlusPlusOpKeyword = 0x10 // alternative representation of + // a C++ operator in objc selectors. }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } @@ -231,6 +233,12 @@ public: /// newlines in it. /// bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; } + + /// isCPlusPlusOpKeyword - Return true if this token is an operator + /// for C++ operator keywords. + bool isCPlusPlusOpKeyword() const + { return (Flags & CPlusPlusOpKeyword) ? true : false; } + }; /// PPConditionalInfo - Information about the conditional stack (#if directives) diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 5160acf19e..05621d31b3 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -613,8 +613,10 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { // C++ 2.11p2: If this is an alternative representation of a C++ operator, // then we act as if it is the actual operator and not the textual // representation of it. - if (II.isCPlusPlusOperatorKeyword()) + if (II.isCPlusPlusOperatorKeyword()) { Identifier.setIdentifierInfo(0); + Identifier.setFlag(Token::CPlusPlusOpKeyword); + } // If this is an extension token, diagnose its use. // We avoid diagnosing tokens that originate from macro definitions. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index c36f09c881..8d7d67ed8d 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -553,6 +553,60 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl, MatchRHSPunctuation(tok::r_paren, LHSLoc); } +static void ConvertCPlusPlusOperatorToken(Preprocessor &PP, Token &Tok) { + if (!Tok.isCPlusPlusOpKeyword()) + return; + + switch (Tok.getKind()) { + case tok::ampamp: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("and")); + Tok.setKind(tok::identifier); + return; + case tok::ampequal: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("and_eq")); + Tok.setKind(tok::identifier); + return; + case tok::amp: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("bitand")); + Tok.setKind(tok::identifier); + return; + case tok::pipe: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("pipe")); + Tok.setKind(tok::identifier); + return; + case tok::tilde: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("compl")); + Tok.setKind(tok::identifier); + return; + case tok::exclaim: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("not")); + Tok.setKind(tok::identifier); + return; + case tok::exclaimequal: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("not_eq")); + Tok.setKind(tok::identifier); + return; + case tok::pipepipe: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("or")); + Tok.setKind(tok::identifier); + return; + case tok::pipeequal: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("or_eq")); + Tok.setKind(tok::identifier); + return; + case tok::caret: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("xor")); + Tok.setKind(tok::identifier); + return; + case tok::caretequal: + Tok.setIdentifierInfo(&PP.getIdentifierTable().get("xor_eq")); + Tok.setKind(tok::identifier); + return; + default: + return; + } +} + /// objc-method-proto: /// objc-instance-method objc-method-decl objc-method-attributes[opt] /// objc-class-method objc-method-decl objc-method-attributes[opt] @@ -569,7 +623,6 @@ Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, tok::TokenKind methodType = Tok.getKind(); SourceLocation mLoc = ConsumeToken(); - Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind); // Since this rule is used for both method declarations and definitions, // the caller is (optionally) responsible for consuming the ';'. @@ -585,6 +638,8 @@ Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, /// in out inout bycopy byref oneway int char float double void _Bool /// IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { + ConvertCPlusPlusOperatorToken(PP, Tok); + switch (Tok.getKind()) { default: return 0; diff --git a/test/SemaObjCXX/cxxoperator-selector.mm b/test/SemaObjCXX/cxxoperator-selector.mm new file mode 100644 index 0000000000..6dd36a8c10 --- /dev/null +++ b/test/SemaObjCXX/cxxoperator-selector.mm @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar:// 8328250 + +@class NSDate; + +@interface XSGraphDataSet +- and; +- xor; +- or; + +- ||; // expected-error {{expected selector for Objective-C method}} + +- &&; // expected-error {{expected selector for Objective-C method}} + +- (void)dataSetForValuesBetween:(NSDate *)startDate and:(NSDate *)endDate; +@end + +@implementation XSGraphDataSet +- (id) and{return 0; }; +- (id) xor{return 0; }; +- (id) or{return 0; }; + +- (void)dataSetForValuesBetween:(NSDate *)startDate and:(NSDate *)endDate { return; } +@end |