]> granicus.if.org Git - clang/commitdiff
Make yet another placeholder type, this one marking that an expression is a bound
authorJohn McCall <rjmccall@apple.com>
Tue, 26 Apr 2011 20:42:42 +0000 (20:42 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 26 Apr 2011 20:42:42 +0000 (20:42 +0000)
member function, i.e. something of the form 'x.f' where 'f' is a non-static
member function.  Diagnose this in the general case.  Some of the new diagnostics
are probably worse than the old ones, but we now get this right much more
universally, and there's certainly room for improvement in the diagnostics.

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

30 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/Expr.h
include/clang/AST/Type.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/MicrosoftMangle.cpp
lib/AST/Type.cpp
lib/AST/TypeLoc.cpp
lib/CodeGen/CGExprCXX.cpp
lib/CodeGen/CGRTTI.cpp
lib/CodeGen/CodeGenTypes.cpp
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaStmt.cpp
lib/Serialization/ASTCommon.cpp
lib/Serialization/ASTReader.cpp
test/CXX/over/over.over/p2-resolve-single-template-id.cpp
test/SemaCXX/addr-of-overloaded-function.cpp
test/SemaCXX/expression-traits.cpp
test/SemaCXX/overloaded-operator.cpp
test/SemaCXX/ptrtomember.cpp
tools/libclang/CIndex.cpp
tools/libclang/CIndexUSRs.cpp

index 820c5a288d5abf745dbcf770a3887dbc1aed79e2..959e158cebcf5d02ceb384a43604a716f92d0b7d 100644 (file)
@@ -426,7 +426,7 @@ public:
   CanQualType FloatTy, DoubleTy, LongDoubleTy;
   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
   CanQualType VoidPtrTy, NullPtrTy;
-  CanQualType OverloadTy, DependentTy, UnknownAnyTy;
+  CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
 
   // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
index 2969b752336ea39237da5c14c0c9793499feafb1..ed207ace0c3121b6f74ebe20cc4ea5e6aeffcca4 100644 (file)
@@ -486,6 +486,11 @@ public:
   /// \brief Returns true if this expression is a bound member function.
   bool isBoundMemberFunction(ASTContext &Ctx) const;
 
+  /// \brief Given an expression of bound-member type, find the type
+  /// of the member.  Returns null if this is an *overloaded* bound
+  /// member expression.
+  static QualType findBoundMemberType(const Expr *expr);
+
   /// \brief Result type of CanThrow().
   enum CanThrowResult {
     CT_Cannot,
index 9ed30563598aaba224ed8f56ef6c100b91c3df26..cfdfae1ee36a91f83f6ff104f36127bb21b99862 100644 (file)
@@ -1190,6 +1190,9 @@ public:
   /// BuiltinTypes.
   bool isPlaceholderType() const;
 
+  /// isSpecificPlaceholderType - Test for a specific placeholder type.
+  bool isSpecificPlaceholderType(unsigned K) const;
+
   /// isIntegerType() does *not* include complex integers (a GCC extension).
   /// isComplexIntegerType() can be used to test for complex integers.
   bool isIntegerType() const;     // C99 6.2.5p17 (int, char, bool, enum)
@@ -1488,32 +1491,52 @@ public:
 
     NullPtr,  // This is the type of C++0x 'nullptr'.
 
+    /// The primitive Objective C 'id' type.  The user-visible 'id'
+    /// type is a typedef of an ObjCObjectPointerType to an
+    /// ObjCObjectType with this as its base.  In fact, this only ever
+    /// shows up in an AST as the base type of an ObjCObjectType.
+    ObjCId,
+
+    /// The primitive Objective C 'Class' type.  The user-visible
+    /// 'Class' type is a typedef of an ObjCObjectPointerType to an
+    /// ObjCObjectType with this as its base.  In fact, this only ever
+    /// shows up in an AST as the base type of an ObjCObjectType.
+    ObjCClass,
+
+    /// The primitive Objective C 'SEL' type.  The user-visible 'SEL'
+    /// type is a typedef of a PointerType to this.
+    ObjCSel,
+
     /// This represents the type of an expression whose type is
     /// totally unknown, e.g. 'T::foo'.  It is permitted for this to
     /// appear in situations where the structure of the type is
     /// theoretically deducible.
     Dependent,
 
-    /// The type of an unresolved overload set.
+    /// The type of an unresolved overload set.  A placeholder type.
+    /// Expressions with this type have one of the following basic
+    /// forms, with parentheses generally permitted:
+    ///   foo          # possibly qualified, not if an implicit access
+    ///   foo          # possibly qualified, not if an implicit access
+    ///   &foo         # possibly qualified, not if an implicit access
+    ///   x->foo       # only if might be a static member function
+    ///   &x->foo      # only if might be a static member function
+    ///   &Class::foo  # when a pointer-to-member; sub-expr also has this type
+    /// OverloadExpr::find can be used to analyze the expression.
     Overload,
 
-    /// __builtin_any_type.  Useful for clients like debuggers
-    /// that don't know what type to give something.  Only a small
-    /// number of operations are valid on expressions of unknown type;
-    /// notable among them, calls and explicit casts.
-    UnknownAny,
-
-    /// The primitive Objective C 'id' type.  The type pointed to by the
-    /// user-visible 'id' type.  Only ever shows up in an AST as the base
-    /// type of an ObjCObjectType.
-    ObjCId,
-
-    /// The primitive Objective C 'Class' type.  The type pointed to by the
-    /// user-visible 'Class' type.  Only ever shows up in an AST as the
-    /// base type of an ObjCObjectType.
-    ObjCClass,
-
-    ObjCSel    // This represents the ObjC 'SEL' type.
+    /// The type of a bound C++ non-static member function.
+    /// A placeholder type.  Expressions with this type have one of the
+    /// following basic forms:
+    ///   foo          # if an implicit access
+    ///   x->foo       # if only contains non-static members
+    BoundMember,
+
+    /// __builtin_any_type.  A placeholder type.  Useful for clients
+    /// like debuggers that don't know what type to give something.
+    /// Only a small number of operations are valid on expressions of
+    /// unknown type, most notably explicit casts.
+    UnknownAny
   };
 
 public:
@@ -1546,11 +1569,11 @@ public:
     return getKind() >= Float && getKind() <= LongDouble;
   }
 
