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

Douglas Gregor doug.gregor at gmail.com
Tue Nov 18 06:39:39 PST 2008


Author: dgregor
Date: Tue Nov 18 08:39:36 2008
New Revision: 59526

URL: http://llvm.org/viewvc/llvm-project?rev=59526&view=rev
Log:
Extend DeclarationName to support C++ overloaded operators, e.g.,
operator+, directly, using the same mechanism as all other special
names.

Removed the "special" identifiers for the overloaded operators from
the identifier table and IdentifierInfo data structure. IdentifierInfo
is back to representing only real identifiers.

Added a new Action, ActOnOperatorFunctionIdExpr, that builds an
expression from an parsed operator-function-id (e.g., "operator
+"). ActOnIdentifierExpr used to do this job, but
operator-function-ids are no longer represented by IdentifierInfo's.

Extended Declarator to store overloaded operator names. 
Sema::GetNameForDeclarator now knows how to turn the operator
name into a DeclarationName for the overloaded operator. 

Except for (perhaps) consolidating the functionality of
ActOnIdentifier, ActOnOperatorFunctionIdExpr, and
ActOnConversionFunctionExpr into a common routine that builds an
appropriate DeclRefExpr by looking up a DeclarationName, all of the
work on normalizing declaration names should be complete with this
commit.


Modified:
    cfe/trunk/docs/InternalsManual.html
    cfe/trunk/include/clang/AST/DeclarationName.h
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclSerialization.cpp
    cfe/trunk/lib/AST/DeclarationName.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp

Modified: cfe/trunk/docs/InternalsManual.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/InternalsManual.html?rev=59526&r1=59525&r2=59526&view=diff

==============================================================================
--- cfe/trunk/docs/InternalsManual.html (original)
+++ cfe/trunk/docs/InternalsManual.html Tue Nov 18 08:39:36 2008
@@ -469,7 +469,7 @@
 <p>Given
   a <code>DeclarationName</code> <code>N</code>, <code>N.getNameKind()</code>
   will produce a value that describes what kind of name <code>N</code>
-  stores. There are 7 options (all of the names are inside
+  stores. There are 8 options (all of the names are inside
   the <code>DeclarationName</code> class)</p>
 <dl>
   <dt>Identifier</dt>
@@ -514,11 +514,19 @@
       const *</code>". Use <code>N.getCXXNameType()</code> to retrieve
   the type that this conversion function converts to. This type is
     always a canonical type.</dd>
+
+  <dt>CXXOperatorName</dt>
+  <dd>The name is a C++ overloaded operator name. Overloaded operators
+  are named according to their spelling, e.g.,
+  "<code>operator+</code>" or "<code>operator new
+  []</code>". Use <code>N.getCXXOverloadedOperator()</code> to
+  retrieve the overloaded operator (a value of
+    type <code>OverloadedOperatorKind</code>).</dd>
 </dl>
 
 <p><code>DeclarationName</code>s are cheap to create, copy, and
   compare. They require only a single pointer's worth of storage in
-  the common cases (identifiers, C++ overloaded operator names, zero-
+  the common cases (identifiers, zero-
   and one-argument Objective-C selectors) and use dense, uniqued
   storage for the other kinds of
   names. Two <code>DeclarationName</code>s can be compared for
@@ -532,16 +540,15 @@
 
 <p><code>DeclarationName</code> instances can be created in different
   ways depending on what kind of name the instance will store. Normal
-  identifiers (<code>IdentifierInfo</code> pointers), including
-  overloaded operator names, and Objective-C selectors
+  identifiers (<code>IdentifierInfo</code> pointers) and Objective-C selectors
   (<code>Selector</code>) can be implicitly converted
   to <code>DeclarationName</code>s. Names for C++ constructors,
-  destructors, and conversion functions can be retrieved from
+  destructors, conversion functions, and overloaded operators can be retrieved from
   the <code>DeclarationNameTable</code>, an instance of which is
   available as <code>ASTContext::DeclarationNames</code>. The member
   functions <code>getCXXConstructorName</code>, <code>getCXXDestructorName</code>,
-  and <code>getCXXConversionFunctionName</code>, respectively,
-  return <code>DeclarationName</code> instances for the three kinds of
+  <code>getCXXConversionFunctionName</code>, and <code>getCXXOperatorName</code>, respectively,
+  return <code>DeclarationName</code> instances for the four kinds of
   C++ special function names.</p>
 
 <!-- ======================================================================= -->

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclarationName.h (original)
+++ cfe/trunk/include/clang/AST/DeclarationName.h Tue Nov 18 08:39:36 2008
@@ -23,6 +23,7 @@
 
 namespace clang {
   class CXXSpecialName;       // a private class used by DeclarationName
+  class CXXOperatorIdName;    // a private class used by DeclarationName
   class DeclarationNameExtra; // a private class used by DeclarationName
   class IdentifierInfo;
   class MultiKeywordSelector; // a private class used by Selector and DeclarationName
@@ -43,7 +44,8 @@
     ObjCMultiArgSelector,
     CXXConstructorName,
     CXXDestructorName,
-    CXXConversionFunctionName
+    CXXConversionFunctionName,
+    CXXOperatorName
   };
 
 private:
@@ -53,7 +55,7 @@
     StoredIdentifier = 0,
     StoredObjCZeroArgSelector,
     StoredObjCOneArgSelector,
-    StoredObjCMultiArgSelectorOrCXXName,
+    StoredDeclarationNameExtra,
     PtrMask = 0x03
   };
 
@@ -62,22 +64,21 @@
   /// on the kind of name this is, the upper bits of Ptr may have one
   /// of several different meanings:
   ///
-  ///   Identifier - The name is a normal identifier, and Ptr is a
-  ///   normal IdentifierInfo pointer.  
+  ///   StoredIdentifier - The name is a normal identifier, and Ptr is
+  ///   a normal IdentifierInfo pointer.
   ///
-  ///   ObjCZeroArgSelector - The name is an Objective-C selector with
-  ///   zero arguments, and Ptr is an IdentifierInfo pointer pointing
-  ///   to the selector name.
+  ///   StoredObjCZeroArgSelector - The name is an Objective-C
+  ///   selector with zero arguments, and Ptr is an IdentifierInfo
+  ///   pointer pointing to the selector name.
   ///
-  ///   ObjCOneArgSelector - The name is an Objective-C selector with
-  ///   one argument, and Ptr is an IdentifierInfo pointer pointing to
-  ///   the selector name.
+  ///   StoredObjCOneArgSelector - The name is an Objective-C selector
+  ///   with one argument, and Ptr is an IdentifierInfo pointer
+  ///   pointing to the selector name.
   ///
-  ///   ObjCMultiArgSelectorOrCXXName - This is either an Objective-C
-  ///   selector with two or more arguments or it is a C++ name. Ptr
-  ///   is actually a DeclarationNameExtra structure, whose first
-  ///   value will tell us whether this is an Objective-C selector or
-  ///   special C++ name.
+  ///   StoredDeclarationNameExtra - Ptr is actually a pointer to a
+  ///   DeclarationNameExtra structure, whose first value will tell us
+  ///   whether this is an Objective-C selector, C++ operator-id name,
+  ///   or special C++ name.
   uintptr_t Ptr;
 
   /// getStoredNameKind - Return the kind of object that is stored in
@@ -89,7 +90,7 @@
   /// getExtra - Get the "extra" information associated with this
   /// multi-argument selector or C++ special name.
   DeclarationNameExtra *getExtra() const {
-    assert(getStoredNameKind() == StoredObjCMultiArgSelectorOrCXXName &&
+    assert(getStoredNameKind() == StoredDeclarationNameExtra &&
            "Declaration name does not store an Extra structure");
     return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
   }
@@ -105,12 +106,28 @@
       return 0;
   }
 
+  /// getAsCXXOperatorIdName
+  CXXOperatorIdName *getAsCXXOperatorIdName() const {
+    if (getNameKind() == CXXOperatorName)
+      return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
+    else
+      return 0;
+  }
+
   // Construct a declaration name from the name of a C++ constructor,
   // destructor, or conversion function.
   DeclarationName(CXXSpecialName *Name) 
     : Ptr(reinterpret_cast<uintptr_t>(Name)) { 
     assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
-    Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+    Ptr |= StoredDeclarationNameExtra;
+  }
+
+  // Construct a declaration name from the name of a C++ overloaded
+  // operator.
+  DeclarationName(CXXOperatorIdName *Name) 
+    : Ptr(reinterpret_cast<uintptr_t>(Name)) { 
+    assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
+    Ptr |= StoredDeclarationNameExtra;
   }
 
   // Construct a declaration name from a zero- or one-argument
@@ -130,7 +147,7 @@
   DeclarationName(MultiKeywordSelector *SI)
     : Ptr(reinterpret_cast<uintptr_t>(SI)) {
     assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
-    Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+    Ptr |= StoredDeclarationNameExtra;
   }
 
   /// Construct a declaration name from a raw pointer.
@@ -186,6 +203,11 @@
   /// type associated with that name.
   QualType getCXXNameType() const;
 
+  /// getCXXOverloadedOperator - If this name is the name of an
+  /// overloadable operator in C++ (e.g., @c operator+), retrieve the
+  /// kind of overloaded operator.
+  OverloadedOperatorKind getCXXOverloadedOperator() const;
+
   /// getObjCSelector - Get the Objective-C selector stored in this
   /// declaration name.
   Selector getObjCSelector() const;
@@ -248,6 +270,7 @@
 /// getCXXConstructorName).
 class DeclarationNameTable {
   void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
+  CXXOperatorIdName *CXXOperatorNames; // Operator names
 
   DeclarationNameTable(const DeclarationNameTable&);            // NONCOPYABLE
   DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
@@ -285,6 +308,10 @@
   /// function.
   DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, 
                                     QualType Ty);
+
+  /// getCXXOperatorName - Get the name of the overloadable C++
+  /// operator corresponding to Op.
+  DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
 };  
 
 }  // end namespace clang

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

