[cfe-commits] r58986 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Basic/OperatorKinds.def include/clang/Basic/OperatorKinds.h lib/Basic/IdentifierTable.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/SemaDeclCXX.cpp

Douglas Gregor doug.gregor at gmail.com
Mon Nov 10 05:38:23 PST 2008


Author: dgregor
Date: Mon Nov 10 07:38:07 2008
New Revision: 58986

URL: http://llvm.org/viewvc/llvm-project?rev=58986&view=rev
Log:
Some cleanups to the declaration/checking of overloaded operators in C++. Thanks to Sebastian for the review

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Basic/OperatorKinds.def
    cfe/trunk/include/clang/Basic/OperatorKinds.h
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=58986&r1=58985&r2=58986&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Nov 10 07:38:07 2008
@@ -1316,15 +1316,27 @@
 DIAG(err_operator_overload_default_arg, ERROR,
      "a parameter of an overloaded operator cannot have a default argument")
 DIAG(err_operator_overload_must_be_unary, ERROR,
-     "overloaded operator '%0' must be a unary operator (has %1 parameter%2)")
+     "overloaded operator '%0' must be a unary operator (has %1 parameter)")
 DIAG(err_operator_overload_must_be_binary, ERROR,
-     "overloaded operator '%0' must be a binary operator (has %1 parameter%2)")
+     "overloaded operator '%0' must be a binary operator (has %1 parameter)")
 DIAG(err_operator_overload_must_be_unary_or_binary, ERROR,
-     "overloaded operator '%0' must be a unary or binary operator (has %1 parameter%2)")
+     "overloaded operator '%0' must be a unary or binary operator (has %1 parameter)")
+DIAG(err_operator_overload_must_be_unary_plural, ERROR,
+     "overloaded operator '%0' must be a unary operator (has %1 parameters)")
+DIAG(err_operator_overload_must_be_binary_plural, ERROR,
+     "overloaded operator '%0' must be a binary operator (has %1 parameters)")
+DIAG(err_operator_overload_must_be_unary_or_binary_plural, ERROR,
+     "overloaded operator '%0' must be a unary or binary operator (has %1 parameters)")
 DIAG(err_operator_overload_must_be_member, ERROR,
      "overloaded operator '%0' must be a non-static member function")
-DIAG(err_operator_overload_post_incdec_must_be_int, ERROR,
-     "%0parameter of overloaded post-%1 operator must have type 'int' (not '%2')")
+DIAG(err_operator_overload_post_inc_must_be_int, ERROR,
+     "second parameter of overloaded post-increment operator must have type 'int' (not '%0')")
+DIAG(err_operator_overload_post_dec_must_be_int, ERROR,
+     "second parameter of overloaded post-decrement operator must have type 'int' (not '%0')")
+DIAG(err_operator_overload_post_inc_must_be_int_member, ERROR,
+     "parameter of overloaded post-increment operator must have type 'int' (not '%0')")
+DIAG(err_operator_overload_post_dec_must_be_int_member, ERROR,
+     "parameter of overloaded post-decrement operator must have type 'int' (not '%0')")
 DIAG(err_operator_missing_type_specifier, ERROR,
      "missing type specifier after 'operator'")
 

Modified: cfe/trunk/include/clang/Basic/OperatorKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OperatorKinds.def?rev=58986&r1=58985&r2=58986&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/OperatorKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OperatorKinds.def Mon Nov 10 07:38:07 2008
@@ -11,58 +11,93 @@
 // all of the overloadable C++ operators.
 //
 //===----------------------------------------------------------------------===//