-  /// Determines whether this type is a "forbidden" placeholder type,
-  /// i.e. a type which cannot appear in arbitrary positions in a
-  /// fully-formed expression.
+  /// Determines whether this type is a placeholder type, i.e. a type
+  /// which cannot appear in arbitrary positions in a fully-formed
+  /// expression.
   bool isPlaceholderType() const {
-    return getKind() == Overload || getKind() == UnknownAny;
+    return getKind() >= Overload;
   }
 
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
@@ -4300,6 +4323,12 @@ inline bool Type::isPlaceholderType() const {
   return false;
 }
 
+inline bool Type::isSpecificPlaceholderType(unsigned K) const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+    return (BT->getKind() == (BuiltinType::Kind) K);
+  return false;
+}
+
 /// \brief Determines whether this is a type for which one can define
 /// an overloaded operator.
 inline bool Type::isOverloadableType() const {
index 0e813a6e123f387f7ebc7a3153406dec5c77c83f..b3d4890fdafefd3e299deb97e8ee68eb102faa24 100644 (file)
@@ -112,6 +112,7 @@ namespace clang {
   class ObjCPropertyDecl;
   class ObjCProtocolDecl;
   class OverloadCandidateSet;
+  class OverloadExpr;
   class ParenListExpr;
   class ParmVarDecl;
   class Preprocessor;
@@ -1413,7 +1414,7 @@ public:
                                                    bool Complain,
                                                    DeclAccessPair &Found);
 
-  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From,
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
                                                    bool Complain = false,
                                                    DeclAccessPair* Found = 0);
 
index 72252d4da80d2b044c8eb40bbdc4db830d162e0a..06be21791566fcb9671d0af8b8676c610c14f6a4 100644 (file)
@@ -491,8 +491,10 @@ namespace clang {
       PREDEF_TYPE_OBJC_CLASS    = 27,
       /// \brief The ObjC 'SEL' type.
       PREDEF_TYPE_OBJC_SEL      = 28,
-      /// \brief The 'unknown any' type.
-      PREDEF_TYPE_UNKNOWN_ANY   = 29
+      /// \brief The 'unknown any' placeholder type.
+      PREDEF_TYPE_UNKNOWN_ANY   = 29,
+      /// \brief The placeholder type for bound member functions.
+      PREDEF_TYPE_BOUND_MEMBER  = 30
     };
 
     /// \brief The number of predefined type IDs that are reserved for
index 3d74d3a9380af93f6278333e36e49472d2548443..a31969dc9077a9250b0e394507523465bfebbcf5 100644 (file)
@@ -402,6 +402,9 @@ void ASTContext::InitBuiltinTypes() {
   // Placeholder type for functions.
   InitBuiltinType(OverloadTy,          BuiltinType::Overload);
 
+  // Placeholder type for bound members.
+  InitBuiltinType(BoundMemberTy,       BuiltinType::BoundMember);
+
   // "any" type; useful for debugger-like clients.
   InitBuiltinType(UnknownAnyTy,        BuiltinType::UnknownAny);
 
index 2b15904fdba5c6535e1f9feda094b87e57c5dbb2..7c45543f66a24bc6fc3f79bdc5ddaf2347e7081e 100644 (file)
@@ -1363,6 +1363,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
   case BuiltinType::Overload: return Importer.getToContext().OverloadTy;
   case BuiltinType::Dependent: return Importer.getToContext().DependentTy;
   case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy;
+  case BuiltinType::BoundMember: return Importer.getToContext().BoundMemberTy;
 
   case BuiltinType::ObjCId:
     // FIXME: Make sure that the "to" context supports Objective-C!
index dd1a317f4a17be0ddfb8928427b7a3790ad73091..2a5917c4594bbc812f85164233a4cbae7f8ab1a9 100644 (file)
@@ -820,11 +820,11 @@ QualType CallExpr::getCallReturnType() const {
     CalleeType = FnTypePtr->getPointeeType();
   else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
     CalleeType = BPT->getPointeeType();
-  else if (const MemberPointerType *MPT
-                                      = CalleeType->getAs<MemberPointerType>())
-    CalleeType = MPT->getPointeeType();
+  else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember))
+    // This should never be overloaded and so should never return null.
+    CalleeType = Expr::findBoundMemberType(getCallee());
     
-  const FunctionType *FnType = CalleeType->getAs<FunctionType>();
+  const FunctionType *FnType = CalleeType->castAs<FunctionType>();
   return FnType->getResultType();
 }
 
@@ -1623,6 +1623,30 @@ bool Expr::isBoundMemberFunction(ASTContext &Ctx) const {
   return ClassifyLValue(Ctx) == Expr::LV_MemberFunction;
 }
 
+QualType Expr::findBoundMemberType(const Expr *expr) {
+  assert(expr->getType()->isSpecificPlaceholderType(BuiltinType::BoundMember));
+
+  // Bound member expressions are always one of these possibilities:
+  //   x->m      x.m      x->*y      x.*y
+  // (possibly parenthesized)
+
+  expr = expr->IgnoreParens();
+  if (const MemberExpr *mem = dyn_cast<MemberExpr>(expr)) {
+    assert(isa<CXXMethodDecl>(mem->getMemberDecl()));
+    return mem->getMemberDecl()->getType();
+  }
+
+  if (const BinaryOperator *op = dyn_cast<BinaryOperator>(expr)) {
+    QualType type = op->getRHS()->getType()->castAs<MemberPointerType>()
+                      ->getPointeeType();
+    assert(type->isFunctionType());
+    return type;
+  }
+
+  assert(isa<UnresolvedMemberExpr>(expr));
+  return QualType();
+}
+
 static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1,
                                           Expr::CanThrowResult CT2) {
   // CanThrowResult constants are ordered so that the maximum is the correct
index 127431ba7d661f1c3399cecc8cb891f3b300fbc4..1a1a0a36a65b43664398cda90b9512c92fec58e4 100644 (file)
@@ -837,6 +837,28 @@ bool CXXDependentScopeMemberExpr::isImplicitAccess() const {
   return cast<Expr>(Base)->isImplicitCXXThis();
 }
 
+static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,
+                                            UnresolvedSetIterator end) {
+  do {
+    NamedDecl *decl = *begin;
+    if (isa<UnresolvedUsingValueDecl>(decl))
+      return false;
+    if (isa<UsingShadowDecl>(decl))
+      decl = cast<UsingShadowDecl>(decl)->getUnderlyingDecl();
+
+    // Unresolved member expressions should only contain methods and
+    // method templates.
+    assert(isa<CXXMethodDecl>(decl) || isa<FunctionTemplateDecl>(decl));
+
+    if (isa<FunctionTemplateDecl>(decl))
+      decl = cast<FunctionTemplateDecl>(decl)->getTemplatedDecl();
+    if (cast<CXXMethodDecl>(decl)->isStatic())
+      return false;
+  } while (++begin != end);
+
+  return true;
+}
+
 UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, 
                                            bool HasUnresolvedUsing,
                                            Expr *Base, QualType BaseType,