==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Tue Nov 18 08:39:36 2008
@@ -51,12 +51,11 @@
   // 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.
-  // 4 bits left in 32-bit word.
+  // 10 bits left in 32-bit word.
   void *FETokenInfo;               // Managed by the language front-end.
   IdentifierInfo(const IdentifierInfo&);  // NONCOPYABLE.
   void operator=(const IdentifierInfo&);  // NONASSIGNABLE.
@@ -123,16 +122,6 @@
            && "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.
@@ -175,10 +164,6 @@
   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.
@@ -199,11 +184,6 @@
     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;
   
@@ -217,7 +197,6 @@
   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 
@@ -342,9 +321,9 @@
   static SelectorTable* CreateAndRegister(llvm::Deserializer& D);
 };
 
-/// DeclarationNameExtra - Common base of the MultiKeywordSelector and
-/// CXXSpecialName classes, both of which are private classes that can
-/// be stored by the AST's DeclarationName class.
+/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
+/// CXXSpecialName, and CXXOperatorIdName classes, all of which are
+/// private classes that describe different kinds of names.
 class DeclarationNameExtra {
 public:
   /// ExtraKind - The kind of "extra" information stored in the
@@ -354,12 +333,17 @@
     CXXConstructor = 0,
     CXXDestructor,
     CXXConversionFunction,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+    CXXOperator##Name,
+#include "clang/Basic/OperatorKinds.def"
     NUM_EXTRA_KINDS
   };
 
