[cfe-commits] r58817 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Basic/ lib/Parse/ lib/Sema/ test/SemaCXX/ www/

Douglas Gregor doug.gregor at gmail.com
Thu Nov 6 14:13:31 PST 2008


Author: dgregor
Date: Thu Nov  6 16:13:31 2008
New Revision: 58817

URL: http://llvm.org/viewvc/llvm-project?rev=58817&view=rev
Log:
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".


Added:
    cfe/trunk/include/clang/Basic/OperatorKinds.def
    cfe/trunk/include/clang/Basic/OperatorKinds.h   (with props)
    cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Parse/AccessSpecifier.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=58817&r1=58816&r2=58817&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Nov  6 16:13:31 2008
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_AST_DECL_H
 #define LLVM_CLANG_AST_DECL_H
 
+#include "clang/Basic/OperatorKinds.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/Parse/AccessSpecifier.h"
 #include "llvm/ADT/SmallVector.h"
@@ -542,6 +543,14 @@
   StorageClass getStorageClass() const { return StorageClass(SClass); }
   bool isInline() const { return IsInline; }
  
+  /// isOverloadedOperator - Whether this function declaration
+  /// represents an C++ overloaded operator, e.g., "operator+".
+  bool isOverloadedOperator() const { 
+    return getOverloadedOperator() != OO_None;
+  };
+
+  OverloadedOperatorKind getOverloadedOperator() const;
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Nov  6 16:13:31 2008
@@ -1288,6 +1288,28 @@
 DIAG(err_ambiguous_derived_to_base_conv, ERROR,
      "ambiguous conversion from derived class '%0' to base class '%1':%2")
 
+// C++ operator overloading
+DIAG(err_expected_operator, ERROR,
+     "expected 'operator' keyword")
+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)")
+DIAG(err_operator_overload_variadic, ERROR,
+     "overloaded operator cannot be variadic")
+DIAG(err_operator_overload_static, ERROR,
+     "overloaded operator '%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")
+DIAG(err_operator_overload_must_be_unary, ERROR,
+     "overloaded operator '%0' must be a unary operator (has %1 parameter%2)")
+DIAG(err_operator_overload_must_be_binary, ERROR,
+     "overloaded operator '%0' must be a binary operator (has %1 parameter%2)")
+DIAG(err_operator_overload_must_be_unary_or_binary, ERROR,
+     "overloaded operator '%0' must be a unary or binary operator (has %1 parameter%2)")
+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(warn_not_compound_assign, WARNING,
      "use of unary operator that may be intended as compound assignment (%0=)")
 

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

==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Thu Nov  6 16:13:31 2008
@@ -15,6 +15,7 @@
 #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
 #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
 
+#include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/TokenKinds.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/SmallString.h"
@@ -49,11 +50,12 @@
   // First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
   // are for builtins.
   unsigned ObjCOrBuiltinID    :10; 
+  unsigned OperatorID         : 6; // C++ overloaded operator.
   bool HasMacro               : 1; // True if there is a #define for this.
   bool IsExtension            : 1; // True if identifier is a lang extension.
   bool IsPoisoned             : 1; // True if identifier is poisoned.
   bool IsCPPOperatorKeyword   : 1; // True if ident is a C++ operator keyword.
-  // 10 bits left in 32-bit word.
+  // 4 bits left in 32-bit word.
   void *FETokenInfo;               // Managed by the language front-end.
   IdentifierInfo(const IdentifierInfo&);  // NONCOPYABLE.
   void operator=(const IdentifierInfo&);  // NONASSIGNABLE.
@@ -120,6 +122,16 @@
            && "ID too large for field!");
   }
   
+  /// getOverloadedOperatorID - Get the C++ overloaded operator that
+  /// corresponds to this identifier.
+  OverloadedOperatorKind getOverloadedOperatorID() const {
+    return OverloadedOperatorKind(OperatorID);
+  }
+  void setOverloadedOperatorID(OverloadedOperatorKind ID) {
+    OperatorID = ID;
+    assert(OperatorID == (unsigned)ID && "ID too large for field!");
+  }
+
   /// get/setExtension - Initialize information about whether or not this
   /// language token is an extension.  This controls extension warnings, and is
   /// only valid if a custom token ID is set.
@@ -161,6 +173,11 @@
   // BumpPtrAllocator!
   typedef llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator> HashTableTy;
   HashTableTy HashTable;