@@ -857,6 +879,11 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C,
                   BaseType->containsUnexpandedParameterPack())),
     IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
     Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
+
+  // Check whether all of the members are non-static member functions,
+  // and if so, mark give this bound-member type instead of overload type.
+  if (hasOnlyNonStaticMemberFunctions(Begin, End))
+    setType(C.BoundMemberTy);
 }
 
 bool UnresolvedMemberExpr::isImplicitAccess() const {
index b62442d6d2a8093b92c382ff08cc0af53be0fb55..14ee74be124b93a3ba01c7c7d0caac4088e70cd9 100644 (file)
@@ -1471,6 +1471,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
 
   case BuiltinType::Overload:
   case BuiltinType::Dependent:
+  case BuiltinType::BoundMember:
   case BuiltinType::UnknownAny:
     assert(false &&
            "Overloaded and dependent types shouldn't get to name mangling");
index 046c33ddda6b9cc29cdad294986f8ed5ba95cbf8..2ba4cf2f67c78e06e283695f67592f32c487f53a 100644 (file)
@@ -718,6 +718,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) {
   case BuiltinType::Overload:
   case BuiltinType::Dependent:
   case BuiltinType::UnknownAny:
+  case BuiltinType::BoundMember:
     assert(false &&
            "Overloaded and dependent types shouldn't get to name mangling");
     break;
index 124bf1330527ed73d9067659415c83d92a20da84..d43a121881e8507260977a3227d550f4579a8a03 100644 (file)
@@ -1169,6 +1169,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const {
   case Char32:            return "char32_t";
   case NullPtr:           return "nullptr_t";
   case Overload:          return "<overloaded function type>";
+  case BoundMember:       return "<bound member function type>";
   case Dependent:         return "<dependent type>";
   case UnknownAny:        return "<unknown type>";
   case ObjCId:            return "id";
index cc6483042859ebb5ccd09d6b54a39796cbbc0c46..34e7693e307545899fb3d5433f74615ffc9448b0 100644 (file)
@@ -234,6 +234,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
     case BuiltinType::NullPtr:
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
+    case BuiltinType::BoundMember:
     case BuiltinType::UnknownAny:
     case BuiltinType::ObjCId:
     case BuiltinType::ObjCClass:
index 228d9c6c5e6d9f7c6a0ad10a9ae97a749cfc5113..94f95053425ee94cb72aa56ccc514aee3c26c78c 100644 (file)
@@ -289,10 +289,10 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
   const Expr *MemFnExpr = BO->getRHS();
   
   const MemberPointerType *MPT = 
-    MemFnExpr->getType()->getAs<MemberPointerType>();
+    MemFnExpr->getType()->castAs<MemberPointerType>();
 
   const FunctionProtoType *FPT = 
-    MPT->getPointeeType()->getAs<FunctionProtoType>();
+    MPT->getPointeeType()->castAs<FunctionProtoType>();
   const CXXRecordDecl *RD = 
     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
 
@@ -321,8 +321,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
   
   // And the rest of the call args
   EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end());
-  const FunctionType *BO_FPT = BO->getType()->getAs<FunctionProtoType>();
-  return EmitCall(CGM.getTypes().getFunctionInfo(Args, BO_FPT), Callee, 
+  return EmitCall(CGM.getTypes().getFunctionInfo(Args, FPT), Callee, 
                   ReturnValue, Args);
 }
 
index b8d234f8a6249fc6a0d388be00e5535d21b398dc..c73b199e31f7f725b8ff1a6f1fa4ebde75afab62 100644 (file)
@@ -196,8 +196,9 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
       
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
+    case BuiltinType::BoundMember:
     case BuiltinType::UnknownAny:
-      assert(false && "Should not see this type here!");
+      llvm_unreachable("asking for RRTI for a placeholder type!");
       
     case BuiltinType::ObjCId:
     case BuiltinType::ObjCClass:
index 255d12f2cc316ea9f6fc081cba0321e2f0558b41..8db6fe51868437f69512c2257739fc7d84bf03fb 100644 (file)
@@ -229,7 +229,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
 #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
 #include "clang/AST/TypeNodes.def"
-    assert(false && "Non-canonical or dependent types aren't possible.");
+    llvm_unreachable("Non-canonical or dependent types aren't possible.");
     break;
 
   case Type::Builtin: {
@@ -283,8 +283,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
     
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
+    case BuiltinType::BoundMember:
     case BuiltinType::UnknownAny:
-      llvm_unreachable("Unexpected builtin type!");
+      llvm_unreachable("Unexpected placeholder builtin type!");
       break;
     }
     llvm_unreachable("Unknown builtin type!");
index 648011b1f05fb084a79b1cd3ae6c33ecf8c14b3c..ed54f0f5442528a3147f478253cc04534fa90834 100644 (file)
@@ -160,10 +160,6 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
   // FIXME: should we check this in a more fine-grained manner?
   bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
 
-  if (Ex.get()->isBoundMemberFunction(Context))
-    Diag(Ex.get()->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-      << Ex.get()->getSourceRange();
-
   ExprValueKind VK = VK_RValue;
   if (TypeDependent)
     VK = Expr::getValueKindForType(DestType);
@@ -305,6 +301,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
 /// Diagnose a failed cast.
 static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
                             SourceRange opRange, Expr *src, QualType destType) {
+  if (src->getType() == S.Context.BoundMemberTy) {
+    (void) S.CheckPlaceholderExpr(src); // will always fail
+    return;
+  }
+
   if (msg == diag::err_bad_cxx_cast_generic &&
       tryDiagnoseOverloadedCast(S, castType, opRange, src, destType))
     return;
@@ -1540,12 +1541,6 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
                          Expr *CastExpr, CastKind &Kind, 
                          CXXCastPath &BasePath,
                          bool FunctionalStyle) {
-  if (CastExpr->isBoundMemberFunction(Context)) {
-    Diag(CastExpr->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-        << CastExpr->getSourceRange();
-    return ExprError();
-  }
-
   // This test is outside everything else because it's the only case where
   // a non-lvalue-reference target type does not lead to decay.
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -1557,6 +1552,9 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
       return ExprError();
     CastExpr = CastExprRes.take();
 
+    if (CastExpr->getType() == Context.BoundMemberTy)
+      return CheckPlaceholderExpr(CastExpr); // will always fail
+
     if (CastExpr->getType() == Context.OverloadTy) {
       ExprResult SingleFunctionExpr = 
         ResolveAndFixSingleFunctionTemplateSpecialization(
index c90c5132506949fcb331dce9ded243770356a57b..212f584f5feb91e647666ae74e1a05e6ea8b6e80 100644 (file)
@@ -3934,12 +3934,20 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
   }
 
   if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    ExprValueKind valueKind;
+    QualType type;
+    if (MemberFn->isInstance()) {
+      valueKind = VK_RValue;
+      type = Context.BoundMemberTy;
+    } else {
+      valueKind = VK_LValue;
+      type = MemberFn->getType();
+    }
+
     MarkDeclarationReferenced(MemberLoc, MemberDecl);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
                                  MemberFn, FoundDecl, MemberNameInfo,
-                                 MemberFn->getType(),
-                                 MemberFn->isInstance() ? VK_RValue : VK_LValue,
-                                 OK_Ordinary));
+                                 type, valueKind, OK_Ordinary));
   }
   assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
 