-  /// ExtraKindOrNumArgs - Either the kind of C++ special name (if the
-  /// value is one of the CXX* enumerators of ExtraKind), in which
-  /// case the DeclarationNameExtra is also a CXXSpecialName, or
+  /// ExtraKindOrNumArgs - Either the kind of C++ special name or
+  /// operator-id (if the value is one of the CXX* enumerators of
+  /// ExtraKind), in which case the DeclarationNameExtra is also a
+  /// CXXSpecialName (for CXXConstructor, CXXDestructor, or
+  /// CXXConversionFunction) or CXXOperatorIdName, otherwise it is
   /// NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
   /// arguments in the Objective-C selector, in which case the
   /// DeclarationNameExtra is also a MultiKeywordSelector.

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Nov 18 08:39:36 2008
@@ -463,9 +463,22 @@
                                          const CXXScopeSpec *SS = 0) {
     return 0;
   }
+
+  /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
+  /// name (e.g., @c operator+ ) as an expression. This is very
+  /// similar to ActOnIdentifierExpr, except that instead of providing
+  /// an identifier the parser provides the kind of overloaded
+  /// operator that was parsed.
+  virtual ExprResult ActOnOperatorFunctionIdExpr(Scope *S, 
+                                                 SourceLocation OperatorLoc,
+                                                 OverloadedOperatorKind Op,
+                                                 bool HasTrailingLParen,
+                                                 const CXXScopeSpec *SS = 0) {
+    return 0;
+  }
   
   /// ActOnConversionFunctionExpr - Parse a C++ conversion function
