]> granicus.if.org Git - clang/commitdiff
Updated IdentifierResolver to deal with DeclarationNames. The names of
authorDouglas Gregor <dgregor@apple.com>
Mon, 17 Nov 2008 20:34:05 +0000 (20:34 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 17 Nov 2008 20:34:05 +0000 (20:34 +0000)
C++ constructors, destructors, and conversion functions now have a
FETokenInfo field that IdentifierResolver can access, so that these
special names are handled just like ordinary identifiers. A few other
Sema routines now use DeclarationNames instead of IdentifierInfo*'s.

To validate this design, this code also implements parsing and
semantic analysis for id-expressions that name conversion functions,
e.g.,

  return operator bool();

The new parser action ActOnConversionFunctionExpr takes the result of
parsing "operator type-id" and turning it into an expression, using
the IdentifierResolver with the DeclarationName of the conversion
function. ActOnDeclarator pushes those conversion function names into
scope so that the IdentifierResolver can find them, of course.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59462 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
docs/InternalsManual.html
include/clang/AST/DeclBase.h
include/clang/AST/DeclarationName.h
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Action.h
lib/AST/DeclarationName.cpp
lib/Parse/MinimalAction.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/IdentifierResolver.cpp
lib/Sema/IdentifierResolver.h
lib/Sema/Sema.h
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/SemaChecking.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/conversion-function.cpp

index adfa7c3e7481c21120617a5043f49a9dd32addad..d9c2701f6e13f4914ea7b4e3de60399c53f775d0 100644 (file)
@@ -468,7 +468,7 @@ malloc'd objects are at least 8 byte aligned.</p>
 
 <p>Given
   a <code>DeclarationName</code> <code>N</code>, <code>N.getNameKind()</code>
-  will produce a valid that describes what kind of name <code>N</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
   the <code>DeclarationName</code> class)</p>
 <dl>
index 753d572fb3a631db86c55803921f4a8b16f667df..ba948078a6ca3b7ee2e84a45c1545a1824592cfe 100644 (file)
@@ -185,6 +185,7 @@ public:
     case OverloadedFunction:
     case CXXField:
     case CXXMethod:
+    case CXXConversion:
     case CXXClassVar:
       return IDNS_Ordinary;
     case Record:
index 385e2f34a342fdf074c28150eb716c48a6099bb0..909255c349524123bdea44595c82f73231405b45 100644 (file)
@@ -138,6 +138,10 @@ private:
 
   friend class DeclarationNameTable;
 
+  /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
+  /// for this name as a void pointer.
+  void *getFETokenInfoAsVoid() const;
+
 public:
   /// DeclarationName - Used to create an empty selector.
   DeclarationName() : Ptr(0) { }
@@ -150,6 +154,13 @@ public:
   // Construct a declaration name from an Objective-C selector.
   DeclarationName(Selector Sel);
 
+  // operator bool() - Evaluates true when this declaration name is
+  // non-empty.
+  operator bool() const { 
+    return ((Ptr & PtrMask) != 0) || 
+           (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
+  }
+
   /// getNameKind - Determine what kind of name this is.
   NameKind getNameKind() const;
 
@@ -176,6 +187,15 @@ public:
   /// declaration name.
   Selector getObjCSelector() const;
 
+  /// getFETokenInfo/setFETokenInfo - The language front-end is
+  /// allowed to associate arbitrary metadata with some kinds of
+  /// declaration names, including normal identifiers and C++
+  /// constructors, destructors, and conversion functions.
+  template<typename T>
+  T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
+
+  void setFETokenInfo(void *T);
+
   /// operator== - Determine whether the specified names are identical..
   friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
     return LHS.Ptr == RHS.Ptr;
index d1f72316c19799b879558fd8103ad05a6d07bf7f..c232eaa449c35037a7da7f5ef7cf79618df9b995 100644 (file)
@@ -1375,9 +1375,12 @@ DIAG(err_conv_function_redeclared, ERROR,
 DIAG(warn_conv_to_self_not_used, WARNING,
      "conversion function converting '%0' to itself will never be used")
 DIAG(warn_conv_to_base_not_used, WARNING,
-     "conversion function converting '%0' to its base class '%1' will never be used")
+     "conversion function converting '%0' to its base class '%1' will never "
+     "be used")
 DIAG(warn_conv_to_void_not_used, WARNING,
      "conversion function converting '%0' to '%1' will never be used")
+DIAG(err_no_conv_function, ERROR,
+     "no conversion function to type '%0'")
 
 
 DIAG(warn_not_compound_assign, WARNING,
index 4aa900f6285a2b2daf35b245913f52d2d9c31e8c..313e86f5c56ec50ba7533724c38c380054486d30 100644 (file)
@@ -108,7 +108,7 @@ public:
   /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
   /// namespace) that the identifier must be a member of.
   /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
-  virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+  virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
                              const CXXScopeSpec *SS = 0) = 0;
 
   /// isCurrentClassName - Return true if the specified name is the
@@ -133,7 +133,7 @@ public:
                                                   const CXXScopeSpec &SS,
                                                   SourceLocation IdLoc,
                                                   SourceLocation CCLoc,
-                                                  const IdentifierInfo &II) {
+                                                  IdentifierInfo &II) {
     return 0;
   }
 