@@ -4051,6 +4059,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
         << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
         << FixItHint::CreateReplacement(OpLoc, ".");
       IsArrow = false;
+    } else if (BaseType == Context.BoundMemberTy) {
+      goto fail;
     } else {
       Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
         << BaseType << BaseExpr.get()->getSourceRange();
@@ -4424,6 +4434,16 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
       }
     } else if ((Fun = BaseType->getAs<FunctionType>())) {
       TryCall = true;
+    } else if (BaseType == Context.BoundMemberTy) {
+      // Look for the bound-member type.  If it's still overloaded,
+      // give up, although we probably should have fallen into the
+      // OverloadExpr case above if we actually have an overloaded
+      // bound member.
+      QualType fnType = Expr::findBoundMemberType(BaseExpr.get());
+      if (!fnType.isNull()) {
+        TryCall = true;
+        Fun = fnType->castAs<FunctionType>();
+      }
     }
 
     if (TryCall) {
@@ -4858,91 +4878,33 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
       Fn = result.take();
     }
 
-    Expr *NakedFn = Fn->IgnoreParens();
-
-    // Determine whether this is a call to an unresolved member function.
-    if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
-      // If lookup was unresolved but not dependent (i.e. didn't find
-      // an unresolved using declaration), it has to be an overloaded
-      // function set, which means it must contain either multiple
-      // declarations (all methods or method templates) or a single
-      // method template.
-      assert((MemE->getNumDecls() > 1) ||
-             isa<FunctionTemplateDecl>(
-                                 (*MemE->decls_begin())->getUnderlyingDecl()));
-      (void)MemE;
-
+    if (Fn->getType() == Context.BoundMemberTy) {
       return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
                                        RParenLoc);
     }
+  }
+
+  // Check for overloaded calls.  This can happen even in C due to extensions.
+  if (Fn->getType() == Context.OverloadTy) {
+    OverloadExpr::FindResult find = OverloadExpr::find(Fn);
 
-    // Determine whether this is a call to a member function.
-    if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
-      NamedDecl *MemDecl = MemExpr->getMemberDecl();
-      if (isa<CXXMethodDecl>(MemDecl))
+    // We aren't supposed to apply this logic if there's an '&' involved.
+    if (!find.IsAddressOfOperand) {
+      OverloadExpr *ovl = find.Expression;
+      if (isa<UnresolvedLookupExpr>(ovl)) {
+        UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+        return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
+                                       RParenLoc, ExecConfig);
+      } else {
         return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
                                          RParenLoc);
-    }
-
-    // Determine whether this is a call to a pointer-to-member function.
-    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
-      if (BO->getOpcode() == BO_PtrMemD ||
-          BO->getOpcode() == BO_PtrMemI) {
-        if (const FunctionProtoType *FPT
-                                = BO->getType()->getAs<FunctionProtoType>()) {
-          QualType ResultTy = FPT->getCallResultType(Context);
-          ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
-
-          // Check that the object type isn't more qualified than the
-          // member function we're calling.
-          Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals());
-          Qualifiers ObjectQuals 
-            = BO->getOpcode() == BO_PtrMemD
-                ? BO->getLHS()->getType().getQualifiers()
-                : BO->getLHS()->getType()->getAs<PointerType>()
-                                            ->getPointeeType().getQualifiers();
-
-          Qualifiers Difference = ObjectQuals - FuncQuals;
-          Difference.removeObjCGCAttr();
-          Difference.removeAddressSpace();
-          if (Difference) {
-            std::string QualsString = Difference.getAsString();
-            Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
-              << BO->getType().getUnqualifiedType()
-              << QualsString
-              << (QualsString.find(' ') == std::string::npos? 1 : 2);
-          }
-              
-          CXXMemberCallExpr *TheCall
-            = new (Context) CXXMemberCallExpr(Context, Fn, Args,
-                                              NumArgs, ResultTy, VK,
-                                              RParenLoc);
-
-          if (CheckCallReturnType(FPT->getResultType(),
-                                  BO->getRHS()->getSourceRange().getBegin(),
-                                  TheCall, 0))
-            return ExprError();
-
-          if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs,
-                                      RParenLoc))
-            return ExprError();
-
-          return MaybeBindToTemporary(TheCall);
-        }
       }
     }
   }
 
   // If we're directly calling a function, get the appropriate declaration.