+
+  /// OverloadedOperators - Identifiers corresponding to each of the
+  /// overloadable operators in C++.
+  IdentifierInfo *OverloadedOperators[NUM_OVERLOADED_OPERATORS];
+
 public:
   /// IdentifierTable ctor - Create the identifier table, populating it with
   /// info about the language keywords for the language specified by LangOpts.
@@ -180,7 +197,12 @@
     const char *NameBytes = &Name[0];
     return get(NameBytes, NameBytes+Name.size());
   }
-  
+
+  /// getOverloadedOperator - Retrieve the identifier   
+  IdentifierInfo &getOverloadedOperator(OverloadedOperatorKind Op) {
+    return *OverloadedOperators[Op];
+  }
+
   typedef HashTableTy::const_iterator iterator;
   typedef HashTableTy::const_iterator const_iterator;
   
@@ -194,6 +216,7 @@
   void PrintStats() const;
   
   void AddKeywords(const LangOptions &LangOpts);
+  void AddOverloadedOperators();
 
   /// Emit - Serialize this IdentifierTable to a bitstream.  This should
   ///  be called AFTER objects that externally reference the identifiers in the 

Added: cfe/trunk/include/clang/Basic/OperatorKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OperatorKinds.def?rev=58817&view=auto

==============================================================================
--- cfe/trunk/include/clang/Basic/OperatorKinds.def (added)
+++ cfe/trunk/include/clang/Basic/OperatorKinds.def Thu Nov  6 16:13:31 2008
@@ -0,0 +1,68 @@
+//===--- OperatorKinds.def - C++ Overloaded Operator Database ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the OverloadedOperator database, which includes
+// all of the overloadable C++ operators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OVERLOADED_OPERATOR
+#  define OVERLOADED_OPERATOR(Name,Spelling,Token)
+#endif
+
+#ifndef OVERLOADED_OPERATOR_MULTI
+#  define OVERLOADED_OPERATOR_MULTI(Name,Spelling) \
+     OVERLOADED_OPERATOR(Name,Spelling,unknown)
+#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[]")
+
+#undef OVERLOADED_OPERATOR_MULTI
+#undef OVERLOADED_OPERATOR

Added: cfe/trunk/include/clang/Basic/OperatorKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OperatorKinds.h?rev=58817&view=auto

==============================================================================
--- cfe/trunk/include/clang/Basic/OperatorKinds.h (added)
+++ cfe/trunk/include/clang/Basic/OperatorKinds.h Thu Nov  6 16:13:31 2008
@@ -0,0 +1,31 @@
+//===--- OperatorKinds.h - C++ Overloaded Operators -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines C++ overloaded operators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H
+#define LLVM_CLANG_BASIC_OPERATOR_KINDS_H
+
+namespace clang {
+
+/// OverloadedOperatorKind - Enumeration specifying the different kinds of
+/// C++ overloaded operators.
+enum OverloadedOperatorKind {
+  OO_None,                //< Not an overloaded operator
+#define OVERLOADED_OPERATOR(Name,Spelling,Token) OO_##Name,
+#include "clang/Basic/OperatorKinds.def"
+  NUM_OVERLOADED_OPERATORS
+};
+
+
+} // end namespace clang
+
+#endif

Propchange: cfe/trunk/include/clang/Basic/OperatorKinds.h

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/include/clang/Basic/OperatorKinds.h

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/include/clang/Basic/OperatorKinds.h

------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/include/clang/Parse/AccessSpecifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/AccessSpecifier.h?rev=58817&r1=58816&r2=58817&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/AccessSpecifier.h (original)
+++ cfe/trunk/include/clang/Parse/AccessSpecifier.h Thu Nov  6 16:13:31 2008
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file defines interfaces used for Declaration Specifiers and Declarators.
+// This file defines interfaces used for C++ access specifiers.
 //
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=58817&r1=58816&r2=58817&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Nov  6 16:13:31 2008
@@ -728,6 +728,10 @@
   void ParseBaseClause(DeclTy *ClassDecl);
   BaseResult ParseBaseSpecifier(DeclTy *ClassDecl);
   AccessSpecifier getAccessSpecifierIfPresent() const;
+
+  //===--------------------------------------------------------------------===//
+  // C++ 13.5: Overloaded operators [over.oper]
+  IdentifierInfo *MaybeParseOperatorFunctionId();
 };
 
 }  // end namespace clang

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=58817&r1=58816&r2=58817&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Nov  6 16:13:31 2008
@@ -210,6 +210,15 @@
   return NumRequiredArgs;
 }
 