-  /// name (e.g., operator void const *) as an expression. This is
+  /// name (e.g., @c operator void const *) as an expression. This is
   /// very similar to ActOnIdentifierExpr, except that instead of
   /// providing an identifier the parser provides the type of the
   /// conversion function.

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

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Tue Nov 18 08:39:36 2008
@@ -647,6 +647,7 @@
     DK_Normal,           // A normal declarator (has an identifier). 
     DK_Constructor,      // A C++ constructor (identifier is the class name)
     DK_Destructor,       // A C++ destructor  (identifier is ~class name)
+    DK_Operator,         // A C++ overloaded operator name
     DK_Conversion        // A C++ conversion function (identifier is 
                          // "operator " then the type name)
   };
@@ -677,10 +678,16 @@
   /// AsmLabel - The asm label, if specified.
   Action::ExprTy *AsmLabel;
 
-  // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
-  // type associated with the constructor, destructor, or conversion
-  // operator.
-  Action::TypeTy *Type;
+  union {
+    // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
+    // type associated with the constructor, destructor, or conversion
+    // operator.
+    Action::TypeTy *Type;
+
+    /// When Kind is DK_Operator, this is the actual overloaded
+    /// operator that this declarator names.
+    OverloadedOperatorKind OperatorKind;
+  };
 
 public:
   Declarator(const DeclSpec &ds, TheContext C)
@@ -802,7 +809,7 @@
   }
 
   // setConversionFunction - Set this declarator to be a C++
-  // conversion function declarator.
+  // conversion function declarator (e.g., @c operator int const *).
   void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc) {
     Identifier = 0;
     IdentifierLoc = Loc;
@@ -810,6 +817,14 @@
     Type = Ty;
   }
 
+  // setOverloadedOperator - Set this declaration to be a C++
+  // overloaded operator declarator (e.g., @c operator+).
+  void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc) {
+    IdentifierLoc = Loc;
+    Kind = DK_Operator;
+    OperatorKind = Op;
+  }
+ 
   void AddTypeInfo(const DeclaratorChunk &TI) {
     DeclTypeInfo.push_back(TI);
   }
@@ -859,6 +874,8 @@
 
   Action::TypeTy *getDeclaratorIdType() const { return Type; }
 
+  OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
+
   void setInvalidType(bool flag) { InvalidType = flag; }
   bool getInvalidType() const { return InvalidType; }
 

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Nov 18 08:39:36 2008
@@ -789,7 +789,7 @@
 
   //===--------------------------------------------------------------------===//
   // C++ 13.5: Overloaded operators [over.oper]
-  IdentifierInfo *TryParseOperatorFunctionId();
+  OverloadedOperatorKind TryParseOperatorFunctionId();
   TypeTy *ParseConversionFunctionId();
 };
 

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

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Nov 18 08:39:36 2008
@@ -226,8 +226,8 @@
 /// getOverloadedOperator - Which C++ overloaded operator this
 /// function represents, if any.
 OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
-  if (getIdentifier())
-    return getIdentifier()->getOverloadedOperatorID();
+  if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+    return getDeclName().getCXXOverloadedOperator();
   else
     return OO_None;
 }

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

==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Tue Nov 18 08:39:36 2008
@@ -147,6 +147,10 @@
   case DeclarationName::CXXConversionFunctionName:
     Name.getCXXNameType().Emit(S);
     break;
+
+  case DeclarationName::CXXOperatorName:
+    S.EmitInt(Name.getCXXOverloadedOperator());
+    break;
   }
 }
 
@@ -178,8 +182,16 @@
     break;
 
   case DeclarationName::CXXConversionFunctionName:
-    Name = C.DeclarationNames.getCXXConversionFunctionName(QualType::ReadVal(D));
+    Name 
+      = C.DeclarationNames.getCXXConversionFunctionName(QualType::ReadVal(D));
     break;
+
+  case DeclarationName::CXXOperatorName: {
+    OverloadedOperatorKind Op 
+      = static_cast<OverloadedOperatorKind>(D.ReadInt());
+    Name = C.DeclarationNames.getCXXOperatorName(Op);
+    break;
+  }
   }
 }
 

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