-  // Also, in C++, keep track of whether we should perform argument-dependent
-  // lookup and whether there were any explicitly-specified template arguments.
 
   Expr *NakedFn = Fn->IgnoreParens();
-  if (isa<UnresolvedLookupExpr>(NakedFn)) {
-    UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
-    return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
-                                   RParenLoc, ExecConfig);
-  }
 
   NamedDecl *NDecl = 0;
   if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
@@ -4951,6 +4913,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
   
   if (isa<DeclRefExpr>(NakedFn))
     NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+  else if (isa<MemberExpr>(NakedFn))
+    NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
 
   return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc,
                                ExecConfig);
@@ -8282,6 +8246,11 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
     return S.Context.OverloadTy;
   if (OrigOp->getType() == S.Context.UnknownAnyTy)
     return S.Context.UnknownAnyTy;
+  if (OrigOp->getType() == S.Context.BoundMemberTy) {
+    S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+      << OrigOp->getSourceRange();
+    return QualType();
+  }
 
   assert(!OrigOp->getType()->isPlaceholderType());
 
@@ -10301,13 +10270,11 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
   if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
     DiagnoseEqualityWithExtraParens(parenE);
 
-  if (!E->isTypeDependent()) {
-    if (E->isBoundMemberFunction(Context)) {
-      Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-        << E->getSourceRange();
-      return ExprError();
-    }
+  ExprResult result = CheckPlaceholderExpr(E);
+  if (result.isInvalid()) return ExprError();
+  E = result.take();
 
+  if (!E->isTypeDependent()) {
     if (getLangOptions().CPlusPlus)
       return CheckCXXBooleanCondition(E); // C++ 6.4p4
 
@@ -10728,6 +10695,13 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
                                                              QualType(),
                                                    diag::err_ovl_unresolvable);
 
+  // Bound member functions.
+  if (type == Context.BoundMemberTy) {
+    Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+      << E->getSourceRange();
+    return ExprError();
+  }    
+
   // Expressions of unknown type.
   if (type == Context.UnknownAnyTy)
     return diagnoseUnknownAnyExpr(*this, E);
index edfa4a532dfc01383e9d05b3ace971f4447cbf3a..f8ad763e4bde2834c26204efa4bde19ab0a17410 100644 (file)
@@ -2857,13 +2857,6 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
   //   second operand.
   // The cv qualifiers are the union of those in the pointer and the left side,
   // in accordance with 5.5p5 and 5.2.5.
-  // FIXME: This returns a dereferenced member function pointer as a normal
-  // function type. However, the only operation valid on such functions is
-  // calling them. There's also a GCC extension to get a function pointer to the
-  // thing, which is another complication, because this type - unlike the type
-  // that is the result of this expression - takes the class as the first
-  // argument.
-  // We probably need a "MemberFunctionClosureType" or something like that.
   QualType Result = MemPtr->getPointeeType();
   Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
 
@@ -2900,12 +2893,14 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
   //   operand is a pointer to a member function is a prvalue. The
   //   result of an ->* expression is an lvalue if its second operand
   //   is a pointer to data member and a prvalue otherwise.
-  if (Result->isFunctionType())
+  if (Result->isFunctionType()) {
     VK = VK_RValue;
-  else if (isIndirect)
+    return Context.BoundMemberTy;
+  } else if (isIndirect) {
     VK = VK_LValue;
-  else
+  } else {
     VK = lex.get()->getValueKind();
+  }
 
   return Result;
 }
index 06c097c620c636d748051dc1aaa153c1ce9d6edf..6e6bf22be0b5bf2ab76554469741e525b4c68e1f 100644 (file)
@@ -3623,8 +3623,8 @@ ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
     return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
 
   if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
-    return  Diag(From->getSourceRange().getBegin(),
-                 diag::err_typecheck_bool_condition)
+    return Diag(From->getSourceRange().getBegin(),
+                diag::err_typecheck_bool_condition)
                   << From->getType() << From->getSourceRange();
   return ExprError();
 }
@@ -7202,7 +7202,7 @@ public:
     if (!TargetFunctionType->isFunctionType()) {        
       if (OvlExpr->hasExplicitTemplateArgs()) {
         DeclAccessPair dap;
-        ifFunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+        if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
                                             OvlExpr, false, &dap) ) {
 
           if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
@@ -7502,32 +7502,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp
 /// template, where that template-id refers to a single template whose template
 /// arguments are either provided by the template-id or have defaults,
 /// as described in C++0x [temp.arg.explicit]p3.
-FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, 
-                                                                bool Complain,
-                                                  DeclAccessPair* FoundResult) {
+FunctionDecl *
+Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, 
+                                                  bool Complain,
+                                                  DeclAccessPair *FoundResult) {
   // C++ [over.over]p1:
   //   [...] [Note: any redundant set of parentheses surrounding the
   //   overloaded function name is ignored (5.1). ]
   // C++ [over.over]p1:
   //   [...] The overloaded function name can be preceded by the &
   //   operator.
-  if (From->getType() != Context.OverloadTy)
-    return 0;
-
-  OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
 
   // If we didn't actually find any template-ids, we're done.
-  if (!OvlExpr->hasExplicitTemplateArgs())
+  if (!ovl->hasExplicitTemplateArgs())
     return 0;
 
   TemplateArgumentListInfo ExplicitTemplateArgs;
-  OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+  ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
 
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
   FunctionDecl *Matched = 0;
-  for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
-         E = OvlExpr->decls_end(); I != E; ++I) {
+  for (UnresolvedSetIterator I = ovl->decls_begin(),
+         E = ovl->decls_end(); I != E; ++I) {
     // C++0x [temp.arg.explicit]p3:
     //   [...] In contexts where deduction is done and fails, or in contexts
     //   where deduction is not done, if a template argument list is
@@ -7544,7 +7541,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
     //   function template specialization, which is added to the set of
     //   overloaded functions considered.
     FunctionDecl *Specialization = 0;
-    TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+    TemplateDeductionInfo Info(Context, ovl->getNameLoc());
     if (TemplateDeductionResult Result
           = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
                                     Specialization, Info)) {
@@ -7553,21 +7550,20 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
       continue;
     }
 
+    assert(Specialization && "no specialization and no error?");
+
     // Multiple matches; we can't resolve to a single declaration.
     if (Matched) {
-      if (FoundResult) 
-          *FoundResult = DeclAccessPair();
-      
       if (Complain) {
-        Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
-          << OvlExpr->getName();
-        NoteAllOverloadCandidates(OvlExpr);
+        Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous)
+          << ovl->getName();
+        NoteAllOverloadCandidates(ovl);
       }
       return 0;
-    }   
+    }
     
