Parsing, ASTs, and semantic analysis for the declaration of overloaded
operators in C++. Overloaded operators can be called directly via
their operator-function-ids, e.g., "operator+(foo, bar)", but we don't
yet implement the semantics of operator overloading to handle, e.g.,
"foo + bar".



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58817 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e1fbb6d..0b30631 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1305,6 +1305,15 @@
 
     if (TypeTy *Type = ParseClassName())
       D.SetDestructor(Type, II, TildeLoc);
+  } else if (Tok.is(tok::kw_operator)) {
+    SourceLocation OperatorLoc = Tok.getLocation();
+
+    // First try the name of an overloaded operator
+    if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) {
+      D.SetIdentifier(II, OperatorLoc);
+    } else {
+      // This must be a user-defined conversion.
+    }
   } else if (Tok.is(tok::l_paren)) {
     // direct-declarator: '(' declarator ')'
     // direct-declarator: '(' attributes declarator ')'
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b737695..49c28ee 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -356,7 +356,8 @@
 /// [GNU]   '__extension__'  '__real'  '__imag'
 ///
 ///       primary-expression: [C99 6.5.1]
-///         identifier
+/// [C99]   identifier
+//  [C++]   id-expression
 ///         constant
 ///         string-literal
 /// [C++]   boolean-literal  [C++ 2.13.5]
@@ -390,6 +391,16 @@
 ///         enumeration-constant -> identifier
 ///         character-constant
 ///
+///       id-expression: [C++ 5.1]
+///                   unqualified-id
+///                   qualified-id           [TODO]
+///
+///       unqualified-id: [C++ 5.1]
+///                   identifier
+///                   operator-function-id
+///                   conversion-function-id [TODO]
+///                   '~' class-name         [TODO]
+///                   template-id            [TODO]
 Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
   ExprResult Res;
   tok::TokenKind SavedKind = Tok.getKind();
@@ -461,6 +472,7 @@
     }
     
     // primary-expression: identifier
+    // unqualified-id: identifier
     // constant: enumeration-constant
 
     // Consume the identifier so that we can see if it is followed by a '('.
@@ -589,6 +601,17 @@
     return ParsePostfixExpressionSuffix(Res);
   }
 
+  case tok::kw_operator: {
+    SourceLocation OperatorLoc = Tok.getLocation();
+    if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) {
+      Res = Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II, 
+                                        Tok.is(tok::l_paren));
+      // These can be followed by postfix-expr pieces.
+      return ParsePostfixExpressionSuffix(Res);
+    }
+    break;
+  }
+
   case tok::at: {
     SourceLocation AtLoc = ConsumeToken();
     return ParseObjCAtExpression(AtLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 2b9ab55..fcb229b 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -291,3 +291,78 @@
   ConsumeToken();
   DS.Finish(Diags, PP.getSourceManager(), getLang());
 }
+
+/// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded
+/// operator name (C++ [over.oper]). If successful, returns the
+/// predefined identifier that corresponds to that overloaded
+/// operator. Otherwise, returns NULL and does not consume any tokens.
+///
+///       operator-function-id: [C++ 13.5]
+///         'operator' operator
+///
+/// operator: one of
+///            new   delete  new[]   delete[]
+///            +     -    *  /    %  ^    &   |   ~
+///            !     =    <  >    += -=   *=  /=  %=
+///            ^=    &=   |= <<   >> >>= <<=  ==  !=
+///            <=    >=   && ||   ++ --   ,   ->* ->
+///            ()    []
+IdentifierInfo *Parser::MaybeParseOperatorFunctionId() {
+  if (Tok.isNot(tok::kw_operator))
+    return 0;
+
+  OverloadedOperatorKind Op = OO_None;
+  switch (NextToken().getKind()) {
+  case tok::kw_new:
+    ConsumeToken(); // 'operator'
+    ConsumeToken(); // 'new'
+    if (Tok.is(tok::l_square)) {
+      ConsumeBracket(); // '['
+      ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
+      Op = OO_Array_New;
+    } else {
+      Op = OO_New;
+    }
+    return &PP.getIdentifierTable().getOverloadedOperator(Op);
+
+  case tok::kw_delete:
+    ConsumeToken(); // 'operator'
+    ConsumeToken(); // 'delete'
+    if (Tok.is(tok::l_square)) {
+      ConsumeBracket(); // '['
+      ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
+      Op = OO_Array_Delete;
+    } else {
+      Op = OO_Delete;
+    }
+    return &PP.getIdentifierTable().getOverloadedOperator(Op);
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token) \
+    case tok::Token:  Op = OO_##Name; break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling)
+#include "clang/Basic/OperatorKinds.def"
+
+  case tok::l_paren:
+    ConsumeToken(); // 'operator'
+    ConsumeParen(); // '('
+    ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
+    return &PP.getIdentifierTable().getOverloadedOperator(OO_Call);
+
+  case tok::l_square:
+    ConsumeToken(); // 'operator'
+    ConsumeBracket(); // '['
+    ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
+    return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript);
+
+  default:
+    break;
+  }
+
+  if (Op == OO_None)
+    return 0;
+  else {
+    ExpectAndConsume(tok::kw_operator, diag::err_expected_operator);
+    ConsumeAnyToken(); // the operator itself
+    return &PP.getIdentifierTable().getOverloadedOperator(Op);
+  }
+}