+//
+/// @file OperatorKinds.def
+///
+/// In this file, each of the overloadable C++ operators is enumerated
+/// with either the OVERLOADED_OPERATOR or OVERLOADED_OPERATOR_MULTI
+/// macro, each of which can be specified by the code including this
+/// file. OVERLOADED_OPERATOR is used for single-token operators
+/// (e.g., "+"), and has six arguments:
+///
+/// Name: The name of the token. OO_Name will be the name of the
+/// corresponding enumerator in OverloadedOperatorKind in
+/// OperatorKinds.h.
+///
+/// Spelling: A string that provides a canonical spelling for the
+/// operator, e.g., "operator+".
+///
+/// Token: The name of the token that specifies the operator, e.g.,
+/// "plus" for operator+ or "greatergreaterequal" for
+/// "operator>>=". With a "kw_" prefix, the token name can be used as
+/// an enumerator into the TokenKind enumeration.
+///
+/// Unary: True if the operator can be declared as a unary operator.
+///
+/// Binary: True if the operator can be declared as a binary
+/// operator. Note that some operators (e.g., "operator+" and
+/// "operator*") can be both unary and binary.
+///
+/// MemberOnly: True if this operator can only be declared as a
+/// non-static member function. False if the operator can be both a
+/// non-member function and a non-static member function.
+///
+/// OVERLOADED_OPERATOR_MULTI is used to enumerate the multi-token
+/// overloaded operator names, e.g., "operator delete []". The macro
+/// has all of the parameters of OVERLOADED_OPERATOR except Token,
+/// which is omitted.
 
 #ifndef OVERLOADED_OPERATOR
-#  define OVERLOADED_OPERATOR(Name,Spelling,Token)
+#  define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)
 #endif
 
 #ifndef OVERLOADED_OPERATOR_MULTI
-#  define OVERLOADED_OPERATOR_MULTI(Name,Spelling) \
-     OVERLOADED_OPERATOR(Name,Spelling,unknown)
+#  define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) \
+    OVERLOADED_OPERATOR(Name,Spelling,unknown,Unary,Binary,MemberOnly)
 #endif
 