-    if ((Matched = Specialization) && FoundResult) 
-      *FoundResult = I.getPair();    
+    Matched = Specialization;
+    if (FoundResult) *FoundResult = I.getPair();    
   }
 
   return Matched;
@@ -7581,39 +7577,65 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
 // template specialization
 // Last three arguments should only be supplied if Complain = true
 ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
-             Expr *SrcExpr, bool DoFunctionPointerConverion, bool Complain,
+             Expr *SrcExpr, bool doFunctionPointerConverion, bool complain,
                                   const SourceRange& OpRangeForComplaining, 
                                            QualType DestTypeForComplaining, 
-                                            unsigned DiagIDForComplaining ) {
+                                            unsigned DiagIDForComplaining) {
+  assert(SrcExpr->getType() == Context.OverloadTy);
 
-    assert(SrcExpr->getType() == Context.OverloadTy);
+  OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr);
 
-    DeclAccessPair Found;
-    ExprResult SingleFunctionExpression;
-    if (FunctionDecl* Fn = ResolveSingleFunctionTemplateSpecialization(
-      SrcExpr, false, // false -> Complain 
-      &Found)) {
-        if (!DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
-          // mark the expression as resolved to Fn
-          SingleFunctionExpression = Owned(FixOverloadedFunctionReference(SrcExpr, 
-            Found, Fn));
-          if (DoFunctionPointerConverion)
-            SingleFunctionExpression =
-              DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
-        }      
-    }
-    if (!SingleFunctionExpression.isUsable()) {
-      if (Complain) {
-        OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
-        Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
-          << oe->getName() << DestTypeForComplaining << OpRangeForComplaining 
-          << oe->getQualifierLoc().getSourceRange();
-        NoteAllOverloadCandidates(SrcExpr);
-      }      
+  DeclAccessPair found;
+  ExprResult SingleFunctionExpression;
+  if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+                           ovl.Expression, /*complain*/ false, &found)) {
+    if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin()))
+      return ExprError();
+
+    // It is only correct to resolve to an instance method if we're
+    // resolving a form that's permitted to be a pointer to member.
+    // Otherwise we'll end up making a bound member expression, which
+    // is illegal in all the contexts we resolve like this.
+    if (!ovl.HasFormOfMemberPointer &&
+        isa<CXXMethodDecl>(fn) &&
+        cast<CXXMethodDecl>(fn)->isInstance()) {
+      if (complain) {
+        Diag(ovl.Expression->getExprLoc(),
+             diag::err_invalid_use_of_bound_member_func)
+          << ovl.Expression->getSourceRange();
+        // TODO: I believe we only end up here if there's a mix of
+        // static and non-static candidates (otherwise the expression
+        // would have 'bound member' type, not 'overload' type).
+        // Ideally we would note which candidate was chosen and why
+        // the static candidates were rejected.
+      }
+      
       return ExprError();
     }
 
-    return SingleFunctionExpression;
+    // Fix the expresion to refer to 'fn'.
+    SingleFunctionExpression =
+      Owned(FixOverloadedFunctionReference(SrcExpr, found, fn));
+
+    // If desired, do function-to-pointer decay.
+    if (doFunctionPointerConverion)
+      SingleFunctionExpression =
+        DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
+  }
+
+  if (!SingleFunctionExpression.isUsable()) {
+    if (complain) {
+      Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+        << ovl.Expression->getName()
+        << DestTypeForComplaining
+        << OpRangeForComplaining 
+        << ovl.Expression->getQualifierLoc().getSourceRange();
+      NoteAllOverloadCandidates(SrcExpr);
+    }      
+    return ExprError();
+  }
+
+  return SingleFunctionExpression;
 }
 
 /// \brief Add a single candidate to the overload set.
@@ -8499,16 +8521,66 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
 /// function (and includes the object parameter), Args/NumArgs are the
 /// arguments to the function call (not including the object
 /// parameter). The caller needs to validate that the member
-/// expression refers to a member function or an overloaded member
-/// function.
+/// expression refers to a non-static member function or an overloaded
+/// member function.
 ExprResult
 Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
                                 SourceLocation LParenLoc, Expr **Args,
                                 unsigned NumArgs, SourceLocation RParenLoc) {
+  assert(MemExprE->getType() == Context.BoundMemberTy ||
+         MemExprE->getType() == Context.OverloadTy);
+
   // Dig out the member expression. This holds both the object
   // argument and the member function we're referring to.
   Expr *NakedMemExpr = MemExprE->IgnoreParens();
 
+  // Determine whether this is a call to a pointer-to-member function.
+  if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) {
+    assert(op->getType() == Context.BoundMemberTy);
+    assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI);
+
+    QualType fnType =
+      op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType();
+
+    const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
+    QualType resultType = proto->getCallResultType(Context);
+    ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+
+    // Check that the object type isn't more qualified than the
+    // member function we're calling.
+    Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
+
+    QualType objectType = op->getLHS()->getType();
+    if (op->getOpcode() == BO_PtrMemI)
+      objectType = objectType->castAs<PointerType>()->getPointeeType();
+    Qualifiers objectQuals = objectType.getQualifiers();
+
+    Qualifiers difference = objectQuals - funcQuals;
+    difference.removeObjCGCAttr();
+    difference.removeAddressSpace();
+    if (difference) {
+      std::string qualsString = difference.getAsString();
+      Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
+        << fnType.getUnqualifiedType()
+        << qualsString
+        << (qualsString.find(' ') == std::string::npos ? 1 : 2);
+    }
+              
+    CXXMemberCallExpr *call
+      = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+                                        resultType, valueKind, RParenLoc);
+
+    if (CheckCallReturnType(proto->getResultType(),
+                            op->getRHS()->getSourceRange().getBegin(),
+                            call, 0))
+      return ExprError();
+
+    if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc))
+      return ExprError();
+
+    return MaybeBindToTemporary(call);
+  }
+
   MemberExpr *MemExpr;
   CXXMethodDecl *Method = 0;
   DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
