[cfe-commits] r59443 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/overloaded-operator-decl.cpp

Douglas Gregor doug.gregor at gmail.com
Mon Nov 17 08:14:20 PST 2008


Author: dgregor
Date: Mon Nov 17 10:14:12 2008
New Revision: 59443

URL: http://llvm.org/viewvc/llvm-project?rev=59443&view=rev
Log:
Some cleanups for C++ operator overloading

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Nov 17 10:14:12 2008
@@ -1324,31 +1324,34 @@
 
 // C++ operator overloading
 DIAG(err_operator_overload_needs_class_or_enum, ERROR,
-     "non-member overloaded operator '%0' must have at least one parameter of class or enumeration type (or reference thereof)")
+     "overloaded '%0' must have at least one parameter of class "
+     "or enumeration type")
 DIAG(err_operator_overload_variadic, ERROR,
-     "overloaded operator cannot be variadic")
+     "overloaded '%0' cannot be variadic")
 DIAG(err_operator_overload_static, ERROR,
-     "overloaded operator '%0' cannot be a static member function")
+     "overloaded '%0' cannot be a static member function")
 DIAG(err_operator_overload_default_arg, ERROR,
-     "a parameter of an overloaded operator cannot have a default argument")
+     "parameter of overloaded '%0' cannot have a default argument")
 DIAG(err_operator_overload_must_be_unary, ERROR,
-     "overloaded operator '%0' must be a unary operator (has %1 parameter)")
+     "overloaded '%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)")
+     "overloaded '%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)")
+     "overloaded '%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)")
+     "overloaded '%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)")
+     "overloaded '%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)")
+     "overloaded '%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")
+     "overloaded '%0' must be a non-static member function")
 DIAG(err_operator_overload_post_inc_must_be_int, ERROR,
-     "parameter of overloaded post-increment operator must have type 'int' (not '%0')")
+     "parameter of overloaded post-increment operator must have type 'int' "
+     "(not '%0')")
 DIAG(err_operator_overload_post_dec_must_be_int, ERROR,
-     "parameter of overloaded post-decrement operator must have type 'int' (not '%0')")
+     "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/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=59443&r1=59442&r2=59443&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Nov 17 10:14:12 2008
@@ -795,7 +795,7 @@
 
   //===--------------------------------------------------------------------===//
   // C++ 13.5: Overloaded operators [over.oper]
-  IdentifierInfo *MaybeParseOperatorFunctionId();
+  IdentifierInfo *TryParseOperatorFunctionId();
   TypeTy *ParseConversionFunctionId();
 };
 

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Nov 17 10:14:12 2008
@@ -1464,7 +1464,7 @@
     SourceLocation OperatorLoc = Tok.getLocation();
 
     // First try the name of an overloaded operator
-    if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) {
+    if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
       D.SetIdentifier(II, OperatorLoc);
     } else {
       // This must be a conversion function (C++ [class.conv.fct]).

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Nov 17 10:14:12 2008
@@ -149,7 +149,7 @@
 
   case tok::kw_operator: {
     SourceLocation OperatorLoc = Tok.getLocation();
-    if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) {
+    if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
       return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II, 
                                          Tok.is(tok::l_paren), &SS);
     }
@@ -519,7 +519,7 @@
   return false;
 }
 
-/// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded
+/// TryParseOperatorFunctionId - 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.
@@ -534,7 +534,7 @@
 ///            ^=    &=   |= <<   >> >>= <<=  ==  !=
 ///            <=    >=   && ||   ++ --   ,   ->* ->
 ///            ()    []
-IdentifierInfo *Parser::MaybeParseOperatorFunctionId() {
+IdentifierInfo *Parser::TryParseOperatorFunctionId() {
   assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
 
   OverloadedOperatorKind Op = OO_None;
@@ -581,16 +581,12 @@
     return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript);
 
   default:
-    break;
-  }
-
-  if (Op == OO_None)
     return 0;