-OVERLOADED_OPERATOR_MULTI(New            , "operator new")
-OVERLOADED_OPERATOR_MULTI(Delete         , "operator delete")
-OVERLOADED_OPERATOR_MULTI(Array_New      , "operator new[]")
-OVERLOADED_OPERATOR_MULTI(Array_Delete   , "operator delete[]")
-OVERLOADED_OPERATOR(Plus                 , "operator+"   , plus)
-OVERLOADED_OPERATOR(Minus                , "operator-"   , minus)
-OVERLOADED_OPERATOR(Star                 , "operator*"   , star)
-OVERLOADED_OPERATOR(Slash                , "operator/"   , slash)
-OVERLOADED_OPERATOR(Percent              , "operator%"   , percent)
-OVERLOADED_OPERATOR(Caret                , "operator^"   , caret)
-OVERLOADED_OPERATOR(Amp                  , "operator&"   , amp)
-OVERLOADED_OPERATOR(Pipe                 , "operator|"   , pipe)
-OVERLOADED_OPERATOR(Tilde                , "operator~"   , tilde)
-OVERLOADED_OPERATOR(Exclaim              , "operator!"   , exclaim)
-OVERLOADED_OPERATOR(Equal                , "operator="   , equal)
-OVERLOADED_OPERATOR(Less                 , "operator<"   , less)
-OVERLOADED_OPERATOR(Greater              , "operator>"   , greater)
-OVERLOADED_OPERATOR(PlusEqual            , "operator+="  , plusequal)
-OVERLOADED_OPERATOR(MinusEqual           , "operator-="  , minusequal)
-OVERLOADED_OPERATOR(StarEqual            , "operator*="  , starequal)
-OVERLOADED_OPERATOR(SlashEqual           , "operator/="  , slashequal)
-OVERLOADED_OPERATOR(PercentEqual         , "operator%="  , percentequal)
-OVERLOADED_OPERATOR(CaretEqual           , "operator^="  , caretequal)
-OVERLOADED_OPERATOR(AmpEqual             , "operator&="  , ampequal)
-OVERLOADED_OPERATOR(PipeEqual            , "operator|="  , pipeequal)
-OVERLOADED_OPERATOR(LessLess             , "operator<<"  , lessless)
-OVERLOADED_OPERATOR(GreaterGreater       , "operator>>"  , greatergreater)
-OVERLOADED_OPERATOR(LessLessEqual        , "operator<<=" , lesslessequal)
-OVERLOADED_OPERATOR(GreaterGreaterEqual  , "operator>>=" , greatergreaterequal)
-OVERLOADED_OPERATOR(EqualEqual           , "operator=="  , equalequal)
-OVERLOADED_OPERATOR(ExclaimEqual         , "operator!="  , exclaimequal)
-OVERLOADED_OPERATOR(LessEqual            , "operator<="  , lessequal)
-OVERLOADED_OPERATOR(GreaterEqual         , "operator>="  , greaterequal)
-OVERLOADED_OPERATOR(AmpAmp               , "operator&&"  , ampamp)
-OVERLOADED_OPERATOR(PipePipe             , "operator||"  , pipepipe)
-OVERLOADED_OPERATOR(PlusPlus             , "operator++"  , plusplus)
-OVERLOADED_OPERATOR(MinusMinus           , "operator--"  , minusminus)
-OVERLOADED_OPERATOR(Comma                , "operator,"   , comma)
-OVERLOADED_OPERATOR(ArrowStar            , "operator->*" , arrowstar)
-OVERLOADED_OPERATOR(Arrow                , "operator->"  , arrow)
-OVERLOADED_OPERATOR_MULTI(Call           , "operator()")
-OVERLOADED_OPERATOR_MULTI(Subscript      , "operator[]")
+OVERLOADED_OPERATOR_MULTI(New            , "operator new"                     , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Delete         , "operator delete"                  , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_New      , "operator new[]"                   , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_Delete   , "operator delete[]"                , true , true , false)
+OVERLOADED_OPERATOR(Plus                 , "operator+"   , plus               , true , true , false)
+OVERLOADED_OPERATOR(Minus                , "operator-"   , minus              , true , true , false)
+OVERLOADED_OPERATOR(Star                 , "operator*"   , star               , true , true , false)
+OVERLOADED_OPERATOR(Slash                , "operator/"   , slash              , false, true , false)
+OVERLOADED_OPERATOR(Percent              , "operator%"   , percent            , false, true , false)
+OVERLOADED_OPERATOR(Caret                , "operator^"   , caret              , false, true , false)
+OVERLOADED_OPERATOR(Amp                  , "operator&"   , amp                , true , true , false)
+OVERLOADED_OPERATOR(Pipe                 , "operator|"   , pipe               , false, true , false)
+OVERLOADED_OPERATOR(Tilde                , "operator~"   , tilde              , true , false, false)
+OVERLOADED_OPERATOR(Exclaim              , "operator!"   , exclaim            , true , false, false)
+OVERLOADED_OPERATOR(Equal                , "operator="   , equal              , false, true , true)
+OVERLOADED_OPERATOR(Less                 , "operator<"   , less               , false, true , false)
+OVERLOADED_OPERATOR(Greater              , "operator>"   , greater            , false, true , false)
+OVERLOADED_OPERATOR(PlusEqual            , "operator+="  , plusequal          , false, true , false)
+OVERLOADED_OPERATOR(MinusEqual           , "operator-="  , minusequal         , false, true , false)
+OVERLOADED_OPERATOR(StarEqual            , "operator*="  , starequal          , false, true , false)
+OVERLOADED_OPERATOR(SlashEqual           , "operator/="  , slashequal         , false, true , false)
+OVERLOADED_OPERATOR(PercentEqual         , "operator%="  , percentequal       , false, true , false)
+OVERLOADED_OPERATOR(CaretEqual           , "operator^="  , caretequal         , false, true , false)
+OVERLOADED_OPERATOR(AmpEqual             , "operator&="  , ampequal           , false, true , false)
+OVERLOADED_OPERATOR(PipeEqual            , "operator|="  , pipeequal          , false, true , false)
+OVERLOADED_OPERATOR(LessLess             , "operator<<"  , lessless           , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreater       , "operator>>"  , greatergreater     , false, true , false)
+OVERLOADED_OPERATOR(LessLessEqual        , "operator<<=" , lesslessequal      , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreaterEqual  , "operator>>=" , greatergreaterequal, false, true , false)
+OVERLOADED_OPERATOR(EqualEqual           , "operator=="  , equalequal         , false, true , false)
+OVERLOADED_OPERATOR(ExclaimEqual         , "operator!="  , exclaimequal       , false, true , false)
+OVERLOADED_OPERATOR(LessEqual            , "operator<="  , lessequal          , false, true , false)
+OVERLOADED_OPERATOR(GreaterEqual         , "operator>="  , greaterequal       , false, true , false)
+OVERLOADED_OPERATOR(AmpAmp               , "operator&&"  , ampamp             , false, true , false)
+OVERLOADED_OPERATOR(PipePipe             , "operator||"  , pipepipe           , false, true , false)
+OVERLOADED_OPERATOR(PlusPlus             , "operator++"  , plusplus           , true , true , false)
+OVERLOADED_OPERATOR(MinusMinus           , "operator--"  , minusminus         , true , true , false)
+OVERLOADED_OPERATOR(Comma                , "operator,"   , comma              , false, true , false)
+OVERLOADED_OPERATOR(ArrowStar            , "operator->*" , arrowstar          , false, true , false)
+OVERLOADED_OPERATOR(Arrow                , "operator->"  , arrow              , true , false, true)
+OVERLOADED_OPERATOR_MULTI(Call           , "operator()"                       , true , true , true)
+OVERLOADED_OPERATOR_MULTI(Subscript      , "operator[]"                       , false, true , true)
 
 #undef OVERLOADED_OPERATOR_MULTI
 #undef OVERLOADED_OPERATOR