index e6609c08e21e873880e3f8710b179a8afd85dbb2..5e21a367588730625d7ed3a75c90ef580a577ca0 100644 (file)
@@ -77,12 +77,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
   if (!E)
     return;
 
-  if (E->isBoundMemberFunction(Context)) {
-    Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
-      << E->getSourceRange();
-    return;
-  }
-
   SourceLocation Loc;
   SourceRange R1, R2;
   if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
index b5bbe74ce3d4d18f9d31c2df570e7614c0134912..782e5c6aa79f3a8ba9022a94e3f2c04c3b338fa6 100644 (file)
@@ -50,6 +50,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
   case BuiltinType::Char16:     ID = PREDEF_TYPE_CHAR16_ID;     break;
   case BuiltinType::Char32:     ID = PREDEF_TYPE_CHAR32_ID;     break;
   case BuiltinType::Overload:   ID = PREDEF_TYPE_OVERLOAD_ID;   break;
+  case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER;  break;
   case BuiltinType::Dependent:  ID = PREDEF_TYPE_DEPENDENT_ID;  break;
   case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY;   break;
   case BuiltinType::ObjCId:     ID = PREDEF_TYPE_OBJC_ID;       break;
index 03d9a05f3e3cfc67be098863931feabe4e9edceb..65ff731d3a8c482b00fad0d9294f7fa59556e61f 100644 (file)
@@ -3638,6 +3638,7 @@ QualType ASTReader::GetType(TypeID ID) {
     case PREDEF_TYPE_DOUBLE_ID:     T = Context->DoubleTy;           break;
     case PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy;       break;
     case PREDEF_TYPE_OVERLOAD_ID:   T = Context->OverloadTy;         break;
+    case PREDEF_TYPE_BOUND_MEMBER:  T = Context->BoundMemberTy;      break;
     case PREDEF_TYPE_DEPENDENT_ID:  T = Context->DependentTy;        break;
     case PREDEF_TYPE_UNKNOWN_ANY:   T = Context->UnknownAnyTy;       break;
     case PREDEF_TYPE_NULLPTR_ID:    T = Context->NullPtrTy;          break;
index b1cc1e3cfab0c8e22ffabfcceca5bb1828e208cc..544a66d9e39a4ee0c96b6921461a046acd6c4da5 100644 (file)
@@ -137,10 +137,10 @@ namespace member_pointers {
     if (S::f<int>) return; // expected-error {{call to non-static member function without an object argument}}
     if (&S::f<char>) return;
     if (&S::f<int>) return;
-    if (s.f<char>) return; // expected-error {{contextually convertible}}
-    if (s.f<int>) return; // expected-error {{contextually convertible}}
-    if (&s.f<char>) return; // expected-error {{contextually convertible}}
-    if (&s.f<int>) return; // expected-error {{contextually convertible}}
+    if (s.f<char>) return; // expected-error {{a bound member function may only be called}}
+    if (s.f<int>) return; // expected-error {{a bound member function may only be called}}
+    if (&s.f<char>) return; // expected-error {{cannot create a non-constant pointer to member function}}
+    if (&s.f<int>) return; // expected-error {{cannot create a non-constant pointer to member function}}
 
     if (S::g<char>) return;
     if (S::g<int>) return;
@@ -152,22 +152,23 @@ namespace member_pointers {
     if (&s.g<int>) return;
 
     if (S::h<42>) return;
-    if (S::h<int>) return; // expected-error {{contextually convertible}}
+    if (S::h<int>) return; // expected-error {{a bound member function may only be called}}
     if (&S::h<42>) return;
     if (&S::h<int>) return;
     if (s.h<42>) return;
-    if (s.h<int>) return; // expected-error {{contextually convertible}}
+    if (s.h<int>) return; // expected-error {{a bound member function may only be called}}
     if (&s.h<42>) return;
-    if (&s.h<int>) return; // expected-error {{contextually convertible}}
+    if (&s.h<int>) return; // expected-error {{a bound member function may only be called}}
 
     { bool b = S::f<char>; } // expected-error {{call to non-static member function without an object argument}}
     { bool b = S::f<int>; } // expected-error {{call to non-static member function without an object argument}}
     { bool b = &S::f<char>; }
     { bool b = &S::f<int>; }
-    { bool b = s.f<char>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
-    { bool b = s.f<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
-    { bool b = &s.f<char>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
-    { bool b = &s.f<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
+    // These next two errors are terrible.
+    { bool b = s.f<char>; } // expected-error {{cannot initialize}}
+    { bool b = s.f<int>; } // expected-error {{cannot initialize}}
+    { bool b = &s.f<char>; } // expected-error {{cannot create a non-constant pointer to member function}}
+    { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}}
 
     { bool b = S::g<char>; }
     { bool b = S::g<int>; }
index a1079ff5bac6019c38f19edc922bc349fc5c9c40..a36fd582db2ee49ca00fca54943b06b6998d7110 100644 (file)
@@ -57,11 +57,12 @@ struct B
 
 struct C {
   C &getC() {
-    return makeAC; // expected-error{{address of overloaded function 'makeAC'}}
+    // FIXME: this error message is terrible
+    return makeAC; // expected-error{{cannot bind to a value of unrelated type}}
   }
 
-  C &makeAC();  //expected-note{{candidate function}}
-  const C &makeAC() const; //expected-note{{candidate function}}
+  C &makeAC();
+  const C &makeAC() const;
 
   static void f(); // expected-note{{candidate function}}
   static void f(int); // expected-note{{candidate function}}
index 6b644ea84daadfe0bcbc5414c4d837786133534d..4555192280f054d858e73d3c70bbcd164fabc6bc 100644 (file)
@@ -189,12 +189,12 @@ struct Class : BaseClass
     static int& NestedFuncTemplate() { return variable; } // expected-note{{candidate function}}
 
     template <class T>
-    int& NestedMemfunTemplate() { return variable; } // expected-note{{candidate function}}
+    int& NestedMemfunTemplate() { return variable; }
 
     int operator*() const;
 
     template <class T>
-    int operator+(T) const; // expected-note{{candidate function}}
+    int operator+(T) const;
 
     int NonstaticMemberFunction();
     static int StaticMemberFunction();
@@ -237,12 +237,12 @@ struct Class : BaseClass
         // expected-error{{cannot resolve overloaded function 'NestedFuncTemplate' from context}}
         
         __is_lvalue_expr(::Class::NestedMemfunTemplate);  // qualified-id: template \
-        // expected-error{{cannot resolve overloaded function 'NestedMemfunTemplate' from context}}
+        // expected-error{{a bound member function may only be called}}
         
         __is_lvalue_expr(::Class::operator+);             // operator-function-id: template \
-        // expected-error{{cannot resolve overloaded function 'operator+' from context}}
+        // expected-error{{a bound member function may only be called}}
 
-        ASSERT_RVALUE(::Class::operator*);         // operator-function-id: member function
+        //ASSERT_RVALUE(::Class::operator*);         // operator-function-id: member function
     }
 
     void expr_prim_7()
@@ -256,7 +256,7 @@ struct Class : BaseClass
         ASSERT_LVALUE(StaticMemberFunction);        // identifier: function
         ASSERT_LVALUE(variable);        // identifier: variable
         ASSERT_LVALUE(dataMember);      // identifier: data member
-        ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function
+        //ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function
 
         // (cont'd)...A nested-name-specifier that names a class,
         // optionally followed by the keyword template (14.2), and then
@@ -267,11 +267,11 @@ struct Class : BaseClass
         // member function or a data member.
         ASSERT_LVALUE(Class::dataMember);
         ASSERT_LVALUE(Class::StaticMemberFunction);
-        ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function
+        //ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function
 
         ASSERT_LVALUE(Class::baseDataMember);
         ASSERT_LVALUE(Class::BaseStaticMemberFunction);
-        ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function
+        //ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function
     }
 };
 
@@ -371,7 +371,7 @@ void expr_ref_4()
     
     // — Otherwise, if E1.E2 refers to a non-static member function,
     // then E1.E2 is not an lvalue.
-    ASSERT_RVALUE(Class().NonstaticMemberFunction);
+    //ASSERT_RVALUE(Class().NonstaticMemberFunction);
 
     // — If E2 is a member enumerator, and the type of E2 is T, the
     // expression E1.E2 is not an lvalue. The type of E1.E2 is T.
@@ -502,17 +502,17 @@ void expr_mptr_oper()
     // is a pointer to data member... (cont'd)
     typedef Class MakeRValue;
     ASSERT_RVALUE(MakeRValue().*(&Class::dataMember));
-    ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction));
+    //ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction));
     Class lvalue;
     ASSERT_LVALUE(lvalue.*(&Class::dataMember));
-    ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction));
+    //ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction));
     
     // (cont'd)...The result of an ->* expression is an lvalue only
     // if its second operand is a pointer to data member. If the
     // second operand is the null pointer to member value (4.11), the
     // behavior is undefined.
     ASSERT_LVALUE((&lvalue)->*(&Class::dataMember));