-  else {
-    ConsumeToken(); // 'operator'
-    ConsumeAnyToken(); // the operator itself
-    return &PP.getIdentifierTable().getOverloadedOperator(Op);
   }
+
+  ConsumeToken(); // 'operator'
+  ConsumeAnyToken(); // the operator itself
+  return &PP.getIdentifierTable().getOverloadedOperator(Op);
 }
 
 /// ParseConversionFunctionId - Parse a C++ conversion-function-id,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov 17 10:14:12 2008
@@ -20,6 +20,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Compiler.h"
 #include <algorithm> // for std::equal
 #include <map>
@@ -1825,11 +1826,9 @@
 /// of this overloaded operator is well-formed. If so, returns false;
 /// otherwise, emits appropriate diagnostics and returns true.
 bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
-  assert(FnDecl && FnDecl->getOverloadedOperator() != OO_None &&
+  assert(FnDecl && FnDecl->isOverloadedOperator() &&
          "Expected an overloaded operator declaration");
 
-  bool IsInvalid = false;
-
   OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
 
   // C++ [over.oper]p5: 
@@ -1849,39 +1848,27 @@
   //   function or be a non-member function and have at least one
   //   parameter whose type is a class, a reference to a class, an
   //   enumeration, or a reference to an enumeration.
-  CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl);
-  if (MethodDecl) {
-    if (MethodDecl->isStatic()) {
-      Diag(FnDecl->getLocation(),
-           diag::err_operator_overload_static,
-           FnDecl->getName(),
-           SourceRange(FnDecl->getLocation()));
-      IsInvalid = true;
-
-      // Pretend this isn't a member function; it'll supress
-      // additional, unnecessary error messages.
-      MethodDecl = 0;
-    }
+  if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
+    if (MethodDecl->isStatic())
+      return Diag(FnDecl->getLocation(),
+                  diag::err_operator_overload_static,
+                  FnDecl->getName());
   } else {
     bool ClassOrEnumParam = false;
-    for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
-         Param != FnDecl->param_end(); ++Param) {
-      QualType ParamType = (*Param)->getType();
-      if (const ReferenceType *RefType = ParamType->getAsReferenceType())
-        ParamType = RefType->getPointeeType();
+    for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
+                                   ParamEnd = FnDecl->param_end();
+         Param != ParamEnd; ++Param) {
+      QualType ParamType = (*Param)->getType().getNonReferenceType();
       if (ParamType->isRecordType() || ParamType->isEnumeralType()) {
         ClassOrEnumParam = true;
         break;
       }
     }
 
-    if (!ClassOrEnumParam) {
-      Diag(FnDecl->getLocation(),
-           diag::err_operator_overload_needs_class_or_enum,
-           FnDecl->getName(),
-           SourceRange(FnDecl->getLocation()));
-      IsInvalid = true;
-    }
+    if (!ClassOrEnumParam)
+      return Diag(FnDecl->getLocation(),
+                  diag::err_operator_overload_needs_class_or_enum,
+                  FnDecl->getName());
   }
 
   // C++ [over.oper]p8:
@@ -1893,12 +1880,10 @@
   if (Op != OO_Call) {
     for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
          Param != FnDecl->param_end(); ++Param) {
-      if (Expr *DefArg = (*Param)->getDefaultArg()) {
-        Diag((*Param)->getLocation(),
-             diag::err_operator_overload_default_arg,
-             DefArg->getSourceRange());
-        IsInvalid = true;
-      }
+      if (Expr *DefArg = (*Param)->getDefaultArg())
+        return Diag((*Param)->getLocation(),
+                    diag::err_operator_overload_default_arg,
+                    FnDecl->getName(), DefArg->getSourceRange());
     }
   }
 
@@ -1917,13 +1902,14 @@
   //   [...] Operator functions cannot have more or fewer parameters
   //   than the number required for the corresponding operator, as
   //   described in the rest of this subclause.