Modified: cfe/trunk/include/clang/Basic/OperatorKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OperatorKinds.h?rev=58986&r1=58985&r2=58986&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/OperatorKinds.h (original)
+++ cfe/trunk/include/clang/Basic/OperatorKinds.h Mon Nov 10 07:38:07 2008
@@ -20,7 +20,8 @@
 /// C++ overloaded operators.
 enum OverloadedOperatorKind {
   OO_None,                //< Not an overloaded operator
-#define OVERLOADED_OPERATOR(Name,Spelling,Token) OO_##Name,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+  OO_##Name,
 #include "clang/Basic/OperatorKinds.def"
   NUM_OVERLOADED_OPERATORS
 };

Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=58986&r1=58985&r2=58986&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Mon Nov 10 07:38:07 2008
@@ -165,7 +165,7 @@
 /// AddOverloadedOperators - Register the name of all C++ overloadable
 /// operators ("operator+", "operator[]", etc.)
 void IdentifierTable::AddOverloadedOperators() {
-#define OVERLOADED_OPERATOR(Name,Spelling,Token)                        \
+#define OVERLOADED_OPERATOR(Name,Spelling,Token, Unary, Binary, MemberOnly) \
   OverloadedOperators[OO_##Name] = &get(Spelling);                      \
   OverloadedOperators[OO_##Name]->setOverloadedOperatorID(OO_##Name);
 #include "clang/Basic/OperatorKinds.def"

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=58986&r1=58985&r2=58986&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Nov 10 07:38:07 2008
@@ -515,9 +515,9 @@
     }
     return &PP.getIdentifierTable().getOverloadedOperator(Op);
 
-#define OVERLOADED_OPERATOR(Name,Spelling,Token) \
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)  \
     case tok::Token:  Op = OO_##Name; break;
-#define OVERLOADED_OPERATOR_MULTI(Name,Spelling)
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
 #include "clang/Basic/OperatorKinds.def"
 
   case tok::l_paren:

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=58986&r1=58985&r2=58986&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov 10 07:38:07 2008
@@ -1801,83 +1801,16 @@
     }
   }
 
-  bool CanBeUnaryOperator = false;
-  bool CanBeBinaryOperator = false;
-  bool MustBeMemberOperator = false;
-
-  switch (Op) {
-  case OO_New:
-  case OO_Delete:
-  case OO_Array_New:
-  case OO_Array_Delete:
-    assert(false && "Operators new, new[], delete, and delete[] handled above");
-    return true;
-
-  // Unary-only operators
-  case OO_Arrow:
-    MustBeMemberOperator = true;
-    // Fall through
-
-  case OO_Tilde:
-  case OO_Exclaim:
-    CanBeUnaryOperator = true;
-    break;
-
-  // Binary-only operators
-  case OO_Equal:
-  case OO_Subscript:
-    MustBeMemberOperator = true;
-    // Fall through
-
-  case OO_Slash:
-  case OO_Percent:
-  case OO_Caret:
-  case OO_Pipe:
-  case OO_Less:
-  case OO_Greater:
-  case OO_PlusEqual:
-  case OO_MinusEqual:
-  case OO_StarEqual:
-  case OO_SlashEqual:
-  case OO_PercentEqual:
-  case OO_CaretEqual:
-  case OO_AmpEqual:
-  case OO_PipeEqual:
-  case OO_LessLess:
-  case OO_GreaterGreater:
-  case OO_LessLessEqual:
-  case OO_GreaterGreaterEqual:
-  case OO_EqualEqual:
-  case OO_ExclaimEqual:
-  case OO_LessEqual:
-  case OO_GreaterEqual:
-  case OO_AmpAmp:
-  case OO_PipePipe:
-  case OO_Comma:
-    CanBeBinaryOperator = true;
-    break;
-
-  // Unary or binary operators
-  case OO_Amp:
-  case OO_Plus:
-  case OO_Minus:
-  case OO_Star:
-  case OO_PlusPlus:
-  case OO_MinusMinus:
-  case OO_ArrowStar:
-    CanBeUnaryOperator = true;
-    CanBeBinaryOperator = true;
-    break;
-
-  case OO_Call:
-    MustBeMemberOperator = true;
-    break;
-
-  case OO_None:
-  case NUM_OVERLOADED_OPERATORS:
-    assert(false && "Not an overloaded operator!");
-    return true;
-  }
+  static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
+    { false, false, false }
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+    , { Unary, Binary, MemberOnly }
+#include "clang/Basic/OperatorKinds.def"
+  };
+
+  bool CanBeUnaryOperator = OperatorUses[Op][0];
+  bool CanBeBinaryOperator = OperatorUses[Op][1];
+  bool MustBeMemberOperator = OperatorUses[Op][2];
 
   // C++ [over.oper]p8:
   //   [...] Operator functions cannot have more or fewer parameters