+/// getOverloadedOperator - Which C++ overloaded operator this
+/// function represents, if any.
+OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
+  if (getIdentifier())
+    return getIdentifier()->getOverloadedOperatorID();
+  else
+    return OO_None;
+}
+
 //===----------------------------------------------------------------------===//
 // TagdDecl Implementation
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Thu Nov  6 16:13:31 2008
@@ -28,6 +28,7 @@
 IdentifierInfo::IdentifierInfo() {
   TokenID = tok::identifier;
   ObjCOrBuiltinID = 0;
+  OperatorID = 0;
   HasMacro = false;
   IsExtension = false;
   IsPoisoned = false;
@@ -46,6 +47,7 @@
   // Populate the identifier table with info about keywords for the current
   // language.
   AddKeywords(LangOpts);
+  AddOverloadedOperators();
 }
 
 // This cstor is intended to be used only for serialization.
@@ -160,6 +162,15 @@
 #include "clang/Basic/TokenKinds.def"
 }
 
+/// AddOverloadedOperators - Register the name of all C++ overloadable
+/// operators ("operator+", "operator[]", etc.)
+void IdentifierTable::AddOverloadedOperators() {
+#define OVERLOADED_OPERATOR(Name,Spelling,Token)                        \
+  OverloadedOperators[OO_##Name] = &get(Spelling);                      \
+  OverloadedOperators[OO_##Name]->setOverloadedOperatorID(OO_##Name);
+#include "clang/Basic/OperatorKinds.def"
+}
+
 tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
   // We use a perfect hash function here involving the length of the keyword,
   // the first and third character.  For preprocessor ID's there are no

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Nov  6 16:13:31 2008
@@ -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 ')'

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Nov  6 16:13:31 2008
@@ -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);

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Nov  6 16:13:31 2008
@@ -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);
+  }
+}

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=58817&r1=58816&r2=58817&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Nov  6 16:13:31 2008
@@ -863,6 +863,12 @@
   bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
                                     SourceLocation Loc, SourceRange Range);
 
+  //===--------------------------------------------------------------------===//
+  // C++ Overloaded Operators [C++ 13.5]
+  //
+
+  bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+
   // Objective-C declarations.
   virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
                                            IdentifierInfo *ClassName,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Nov  6 16:13:31 2008
@@ -932,6 +932,11 @@
     else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
       return ActOnDestructorDeclarator(Destructor);
 
+    // Extra checking for C++ overloaded operators (C++ [over.oper]).
+    if (NewFD->isOverloadedOperator() &&
+        CheckOverloadedOperatorDeclaration(NewFD))
+      NewFD->setInvalidDecl();
+    
     // Merge the decl with the existing one if appropriate. Since C functions
     // are in a flat namespace, make sure we consider decls in outer scopes.
     if (PrevDecl &&

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Nov  6 16:13:31 2008
@@ -1576,3 +1576,242 @@
     return PerformImplicitConversion(Init, T1);
   }
 }