==============================================================================
--- cfe/trunk/lib/AST/DeclarationName.cpp (original)
+++ cfe/trunk/lib/AST/DeclarationName.cpp Tue Nov 18 08:39:36 2008
@@ -40,6 +40,15 @@
   }
 };
 
+/// CXXOperatorIdName - Contains extra information for the name of an
+/// overloaded operator in C++, such as "operator+. 
+class CXXOperatorIdName : public DeclarationNameExtra {
+public:
+  /// FETokenInfo - Extra information associated with this operator
+  /// name that can be used by the front end.
+  void *FETokenInfo;
+};
+
 bool operator<(DeclarationName LHS, DeclarationName RHS) {
   if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
     if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
@@ -64,7 +73,7 @@
 
   default:
     Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
-    Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+    Ptr |= StoredDeclarationNameExtra;
     break;
   }
 }
@@ -75,7 +84,7 @@
   case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
   case StoredObjCOneArgSelector:  return ObjCOneArgSelector;
 
-  case StoredObjCMultiArgSelectorOrCXXName:
+  case StoredDeclarationNameExtra:
     switch (getExtra()->ExtraKindOrNumArgs) {
     case DeclarationNameExtra::CXXConstructor: 
       return CXXConstructorName;
@@ -87,6 +96,11 @@
       return CXXConversionFunctionName;
 
     default:
+      // Check if we have one of the CXXOperator* enumeration values.
+      if (getExtra()->ExtraKindOrNumArgs < 
+            DeclarationNameExtra::NUM_EXTRA_KINDS)
+        return CXXOperatorName;
+
       return ObjCMultiArgSelector;
     }
     break;
@@ -125,6 +139,23 @@
     return Result;
   }
 
+  case CXXOperatorName: {
+    static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
+      0,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+      Spelling,
+#include "clang/Basic/OperatorKinds.def"
+    };
+    const char *OpName = OperatorNames[getCXXOverloadedOperator()];
+    assert(OpName && "not an overloaded operator");
+      
+    std::string Result = "operator";
+    if (OpName[0] >= 'a' && OpName[0] <= 'z')
+      Result += ' ';
+    Result += OpName;
+    return Result;
+  }
+
   case CXXConversionFunctionName: {
     std::string Result = "operator ";
     QualType Type = getCXXNameType();
@@ -147,6 +178,16 @@
     return QualType();
 }
 
+OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
+  if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
+    unsigned value 
+      = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
+    return static_cast<OverloadedOperatorKind>(value);
+  } else {
+    return OO_None;
+  }
+}
+
 Selector DeclarationName::getObjCSelector() const {
   switch (getNameKind()) {
   case ObjCZeroArgSelector:
@@ -175,6 +216,9 @@
   case CXXConversionFunctionName:
     return getAsCXXSpecialName()->FETokenInfo;
 
+  case CXXOperatorName:
+    return getAsCXXOperatorIdName()->FETokenInfo;
+
   default:
     assert(false && "Declaration name has no FETokenInfo");
   }
@@ -193,6 +237,10 @@
     getAsCXXSpecialName()->FETokenInfo = T;
     break;
 
+  case CXXOperatorName:
+    getAsCXXOperatorIdName()->FETokenInfo = T;
+    break;
+
   default:
     assert(false && "Declaration name has no FETokenInfo");
   }
@@ -200,10 +248,19 @@
 
 DeclarationNameTable::DeclarationNameTable() {
   CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
+
+  // Initialize the overloaded operator names.
+  CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
+  for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
+    CXXOperatorNames[Op].ExtraKindOrNumArgs 
+      = Op + DeclarationNameExtra::CXXConversionFunction;
+    CXXOperatorNames[Op].FETokenInfo = 0;
+  }
 }
 
 DeclarationNameTable::~DeclarationNameTable() {
   delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
+  delete [] CXXOperatorNames;
 }
 
 DeclarationName 
@@ -249,3 +306,8 @@
   return DeclarationName(SpecialName);
 }
 
+DeclarationName 
+DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
+  return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
+}
+

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

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Nov 18 08:39:36 2008
@@ -90,10 +90,10 @@
     return OO_None;
   
   if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()))