-  unsigned NumParams = FnDecl->getNumParams() + (MethodDecl? 1 : 0);
+  unsigned NumParams = FnDecl->getNumParams() 
+                     + (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
   if (Op != OO_Call &&
       ((NumParams == 1 && !CanBeUnaryOperator) ||
        (NumParams == 2 && !CanBeBinaryOperator) ||
        (NumParams < 1) || (NumParams > 2))) {
     // We have the wrong number of parameters.
-    std::string NumParamsStr = (llvm::APSInt(32) = NumParams).toString(10);
+    std::string NumParamsStr = llvm::utostr(NumParams);
 
     diag::kind DK;
 
@@ -1946,27 +1932,23 @@
       assert(false && "All non-call overloaded operators are unary or binary!");
     }
 
-    Diag(FnDecl->getLocation(), DK,
-         FnDecl->getName(), NumParamsStr, 
-         SourceRange(FnDecl->getLocation()));
-    IsInvalid = true;
+    return Diag(FnDecl->getLocation(), DK,
+                FnDecl->getName(), NumParamsStr);
   }
       
-  // Overloaded operators cannot be variadic.
-  if (FnDecl->getType()->getAsFunctionTypeProto()->isVariadic()) {
-    Diag(FnDecl->getLocation(),
-         diag::err_operator_overload_variadic,
-         SourceRange(FnDecl->getLocation()));
-    IsInvalid = true;
+  // Overloaded operators other than operator() cannot be variadic.
+  if (Op != OO_Call &&
+      FnDecl->getType()->getAsFunctionTypeProto()->isVariadic()) {
+    return Diag(FnDecl->getLocation(),
+                diag::err_operator_overload_variadic,
+                FnDecl->getName());
   }
 
   // Some operators must be non-static member functions.
-  if (MustBeMemberOperator && !MethodDecl) {
-    Diag(FnDecl->getLocation(),
-         diag::err_operator_overload_must_be_member,
-         FnDecl->getName(),
-         SourceRange(FnDecl->getLocation()));
-    IsInvalid = true;
+  if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
+    return Diag(FnDecl->getLocation(),
+                diag::err_operator_overload_must_be_member,
+                FnDecl->getName());
   }
 
   // C++ [over.inc]p1:
@@ -1991,12 +1973,10 @@
         DK = diag::err_operator_overload_post_inc_must_be_int;
       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;
+      return Diag(LastParam->getLocation(), DK,
+                  Context.getCanonicalType(LastParam->getType()).getAsString());
     }
   }
 
-  return IsInvalid;
+  return false;
 }

Modified: cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp?rev=59443&r1=59442&r2=59443&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp Mon Nov 17 10:14:12 2008
@@ -12,7 +12,7 @@
   void operator()(int x = 17) const;
   int operator[](int);
 
-  static int operator+(Y, Y); // expected-error{{overloaded operator 'operator+' cannot be a static member function}}
+  static int operator+(Y, Y); // expected-error{{overloaded 'operator+' cannot be a static member function}}
 };
 
 
@@ -20,15 +20,15 @@
   x = operator+(x, x);
 }
 
-X operator+(int, float); // expected-error{{non-member overloaded operator 'operator+' must have at least one parameter of class or enumeration type (or reference thereof)}}
+X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}}
 
-X operator*(X, X = 5); // expected-error{{a parameter of an overloaded operator cannot have a default argument}}
+X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}}
 
-X operator/(X, X, ...); // expected-error{{overloaded operator cannot be variadic}}
+X operator/(X, X, ...); // expected-error{{overloaded 'operator/' cannot be variadic}}
 
-X operator%(Y); // expected-error{{overloaded operator 'operator%' must be a binary operator (has 1 parameter)}}
+X operator%(Y); // expected-error{{overloaded 'operator%' must be a binary operator (has 1 parameter)}}
 
-void operator()(Y&, int, int); // expected-error{{overloaded operator 'operator()' must be a non-static member function}}
+void operator()(Y&, int, int); // expected-error{{overloaded 'operator()' must be a non-static member function}}
 
 typedef int INT;
 typedef float FLOAT;





More information about the cfe-commits mailing list