+
+/// CheckOverloadedOperatorDeclaration - Check whether the declaration
+/// 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 &&
+         "Expected an overloaded operator declaration");
+
+  bool IsInvalid = false;
+
+  OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
+
+  // C++ [over.oper]p5: 
+  //   The allocation and deallocation functions, operator new,
+  //   operator new[], operator delete and operator delete[], are
+  //   described completely in 3.7.3. The attributes and restrictions
+  //   found in the rest of this subclause do not apply to them unless
+  //   explicitly stated in 3.7.3.
+  // FIXME: Write a separate routine for checking this. For now, just 
+  // allow it.
+  if (Op == OO_New || Op == OO_Array_New ||
+      Op == OO_Delete || Op == OO_Array_Delete)
+    return false;
+
+  // C++ [over.oper]p6:
+  //   An operator function shall either be a non-static member
+  //   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;
+    }
+  } 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();
+      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;
+    }
+  }
+
+  // C++ [over.oper]p8:
+  //   An operator function cannot have default arguments (8.3.6),
+  //   except where explicitly stated below.
+  //
+  // Only the function-call operator allows default arguments 
+  // (C++ [over.call]p1).
+  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;
+      }
+    }
+  }
+
+  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;
+  }
+
+  // C++ [over.oper]p8:
+  //   [...] 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);
+  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 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
+      assert(false && "All non-call overloaded operators are unary or binary!");
+
+    Diag(FnDecl->getLocation(), DK,
+         FnDecl->getName(), NumParamsStr, NumParamsPlural,
+         SourceRange(FnDecl->getLocation()));
+    IsInvalid = true;
+  }
+      
+  // Overloaded operators cannot be variadic.
+  if (FnDecl->getType()->getAsFunctionTypeProto()->isVariadic()) {
+    Diag(FnDecl->getLocation(),
+         diag::err_operator_overload_variadic,
+         SourceRange(FnDecl->getLocation()));
+    IsInvalid = true;
+  }
+
+  // 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;
+  }
+
+  // C++ [over.inc]p1:
+  //   The user-defined function called operator++ implements the
+  //   prefix and postfix ++ operator. If this function is a member
+  //   function with no parameters, or a non-member function with one
+  //   parameter of class or enumeration type, it defines the prefix
+  //   increment operator ++ for objects of that type. If the function
+  //   is a member function with one parameter (which shall be of type
+  //   int) or a non-member function with two parameters (the second
+  //   of which shall be of type int), it defines the postfix
+  //   increment operator ++ for objects of that type.
+  if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
+    ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
+    bool ParamIsInt = false;
+    if (const BuiltinType *BT = LastParam->getType()->getAsBuiltinType())
+      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"),
+           Context.getCanonicalType(LastParam->getType()).getAsString(),
+           SourceRange(FnDecl->getLocation()));
+      IsInvalid = true;
+    }
+  }
+
+  return IsInvalid;
+}

Added: cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp?rev=58817&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp (added)
+++ cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp Thu Nov  6 16:13:31 2008
@@ -0,0 +1,37 @@
+// RUN: clang -fsyntax-only -verify %s 
+struct X { 
+  X();
+  X(int); 
+};
+
+X operator+(X, X);
+X operator-(X, X) { X x; return x; }
+
+struct Y {
+  Y operator-() const;
+  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}}
+};
+
+
+void f(X x) {
+  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*(X, X = 5); // expected-error{{a parameter of an overloaded operator cannot have a default argument}}
+
+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)}}
+
+void operator()(Y&, int, int); // expected-error{{overloaded operator 'operator()' must be a non-static member function}}
+
+typedef int INT;
+typedef float FLOAT;
+Y& operator++(Y&);
+Y operator++(Y&, INT);
+X operator++(X&, FLOAT); // expected-error{{second parameter of overloaded post-increment operator must have type 'int' (not 'float')}}

Propchange: cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=58817&r1=58816&r2=58817&view=diff

==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Thu Nov  6 16:13:31 2008
@@ -810,14 +810,70 @@
   <td></td>
 </tr>
 <tr><td>  13.4 [over.over]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>  13.5 [over.oper]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.1 [over.unary]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.2 [over.binary]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.3 [over.ass]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.4 [over.call]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.5 [over.sub]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.6 [over.ref]</td><td></td><td></td><td></td><td></td><td></td></tr>
-<tr><td>    13.5.7 [over.inc]</td><td></td><td></td><td></td><td></td><td></td></tr>
+<tr>
+  <td>  13.5 [over.oper]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td>Overloaded operators can only be called with function syntax, e.g., <code>operator+(x, y)</code>.</td>
+</tr>
+<tr>
+  <td>    13.5.1 [over.unary]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
+<tr>
+  <td>    13.5.2 [over.binary]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
+<tr>
+  <td>    13.5.3 [over.ass]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
+<tr>
+  <td>    13.5.4 [over.call]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
+<tr>
+  <td>    13.5.5 [over.sub]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
+<tr>
+  <td>    13.5.6 [over.ref]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
+<tr>
+  <td>    13.5.7 [over.inc]</td>
+  <td bgcolor="#347C17" align="center"></td>  
+  <td bgcolor="#347C17" align="center"></td>
+  <td bgcolor="#FDD017" align="center"></td>
+  <td bgcolor="#C11B17" align="center"></td>  
+  <td></td>
+</tr>
 <tr><td>  13.6 [over.built]</td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td>14 [temp]</td><td></td><td></td><td></td><td></td><td></td></tr>
 <tr><td>  14.1 [temp.param]</td><td></td><td></td><td></td><td></td><td></td></tr>





More information about the cfe-commits mailing list