@@ -1890,23 +1823,30 @@
        (NumParams < 1) || (NumParams > 2))) {
     // We have the wrong number of parameters.
     std::string NumParamsStr = (llvm::APSInt(32) = NumParams).toString(10);
-    std::string NumParamsPlural;
-    if (NumParams != 1)
-      NumParamsPlural = "s";
 
     diag::kind DK;
 
-    if (CanBeUnaryOperator && CanBeBinaryOperator)
-      DK = diag::err_operator_overload_must_be_unary_or_binary;
-    else if (CanBeUnaryOperator)
-      DK = diag::err_operator_overload_must_be_unary;
-    else if (CanBeBinaryOperator)
-      DK = diag::err_operator_overload_must_be_binary;
-    else
+    if (CanBeUnaryOperator && CanBeBinaryOperator) {
+      if (NumParams == 1)
+        DK = diag::err_operator_overload_must_be_unary_or_binary;
+      else
+        DK = diag::err_operator_overload_must_be_unary_or_binary;
+    } else if (CanBeUnaryOperator) {
+      if (NumParams == 1)
+        DK = diag::err_operator_overload_must_be_unary;
+      else
+        DK = diag::err_operator_overload_must_be_unary_plural;
+    } else if (CanBeBinaryOperator) {
+      if (NumParams == 1)
+        DK = diag::err_operator_overload_must_be_binary;
+      else
+        DK = diag::err_operator_overload_must_be_binary_plural;
+    } else {
       assert(false && "All non-call overloaded operators are unary or binary!");
+    }
 
     Diag(FnDecl->getLocation(), DK,
-         FnDecl->getName(), NumParamsStr, NumParamsPlural,
+         FnDecl->getName(), NumParamsStr, 
          SourceRange(FnDecl->getLocation()));
     IsInvalid = true;
   }
@@ -1945,11 +1885,19 @@
       ParamIsInt = BT->getKind() == BuiltinType::Int;
 
     if (!ParamIsInt) {
-      Diag(LastParam->getLocation(),
-           diag::err_operator_overload_post_incdec_must_be_int,
-           MethodDecl? std::string() : std::string("second "),
-           (Op == OO_PlusPlus)? std::string("increment") 
-                              : std::string("decrement"),
+      diag::kind DK;
+      if (Op == OO_PlusPlus) {
+        if (MethodDecl)
+          DK = diag::err_operator_overload_post_inc_must_be_int_member;
+        else
+          DK = diag::err_operator_overload_post_inc_must_be_int;
+      } else {
+        if (MethodDecl)
+          DK = diag::err_operator_overload_post_dec_must_be_int_member;
+        else
+          DK = diag::err_operator_overload_post_dec_must_be_int;
+      }
+      Diag(LastParam->getLocation(), DK,
            Context.getCanonicalType(LastParam->getType()).getAsString(),
            SourceRange(FnDecl->getLocation()));
       IsInvalid = true;





More information about the cfe-commits mailing list