-    return FDecl->getIdentifier()->getOverloadedOperatorID();  
+    return FDecl->getDeclName().getCXXOverloadedOperator();  
   else if (const OverloadedFunctionDecl *Ovl 
              = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()))
-    return Ovl->getIdentifier()->getOverloadedOperatorID();
+    return Ovl->getDeclName().getCXXOverloadedOperator();
   else
     return OO_None;
 }

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

==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Tue Nov 18 08:39:36 2008
@@ -28,7 +28,6 @@
 IdentifierInfo::IdentifierInfo() {
   TokenID = tok::identifier;
   ObjCOrBuiltinID = 0;
-  OperatorID = 0;
   HasMacro = false;
   IsExtension = false;
   IsPoisoned = false;
@@ -47,7 +46,6 @@
   // 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.
@@ -163,26 +161,6 @@
 #include "clang/Basic/TokenKinds.def"
 }
 
-/// addOperatorPrefix - Add the prefix "operator" (possible with a
-/// space after it) to the given operator symbol, and return the
-/// result.
-static std::string addOperatorPrefix(const char* Symbol) {
-  std::string result = "operator";
-  if (Symbol[0] >= 'a' && Symbol[0] <= 'z')
-    result += ' ';
-  result += Symbol;
-  return result;
-}
-
-/// AddOverloadedOperators - Register the name of all C++ overloadable
-/// operators ("operator+", "operator[]", etc.)
-void IdentifierTable::AddOverloadedOperators() {
-#define OVERLOADED_OPERATOR(Name,Spelling,Token, Unary, Binary, MemberOnly) \
-  OverloadedOperators[OO_##Name] = &get(addOperatorPrefix(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=59526&r1=59525&r2=59526&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Nov 18 08:39:36 2008
@@ -1460,8 +1460,8 @@
     SourceLocation OperatorLoc = Tok.getLocation();
 
     // First try the name of an overloaded operator
-    if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
-      D.SetIdentifier(II, OperatorLoc);
+    if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
+      D.setOverloadedOperator(Op, OperatorLoc);
     } else {
       // This must be a conversion function (C++ [class.conv.fct]).
       if (TypeTy *ConvType = ParseConversionFunctionId()) {

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Nov 18 08:39:36 2008
@@ -149,9 +149,9 @@
 
   case tok::kw_operator: {
     SourceLocation OperatorLoc = Tok.getLocation();
-    if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
-      return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II, 
-                                         Tok.is(tok::l_paren), &SS);
+    if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
+      return Actions.ActOnOperatorFunctionIdExpr(CurScope, OperatorLoc, Op, 
+                                                 Tok.is(tok::l_paren), &SS);
     } else if (TypeTy *Type = ParseConversionFunctionId()) {
       return Actions.ActOnConversionFunctionExpr(CurScope, OperatorLoc,
                                                  Type, Tok.is(tok::l_paren), 
@@ -534,7 +534,7 @@
 ///            ^=    &=   |= <<   >> >>= <<=  ==  !=
 ///            <=    >=   && ||   ++ --   ,   ->* ->
 ///            ()    []
-IdentifierInfo *Parser::TryParseOperatorFunctionId() {
+OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
   assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
 
   OverloadedOperatorKind Op = OO_None;
@@ -549,7 +549,7 @@
     } else {
       Op = OO_New;
     }
-    return &PP.getIdentifierTable().getOverloadedOperator(Op);
+    return Op;
 
   case tok::kw_delete:
     ConsumeToken(); // 'operator'
@@ -561,7 +561,7 @@
     } else {
       Op = OO_Delete;
     }
-    return &PP.getIdentifierTable().getOverloadedOperator(Op);
+    return Op;
 
 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)  \
     case tok::Token:  Op = OO_##Name; break;
@@ -572,21 +572,21 @@
     ConsumeToken(); // 'operator'
     ConsumeParen(); // '('
     ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
-    return &PP.getIdentifierTable().getOverloadedOperator(OO_Call);
+    return OO_Call;
 
   case tok::l_square:
     ConsumeToken(); // 'operator'
     ConsumeBracket(); // '['
     ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
-    return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript);
+    return OO_Subscript;
 
   default:
-    return 0;
+    return OO_None;
   }
 
   ConsumeToken(); // 'operator'
   ConsumeAnyToken(); // the operator itself
