]> granicus.if.org Git - clang/commitdiff
Patch to allow alternative representation of c++
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 3 Sep 2010 01:26:16 +0000 (01:26 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 3 Sep 2010 01:26:16 +0000 (01:26 +0000)
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

include/clang/Lex/Token.h
lib/Lex/Preprocessor.cpp
lib/Parse/ParseObjc.cpp
test/SemaObjCXX/cxxoperator-selector.mm [new file with mode: 0644]

index bd9b46869a35d5d788380c5cd552fd14aa6a2a86..dc4acd46e29ed0806a5deca07365126711d7cdea 100644 (file)
@@ -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)
index 5160acf19e1f4bad27e7618ba088ee73fdeab85d..05621d31b3f4f8a84254d99890e6f5dd36ba07e7 100644 (file)
@@ -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.
index c36f09c881a205a9424c63808c65692b75d61b9d..8d7d67ed8d4f0f96b2815022d272f39f95a3107c 100644 (file)
@@ -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 (file)
index 0000000..6dd36a8
--- /dev/null
@@ -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