@@ -461,6 +461,19 @@ public:
     return 0;
   }
   
+  /// ActOnConversionFunctionExpr - Parse a C++ conversion function
+  /// name (e.g., 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.
+  virtual ExprResult ActOnConversionFunctionExpr(Scope *S, 
+                                                 SourceLocation OperatorLoc,
+                                                 TypeTy *Type,
+                                                 bool HasTrailingLParen,
+                                                 const CXXScopeSpec *SS = 0) {
+    return 0;
+  }
+
   virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc,
                                          tok::TokenKind Kind) {
     return 0;
@@ -1016,7 +1029,7 @@ public:
   
   /// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
   /// determine whether the name is a typedef or not in this scope.
-  virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+  virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
                              const CXXScopeSpec *SS);
 
   /// isCurrentClassName - Always returns false, because MinimalAction
index 96e194be8c9bed9c5b063478bcd61886b99a7c85..4266ef5eaf82fa58048458002567fbfd82d9ccc2 100644 (file)
@@ -25,8 +25,13 @@ namespace clang {
 class CXXSpecialName 
   : public DeclarationNameExtra, public llvm::FoldingSetNode {
 public:
+  /// Type - The type associated with this declaration name.
   QualType Type;
 
+  /// FETokenInfo - Extra information associated with this declaration
+  /// name that can be used by the front end.
+  void *FETokenInfo;
+
   void Profile(llvm::FoldingSetNodeID &ID) {
     ID.AddInteger(ExtraKindOrNumArgs);
     ID.AddPointer(Type.getAsOpaquePtr());
@@ -114,6 +119,39 @@ Selector DeclarationName::getObjCSelector() const {
   return Selector();
 }
 
+void *DeclarationName::getFETokenInfoAsVoid() const {
+  switch (getNameKind()) {
+  case Identifier:
+    return getAsIdentifierInfo()->getFETokenInfo<void>();
+
+  case CXXConstructorName:
+  case CXXDestructorName:
+  case CXXConversionFunctionName:
+    return getAsCXXSpecialName()->FETokenInfo;
+
+  default:
+    assert(false && "Declaration name has no FETokenInfo");
+  }
+  return 0;
+}
+
+void DeclarationName::setFETokenInfo(void *T) {
+  switch (getNameKind()) {
+  case Identifier:
+    getAsIdentifierInfo()->setFETokenInfo(T);
+    break;
+
+  case CXXConstructorName:
+  case CXXDestructorName:
+  case CXXConversionFunctionName:
+    getAsCXXSpecialName()->FETokenInfo = T;
+    break;
+
+  default:
+    assert(false && "Declaration name has no FETokenInfo");
+  }
+}
+
 DeclarationNameTable::DeclarationNameTable() {
   CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
 }
@@ -159,6 +197,7 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
   CXXSpecialName *SpecialName = new CXXSpecialName;
   SpecialName->ExtraKindOrNumArgs = EKind;
   SpecialName->Type = Ty;
+  SpecialName->FETokenInfo = 0;
 
   SpecialNames->InsertNode(SpecialName, InsertPos);
   return DeclarationName(SpecialName);
index 58e391ee376999239ea2d7bab356d0309b6fa744..583781056e0b91212dde12e92363dbea075f399b 100644 (file)
@@ -58,7 +58,7 @@ void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
 ///
 /// FIXME: Use the passed CXXScopeSpec for accurate C++ type checking.
 Action::TypeTy *
-MinimalAction::isTypeName(const IdentifierInfo &II, Scope *S,
+MinimalAction::isTypeName(IdentifierInfo &II, Scope *S,
                           const CXXScopeSpec *SS) {
   if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
     if (TI->isTypeName)
index 8f14ce50b8d734be00ee771061fb8cca019a07f4..19b521b264191231c7a1b062b1fcee1d98f56693 100644 (file)
@@ -131,7 +131,7 @@ Parser::ExprResult Parser::ParseCXXIdExpression() {
   // unqualified-id:
   //   identifier
   //   operator-function-id
-  //   conversion-function-id                [TODO]
+  //   conversion-function-id
   //   '~' class-name                        [TODO]
   //   template-id                           [TODO]
   //
@@ -152,11 +152,15 @@ Parser::ExprResult Parser::ParseCXXIdExpression() {
     if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
       return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II, 
                                          Tok.is(tok::l_paren), &SS);
+    } else if (TypeTy *Type = ParseConversionFunctionId()) {
+      return Actions.ActOnConversionFunctionExpr(CurScope, OperatorLoc,
+                                                 Type, Tok.is(tok::l_paren), 
+                                                 &SS);
     }
-    // FIXME: Handle conversion-function-id.
-    unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error,
-                                    "expected operator-function-id");
-    return Diag(Tok, DiagID);
+     
+    // We already complained about a bad conversion-function-id,
+    // above.
+    return true;
   }
 
   } // switch.
index 82f95bf1082ee55ed622b3a473a53ebf57c2df87..cf0342fe1b33323656031a99beba4fb9aa2d3421 100644 (file)
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements the IdentifierResolver class, which is used for lexical
-// scoped lookup, based on identifier.
+// scoped lookup, based on declaration names.
 //
 //===----------------------------------------------------------------------===//
 
@@ -23,7 +23,7 @@ using namespace clang;
 // IdDeclInfoMap class
 //===----------------------------------------------------------------------===//
 
-/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
+/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
 /// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
 /// individual IdDeclInfo to heap.
 class IdentifierResolver::IdDeclInfoMap {
@@ -36,9 +36,9 @@ class IdentifierResolver::IdDeclInfoMap {
 public:
   IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
 
-  /// Returns the IdDeclInfo associated to the IdentifierInfo.
+  /// Returns the IdDeclInfo associated to the DeclarationName.
   /// It creates a new IdDeclInfo if one was not created before for this id.
-  IdDeclInfo &operator[](IdentifierInfo *II);
+  IdDeclInfo &operator[](DeclarationName Name);
 };
 
 
@@ -173,19 +173,19 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
 
 /// AddDecl - Link the decl to its shadowed decl chain.
 void IdentifierResolver::AddDecl(NamedDecl *D) {
-  IdentifierInfo *II = D->getIdentifier();
-  void *Ptr = II->getFETokenInfo<void>();
+  DeclarationName Name = D->getDeclName();
+  void *Ptr = Name.getFETokenInfo<void>();
 
   if (!Ptr) {
-    II->setFETokenInfo(D);
+    Name.setFETokenInfo(D);
     return;
   }
 
   IdDeclInfo *IDI;
 
   if (isDeclPtr(Ptr)) {
-    II->setFETokenInfo(NULL);
-    IDI = &(*IdDeclInfos)[II];
+    Name.setFETokenInfo(NULL);
+    IDI = &(*IdDeclInfos)[Name];
     NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
     IDI->AddDecl(PrevD);
   } else
@@ -198,18 +198,18 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
 /// after the decl that the iterator points to, thus the 'Shadow' decl will be
 /// encountered before the 'D' decl.
 void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
-  assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
+  assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
   assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
 
-  IdentifierInfo *II = D->getIdentifier();
-  void *Ptr = II->getFETokenInfo<void>();
+  DeclarationName Name = D->getDeclName();
+  void *Ptr = Name.getFETokenInfo<void>();
   assert(Ptr && "No decl from Ptr ?");
 
   IdDeclInfo *IDI;
 
   if (isDeclPtr(Ptr)) {
-    II->setFETokenInfo(NULL);
-    IDI = &(*IdDeclInfos)[II];
+    Name.setFETokenInfo(NULL);
+    IDI = &(*IdDeclInfos)[Name];
     NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
     assert(PrevD == Shadow && "Invalid shadow decl ?");
     IDI->AddDecl(D);
@@ -225,29 +225,29 @@ void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
 /// The decl must already be part of the decl chain.
 void IdentifierResolver::RemoveDecl(NamedDecl *D) {
   assert(D && "null param passed");
-  IdentifierInfo *II = D->getIdentifier();
-  void *Ptr = II->getFETokenInfo<void>();
+  DeclarationName Name = D->getDeclName();
+  void *Ptr = Name.getFETokenInfo<void>();
 
   assert(Ptr && "Didn't find this decl on its identifier's chain!");
 
   if (isDeclPtr(Ptr)) {
     assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
-    II->setFETokenInfo(NULL);
+    Name.setFETokenInfo(NULL);
     return;
   }
   
   return toIdDeclInfo(Ptr)->RemoveDecl(D);
 }
 
-/// begin - Returns an iterator for decls of identifier 'II', starting at
+/// begin - Returns an iterator for decls with name 'Name', starting at
 /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
 /// decls of parent declaration contexts too.
 IdentifierResolver::iterator
-IdentifierResolver::begin(const IdentifierInfo *II, const DeclContext *Ctx,
+IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx,
                           bool LookInParentCtx) {
   assert(Ctx && "null param passed");
 
-  void *Ptr = II->getFETokenInfo<void>();
+  void *Ptr = Name.getFETokenInfo<void>();
   if (!Ptr) return end();
 
   LookupContext LC(Ctx);
@@ -284,7 +284,7 @@ IdentifierResolver::begin(const IdentifierInfo *II, const DeclContext *Ctx,
 void IdentifierResolver::iterator::PreIncIter() {
   NamedDecl *D = **this;
   LookupContext Ctx(D);
-  void *InfoPtr = D->getIdentifier()->getFETokenInfo<void>();
+  void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
   assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
   IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
 
@@ -310,12 +310,11 @@ void IdentifierResolver::iterator::PreIncIter() {
 // IdDeclInfoMap Implementation
 //===----------------------------------------------------------------------===//
 
-/// Returns the IdDeclInfo associated to the IdentifierInfo.
+/// Returns the IdDeclInfo associated to the DeclarationName.
 /// It creates a new IdDeclInfo if one was not created before for this id.
 IdentifierResolver::IdDeclInfo &
-IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
-  assert (II && "null IdentifierInfo passed");
-  void *Ptr = II->getFETokenInfo<void>();
+IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
+  void *Ptr = Name.getFETokenInfo<void>();
 
   if (Ptr) return *toIdDeclInfo(Ptr);
 
@@ -327,7 +326,7 @@ IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
     CurIndex = 0;
   }
   IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
-  II->setFETokenInfo(reinterpret_cast<void*>(
+  Name.setFETokenInfo(reinterpret_cast<void*>(
                               reinterpret_cast<uintptr_t>(IDI) | 0x1)
                                                                      );
   ++CurIndex;
index e76bec6ee2508e27b760dc5071c917b76c299e72..5a0f7467766fd63f914894ece878af4d554f3709 100644 (file)
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file defines the IdentifierResolver class, which is used for lexical
-// scoped lookup, based on identifier.
+// scoped lookup, based on declaration names.
 //
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Parse/Scope.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/DeclCXX.h"
 
 namespace clang {
 
-/// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes.
-/// It manages the shadowing chains of identifiers and implements efficent decl
-/// lookup based on an identifier.
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes.  It manages the shadowing chains of declaration names and
+/// implements efficent decl lookup based on a declaration name.
 class IdentifierResolver {
 
   /// LookupContext - A wrapper for DeclContext. DeclContext is only part of
@@ -79,10 +80,10 @@ class IdentifierResolver {
     }
   };
 
-  /// IdDeclInfo - Keeps track of information about decls associated to a
-  /// particular identifier. IdDeclInfos are lazily constructed and assigned
-  /// to an identifier the first time a decl with that identifier is shadowed
-  /// in some scope.
+  /// IdDeclInfo - Keeps track of information about decls associated
+  /// to a particular declaration name. IdDeclInfos are lazily
+  /// constructed and assigned to a declaration name the first time a
+  /// decl with that declaration name is shadowed in some scope.
   class IdDeclInfo {
   public:
     typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
@@ -123,7 +124,7 @@ class IdentifierResolver {
 
 public:
 
-  /// iterator - Iterate over the decls of a specified identifier.
+  /// iterator - Iterate over the decls of a specified declaration name.
   /// It will walk or not the parent declaration contexts depending on how
   /// it was instantiated.
   class iterator {
@@ -192,11 +193,11 @@ public:
     void PreIncIter();
   };
 
-  /// begin - Returns an iterator for decls of identifier 'II', starting at
+  /// begin - Returns an iterator for decls with the name 'Name', starting at
   /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
   /// decls of parent declaration contexts too.
   /// Default for 'LookInParentCtx is true.
-  static iterator begin(const IdentifierInfo *II, const DeclContext *Ctx,
+  static iterator begin(DeclarationName Name, const DeclContext *Ctx,
                         bool LookInParentCtx = true);
 
   /// end - Returns an iterator that has 'finished'.
@@ -230,12 +231,12 @@ private:
   class IdDeclInfoMap;
   IdDeclInfoMap *IdDeclInfos;
 
-  /// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
+  /// FETokenInfo contains a Decl pointer if lower bit == 0.
   static inline bool isDeclPtr(void *Ptr) {
     return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
   }
 
-  /// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+  /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
   static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
     assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
           && "Ptr not a IdDeclInfo* !");
index efe481abaef0460a66c66be26d96ddeb301bb43a..50a12f13855045dd4a58853e424ac3173b50fc14 100644 (file)
@@ -282,7 +282,7 @@ public:
   //===--------------------------------------------------------------------===//
   // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
   //
-  virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+  virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
                              const CXXScopeSpec *SS);
   virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup);
   virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D);
@@ -462,7 +462,7 @@ public:
   void CheckExtraCXXDefaultArguments(Declarator &D);
 
   /// More parsing and symbol table subroutines...
-  Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
+  Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
                    const DeclContext *LookupCtx = 0,
                    bool enableLazyBuiltinCreation = true);
   ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
@@ -614,6 +614,11 @@ public:
                                          IdentifierInfo &II,
                                          bool HasTrailingLParen,
                                          const CXXScopeSpec *SS = 0);
+  virtual ExprResult ActOnConversionFunctionExpr(Scope *S, 
+                                                 SourceLocation OperatorLoc,
+                                                 TypeTy *Ty,
+                                                 bool HasTrailingLParen,
+                                                 const CXXScopeSpec *SS);
   virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc,
                                          tok::TokenKind Kind);
   virtual ExprResult ActOnNumericConstant(const Token &);
@@ -820,7 +825,7 @@ public:
                                                   const CXXScopeSpec &SS,
                                                   SourceLocation IdLoc,
                                                   SourceLocation CCLoc,
-                                                  const IdentifierInfo &II);
+                                                  IdentifierInfo &II);
 
   /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
   /// scope or nested-name-specifier) is parsed, part of a declarator-id.
index 14805279b03d5e72483320d2b472f8d23827d1fd..f22ca0c712cbfd84cd36ab620a8db496475b5436 100644 (file)
@@ -20,9 +20,9 @@ using namespace clang;
 \r
 namespace {\r
   Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,\r
-                         const IdentifierInfo &II, bool &IdIsUndeclared) {\r
+                         DeclarationName Name, bool &IdIsUndeclared) {\r
     IdentifierResolver::iterator\r
-      I = IdentifierResolver::begin(&II, LookupCtx, LookInParentCtx),\r
+      I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),\r
       E = IdentifierResolver::end();\r
 \r
     if (I == E) {\r
@@ -67,15 +67,16 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
                                                     const CXXScopeSpec &SS,\r
                                                     SourceLocation IdLoc,\r
                                                     SourceLocation CCLoc,\r
-                                                    const IdentifierInfo &II) {\r
+                                                    IdentifierInfo &II) {\r
   DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());\r
   Decl *SD;\r
   bool IdIsUndeclared;\r
 \r
   if (DC)\r
-    SD = LookupNestedName(DC, false/*LookInParentCtx*/, II, IdIsUndeclared);\r
+    SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);\r
   else\r
-    SD = LookupNestedName(CurContext, true/*LookInParent*/, II, IdIsUndeclared);\r
+    SD = LookupNestedName(CurContext, true/*LookInParent*/, &II, \r
+                          IdIsUndeclared);\r
 \r
   if (SD) {\r
     if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {\r
index 816d6fd05d60bd672c6ec2f934f926a8130f95a5..49c153d8c86196da84b2097cf67a86d0da675858 100644 (file)
@@ -29,7 +29,12 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) {
   llvm::OwningPtr<CallExpr> TheCall(TheCallRaw);
   // Get the IdentifierInfo* for the called function.
   IdentifierInfo *FnInfo = FDecl->getIdentifier();
-  
+
+  // None of the checks below are needed for functions that don't have
+  // simple names (e.g., C++ conversion functions).
+  if (!FnInfo)
+    return TheCall.take();
+
   switch (FnInfo->getBuiltinID()) {
   case Builtin::BI__builtin___CFStringMakeConstantString:
     assert(TheCall->getNumArgs() == 1 &&
index 48073694a32c3254ff9a9aeb7c15558c9f7f3f32..ea2a3ad9a75d4bececca555ad2d85b568ecf85b7 100644 (file)
@@ -28,7 +28,7 @@
 #include "llvm/ADT/StringExtras.h"
 using namespace clang;
 
-Sema::TypeTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S,
+Sema::TypeTy *Sema::isTypeName(IdentifierInfo &II, Scope *S,
                                const CXXScopeSpec *SS) {
   DeclContext *DC = 0;
   if (SS) {
@@ -113,7 +113,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
     // We are pushing the name of a function, which might be an
     // overloaded name.
     IdentifierResolver::iterator
-        I = IdResolver.begin(FD->getIdentifier(),
+        I = IdResolver.begin(FD->getDeclName(),
                              FD->getDeclContext(), false/*LookInParentCtx*/);
     if (I != IdResolver.end() &&
         IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
@@ -126,7 +126,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
         // FunctionDecl and put it into an OverloadedFunctionDecl.
         Ovl = OverloadedFunctionDecl::Create(Context, 
                                              FD->getDeclContext(),
-                                             FD->getIdentifier());
+                                             FD->getDeclName());
         Ovl->addOverload(dyn_cast<FunctionDecl>(*I));
         
         // Remove the name binding to the existing FunctionDecl...
@@ -187,17 +187,17 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
 
 /// LookupDecl - Look up the inner-most declaration in the specified
 /// namespace.
-Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
+Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
                        const DeclContext *LookupCtx,
                        bool enableLazyBuiltinCreation) {
-  if (II == 0) return 0;
+  if (!Name) return 0;
   unsigned NS = NSI;
   if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
     NS |= Decl::IDNS_Tag;
 
   IdentifierResolver::iterator 
-    I = LookupCtx ? IdResolver.begin(II, LookupCtx, false/*LookInParentCtx*/) :
-                    IdResolver.begin(II, CurContext, true/*LookInParentCtx*/);
+    I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/)
+                  : IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/);
   // Scan up the scope chain looking for a decl that matches this identifier
   // that is in the appropriate namespace.  This search should not take long, as
   // shadowing of names is uncommon, and deep shadowing is extremely uncommon.
@@ -209,13 +209,14 @@ Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
   // corresponds to a compiler builtin, create the decl object for the builtin
   // now, injecting it into translation unit scope, and return it.
   if (NS & Decl::IDNS_Ordinary) {
-    if (enableLazyBuiltinCreation &&
+    IdentifierInfo *II = Name.getAsIdentifierInfo();
+    if (enableLazyBuiltinCreation && II &&
         (LookupCtx == 0 || isa<TranslationUnitDecl>(LookupCtx))) {
       // If this is a builtin on this (or all) targets, create the decl.
       if (unsigned BuiltinID = II->getBuiltinID())
         return LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S);
     }
-    if (getLangOptions().ObjC1) {
+    if (getLangOptions().ObjC1 && II) {
       // @interface and @compatibility_alias introduce typedef-like names.
       // Unlike typedef's, they can only be introduced at file-scope (and are 
       // therefore not scoped decls). They can, however, be shadowed by
@@ -1034,8 +1035,11 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       return ActOnConstructorDeclarator(Constructor);
     else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
       return ActOnDestructorDeclarator(Destructor);
-    else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
-      return ActOnConversionDeclarator(Conversion);
+    
+    // Extra checking for conversion functions, including recording
+    // the conversion function in its class.
+    if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+      ActOnConversionDeclarator(Conversion);
 
     // Extra checking for C++ overloaded operators (C++ [over.oper]).
     if (NewFD->isOverloadedOperator() &&
index e420ce59916769868805232b49bdc50c4ee66a56..e49ef27af7766a7fdd3a9ed07db91128c584ed7a 100644 (file)
 #include "clang/Basic/Diagnostic.h"
 using namespace clang;
 
+/// ActOnConversionFunctionExpr - Parse a C++ conversion function
+/// name (e.g., 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.
+Sema::ExprResult Sema::ActOnConversionFunctionExpr(Scope *S, 
+                                                   SourceLocation OperatorLoc,
+                                                   TypeTy *Ty,
+                                                   bool HasTrailingLParen,
+                                                   const CXXScopeSpec *SS) {
+  QualType ConvType = QualType::getFromOpaquePtr(Ty);
+  QualType ConvTypeCanon = Context.getCanonicalType(ConvType);
+  DeclarationName ConvName 
+    = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
+
+  // We only expect to find a CXXConversionDecl.
+  Decl *D;
+  if (SS && !SS->isEmpty()) {
+    DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
+    if (DC == 0)
+      return true;
+    D = LookupDecl(ConvName, Decl::IDNS_Ordinary, S, DC);
+  } else
+    D = LookupDecl(ConvName, 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,
+                  ConvType.getAsString(), SS->getRange());
+    else
+      return Diag(OperatorLoc, diag::err_no_conv_function, 
+                  ConvType.getAsString());
+  }
+  
+  assert(isa<CXXConversionDecl>(D) && "we had to find a conversion function");
+  CXXConversionDecl *Conversion = cast<CXXConversionDecl>(D);
+
+  // check if referencing a declaration with __attribute__((deprecated)).
+  if (Conversion->getAttr<DeprecatedAttr>())
+    Diag(OperatorLoc, diag::warn_deprecated, Conversion->getName());
+
+  // Only create DeclRefExpr's for valid Decl's.
+  if (Conversion->isInvalidDecl())
+    return true;
+  
+  // Create a normal DeclRefExpr.
+  return new DeclRefExpr(Conversion, Conversion->getType(), OperatorLoc);
+}
 
 /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
 Action::ExprResult
index 3c96e54c53175f972057634fd7117dc249722d66..6450387b02c1688b780f16c1b2342210ff482cbe 100644 (file)
@@ -3,6 +3,14 @@ class X {
 public:
   operator bool();
   operator int() const;
+
+  bool f() {
+    return operator bool();
+  }
+
+  float g() {
+    return operator float(); // expected-error{{no conversion function to type 'float'}}
+  }
 };
 
 operator int(); // expected-error{{conversion function must be a non-static member function}}