-  return &PP.getIdentifierTable().getOverloadedOperator(Op);
+  return Op;
 }
 
 /// ParseConversionFunctionId - Parse a C++ conversion-function-id,

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Nov 18 08:39:36 2008
@@ -615,6 +615,11 @@
                                          IdentifierInfo &II,
                                          bool HasTrailingLParen,
                                          const CXXScopeSpec *SS = 0);
+  virtual ExprResult ActOnOperatorFunctionIdExpr(Scope *S, 
+                                                 SourceLocation OperatorLoc,
+                                                 OverloadedOperatorKind Op,
+                                                 bool HasTrailingLParen,
+                                                 const CXXScopeSpec *SS = 0);
   virtual ExprResult ActOnConversionFunctionExpr(Scope *S, 
                                                  SourceLocation OperatorLoc,
                                                  TypeTy *Ty,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Nov 18 08:39:36 2008
@@ -783,6 +783,11 @@
     Ty = Context.getCanonicalType(Ty);
     return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
   }
+
+  case Declarator::DK_Operator:
+    assert(D.getIdentifier() == 0 && "operator names have no identifier");
+    return Context.DeclarationNames.getCXXOperatorName(
+                                                D.getOverloadedOperator());
   }
 
   assert(false && "Unknown name kind");

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Nov 18 08:39:36 2008
@@ -2839,7 +2839,7 @@
     OverloadedOperatorKind OverOp = OverOps[Opc];
 
     // Lookup this operator.
-    Decl *D = LookupDecl(&PP.getIdentifierTable().getOverloadedOperator(OverOp),
+    Decl *D = LookupDecl(Context.DeclarationNames.getCXXOperatorName(OverOp),
                          Decl::IDNS_Ordinary, S);
 
     // Add any overloaded operators we find to the overload set.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Nov 18 08:39:36 2008
@@ -70,6 +70,52 @@
   return new DeclRefExpr(Conversion, Conversion->getType(), OperatorLoc);
 }
 
+/// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
+/// name (e.g., @c operator+ ) as an expression. This is very
+/// similar to ActOnIdentifierExpr, except that instead of providing
+/// an identifier the parser provides the kind of overloaded
+/// operator that was parsed.
+Sema::ExprResult Sema::ActOnOperatorFunctionIdExpr(Scope *S, 
+                                                   SourceLocation OperatorLoc,
+                                                   OverloadedOperatorKind Op,
+                                                   bool HasTrailingLParen,
+                                                   const CXXScopeSpec *SS) {
+  DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op);
+  
+  Decl *D;
+  if (SS && !SS->isEmpty()) {
+    DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
+    if (DC == 0)
+      return true;
+    D = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);
+  } else
+    D = LookupDecl(Name, Decl::IDNS_Ordinary, S);
+  
+  if (D == 0) {
+    // If there is no conversion function that converts to this type,
+    // diagnose the problem.
+    if (SS && !SS->isEmpty())
+      return Diag(OperatorLoc, diag::err_typecheck_no_member,
+                  Name.getAsString(), SS->getRange());
+    else
+      return Diag(OperatorLoc, diag::err_undeclared_var_use,
+                  Name.getAsString());
+  }
+  
+  ValueDecl *VD = cast<ValueDecl>(D);
+
+  // check if referencing a declaration with __attribute__((deprecated)).
+  if (VD->getAttr<DeprecatedAttr>())
+    Diag(OperatorLoc, diag::warn_deprecated, Name.getAsString());
+
+  // Only create DeclRefExpr's for valid Decl's.
+  if (VD->isInvalidDecl())
+    return true;
+  
+  // Create a normal DeclRefExpr.
+  return new DeclRefExpr(VD, VD->getType(), OperatorLoc);
+}
+
 /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
 Action::ExprResult
 Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,

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=59526&r1=59525&r2=59526&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator-decl.cpp Tue Nov 18 08:39:36 2008
@@ -20,8 +20,7 @@
   x = operator+(x, x);
 }
 
-X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} \
-                         // expected-error{{previous definition is here}}
+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{{parameter of overloaded 'operator*' cannot have a default argument}}
 
@@ -37,4 +36,4 @@
 Y operator++(Y&, INT);
 X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'float')}}
 
-int operator+; // expected-error{{redefinition of 'operator+' as different kind of symbol}}
+int operator+; // expected-error{{'operator+' cannot be the name of a variable or data member}}





More information about the cfe-commits mailing list