-    ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction));
+    //ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction));
 }
 
 void expr_cond(bool cond)
index 8d39af10af0c37fc0a21f61b12b6f9f48fbf7c4b..44d013fe796ed0649f48905e28cf44a2557b2638 100644 (file)
@@ -387,15 +387,15 @@ void test_lookup_through_using() {
 
 namespace rdar9136502 {
   struct X {
-    int i(); // expected-note {{candidate function}}
-    int i(int); // expected-note {{candidate function}}
+    int i();
+    int i(int);
   };
 
   struct Y {
-    Y &operator<<(int); // expected-note{{candidate function not viable: no overload of 'i' matching 'int' for 1st argument}}
+    Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}}
   };
 
   void f(X x, Y y) {
-    y << x.i; // expected-error{{cannot resolve overloaded function 'i' from context}}
+    y << x.i; // expected-error{{a bound member function may only be called}}
   }
 }
index 8afcb112a36b55be0f301d6a13437e505507bba9..c3917333a540b4564d7475fca152dfdd78e8cb96 100644 (file)
@@ -27,8 +27,7 @@ void f3(S3* p, void (S3::*m)()) {
     (void)(void*)(p->*m); // expected-error {{a bound member function may only be called}}
     (void)reinterpret_cast<void*>(p->*m); // expected-error {{a bound member function may only be called}}
     if (p->*m) {} // expected-error {{a bound member function may only be called}}
-    if (!p->*m) {} // FIXME: xpected-error {{a bound member function may only be called}} \
-    // expected-error{{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'bool'}}
+    if (!(p->*m)) {} // expected-error {{a bound member function may only be called}}
     if (p->m) {}; // expected-error {{a bound member function may only be called}}
-    if (!p->m) {}; // FIXME: xpected-error {{a bound member function may only be called}}
+    if (!p->m) {}; // expected-error {{a bound member function may only be called}}
 }
index a50c987b3c25b86951ab4f188a0cb08fe348ad03..a0e204d61fe52ad73730361e7135752f76a0b6eb 100644 (file)
@@ -1412,6 +1412,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
   case BuiltinType::LongDouble:
   case BuiltinType::NullPtr:
   case BuiltinType::Overload:
+  case BuiltinType::BoundMember:
   case BuiltinType::Dependent:
   case BuiltinType::UnknownAny:
     break;
index 30173d3e7edfab6cd25986c5d5cae3efa25d9616..68871e94951cd9fcd09d98f1862599bad2147cdd 100644 (file)
@@ -570,6 +570,7 @@ void USRGenerator::VisitType(QualType T) {
         case BuiltinType::NullPtr:
           c = 'n'; break;
         case BuiltinType::Overload:
+        case BuiltinType::BoundMember:
         case BuiltinType::Dependent:
         case BuiltinType::UnknownAny:
           IgnoreResults = true;