[cfe-commits] r110513 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Expr.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Expr.cpp lib/Checker/GRExprEngine.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h lib/Sema/SemaOverload.cpp test/CodeGenObjCXX/references.mm test/SemaObjCXX/references.mm

Douglas Gregor dgregor at apple.com
Sat Aug 7 04:51:52 PDT 2010


Author: dgregor
Date: Sat Aug  7 06:51:51 2010
New Revision: 110513

URL: http://llvm.org/viewvc/llvm-project?rev=110513&view=rev
Log:
Allow reference binding of a reference of Objective-C object type to
an lvalue of another, compatible Objective-C object type (e.g., a
subclass). Introduce a new initialization sequence step kind to
describe this binding, along with a new cast kind. Fixes PR7741.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Checker/GRExprEngine.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaInit.h
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CodeGenObjCXX/references.mm
    cfe/trunk/test/SemaObjCXX/references.mm

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sat Aug  7 06:51:51 2010
@@ -1251,7 +1251,8 @@
   bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
   QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
                                    const ObjCObjectPointerType *RHSOPT);
-  
+  bool canBindObjCObjectType(QualType To, QualType From);
+
   // Functions for calculating composite types
   QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
                       bool Unqualified = false);

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sat Aug  7 06:51:51 2010
@@ -1927,8 +1927,12 @@
     CK_AnyPointerToObjCPointerCast,
     /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block 
     /// pointer
-    CK_AnyPointerToBlockPointerCast
+    CK_AnyPointerToBlockPointerCast,
 
+    /// \brief Converting between two Objective-C object types, which
+    /// can occur when performing reference binding to an Objective-C
+    /// object.
+    CK_ObjCObjectLValueCast
   };
 
 private:
@@ -1970,6 +1974,7 @@
     case CK_MemberPointerToBoolean:
     case CK_AnyPointerToObjCPointerCast:
     case CK_AnyPointerToBlockPointerCast:
+    case CK_ObjCObjectLValueCast:
       assert(path_empty() && "Cast kind should not have a base path!");
       break;
     }

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sat Aug  7 06:51:51 2010
@@ -917,6 +917,7 @@
   bool isObjCQualifiedInterfaceType() const;    // NSString<foo>
   bool isObjCQualifiedIdType() const;           // id<foo>
   bool isObjCQualifiedClassType() const;        // Class<foo>
+  bool isObjCObjectOrInterfaceType() const;
   bool isObjCIdType() const;                    // id
   bool isObjCClassType() const;                 // Class
   bool isObjCSelType() const;                 // Class
@@ -3506,6 +3507,11 @@
 inline bool Type::isObjCObjectType() const {
   return isa<ObjCObjectType>(CanonicalType);
 }
+inline bool Type::isObjCObjectOrInterfaceType() const {
+  return isa<ObjCInterfaceType>(CanonicalType) || 
+    isa<ObjCObjectType>(CanonicalType);
+}
+
 inline bool Type::isObjCQualifiedIdType() const {
   if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
     return OPT->isObjCQualifiedIdType();

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Aug  7 06:51:51 2010
@@ -4560,6 +4560,12 @@
          canAssignObjCInterfaces(RHSOPT, LHSOPT);
 }
 
+bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
+  return canAssignObjCInterfaces(
+                getObjCObjectPointerType(To)->getAs<ObjCObjectPointerType>(),
+                getObjCObjectPointerType(From)->getAs<ObjCObjectPointerType>());
+}
+
 /// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
 /// both shall have the identically qualified version of a compatible type.
 /// C99 6.2.7p1: Two types have compatible types if their types are the

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Sat Aug  7 06:51:51 2010
@@ -717,6 +717,8 @@
     return "AnyPointerToObjCPointerCast";
   case CastExpr::CK_AnyPointerToBlockPointerCast:
     return "AnyPointerToBlockPointerCast";
+  case CastExpr::CK_ObjCObjectLValueCast:
+    return "ObjCObjectLValueCast";
   }
 
   assert(0 && "Unhandled cast kind!");

Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Sat Aug  7 06:51:51 2010
@@ -2514,7 +2514,8 @@
   case CastExpr::CK_AnyPointerToObjCPointerCast:
   case CastExpr::CK_AnyPointerToBlockPointerCast:
   case CastExpr::CK_DerivedToBase:
-  case CastExpr::CK_UncheckedDerivedToBase: {
+  case CastExpr::CK_UncheckedDerivedToBase:
+  case CastExpr::CK_ObjCObjectLValueCast: {
     // Delegate to SValuator to process.
     for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
       ExplodedNode* N = *I;

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sat Aug  7 06:51:51 2010
@@ -1851,6 +1851,13 @@
                                            ConvertType(CE->getTypeAsWritten()));
     return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
   }
+  case CastExpr::CK_ObjCObjectLValueCast: {
+    LValue LV = EmitLValue(E->getSubExpr());
+    QualType ToType = getContext().getLValueReferenceType(E->getType());
+    llvm::Value *V = Builder.CreateBitCast(LV.getAddress(), 
+                                           ConvertType(ToType));
+    return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+  }
   }
   
   llvm_unreachable("Unhandled lvalue cast kind?");

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sat Aug  7 06:51:51 2010
@@ -925,7 +925,8 @@
     //assert(0 && "Unknown cast kind!");
     break;
 
-  case CastExpr::CK_LValueBitCast: {
+  case CastExpr::CK_LValueBitCast: 
+  case CastExpr::CK_ObjCObjectLValueCast: {
     Value *V = EmitLValue(E).getAddress();
     V = Builder.CreateBitCast(V, 
                           ConvertType(CGF.getContext().getPointerType(DestTy)));
@@ -1044,7 +1045,10 @@
     return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
   }
   case CastExpr::CK_ToVoid: {
-    CGF.EmitAnyExpr(E, 0, false, true);
+    if (E->Classify(CGF.getContext()).isGLValue())
+      CGF.EmitLValue(E);
+    else
+      CGF.EmitAnyExpr(E, 0, false, true);
     return 0;
   }
   case CastExpr::CK_VectorSplat: {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Aug  7 06:51:51 2010
@@ -4517,7 +4517,8 @@
 
   ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
                                                       QualType T1, QualType T2,
-                                                      bool& DerivedToBase);
+                                                      bool &DerivedToBase,
+                                                      bool &ObjCConversion);
 
   /// CheckCastTypes - Check type constraints for casting between types under
   /// C semantics, or forward to CXXCheckCStyleCast in C++.

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Sat Aug  7 06:51:51 2010
@@ -646,9 +646,10 @@
   // this is the only cast possibility, so we issue an error if we fail now.
   // FIXME: Should allow casting away constness if CStyle.
   bool DerivedToBase;
+  bool ObjCConversion;
   if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
                                         SrcExpr->getType(), R->getPointeeType(),
-                                        DerivedToBase) <
+                                        DerivedToBase, ObjCConversion) <
         Sema::Ref_Compatible_With_Added_Qualification) {
     msg = diag::err_bad_lvalue_to_rvalue_cast;
     return TC_Failed;

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Aug  7 06:51:51 2010
@@ -2035,6 +2035,7 @@
   case SK_ZeroInitialization:
   case SK_CAssignment:
   case SK_StringInit:
+  case SK_ObjCObjectConversion:
     break;
     
   case SK_ConversionSequence:
@@ -2201,6 +2202,13 @@
   Steps.push_back(S);
 }
 
+void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
+  Step S;
+  S.Kind = SK_ObjCObjectConversion;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
 void InitializationSequence::SetOverloadFailure(FailureKind Failure, 
                                                 OverloadingResult Result) {
   SequenceKind = FailedSequence;
@@ -2275,10 +2283,13 @@
   QualType T2 = cv2T2.getUnqualifiedType();
 
   bool DerivedToBase;
+  bool ObjCConversion;
   assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), 
-                                         T1, T2, DerivedToBase) &&
+                                         T1, T2, DerivedToBase,
+                                         ObjCConversion) &&
          "Must have incompatible references when binding via conversion");
   (void)DerivedToBase;
+  (void)ObjCConversion;
 
   // Build the candidate set directly in the initialization sequence
   // structure, so that it will persist if we fail.
@@ -2400,10 +2411,11 @@
         ImplicitCastExpr::LValue : ImplicitCastExpr::XValue;
 
   bool NewDerivedToBase = false;
+  bool NewObjCConversion = false;
   Sema::ReferenceCompareResult NewRefRelationship
     = S.CompareReferenceRelationship(DeclLoc, T1, 
                                      T2.getNonLValueExprType(S.Context),
-                                     NewDerivedToBase);
+                                     NewDerivedToBase, NewObjCConversion);
   if (NewRefRelationship == Sema::Ref_Incompatible) {
     // If the type we've converted to is not reference-related to the
     // type we're looking for, then there is another conversion step
@@ -2418,8 +2430,12 @@
     Sequence.AddDerivedToBaseCastStep(
                                 S.Context.getQualifiedType(T1,
                                   T2.getNonReferenceType().getQualifiers()), 
-                                  Category);
-  
+                                      Category);
+  else if (NewObjCConversion)
+    Sequence.AddObjCObjectConversionStep(
+                                S.Context.getQualifiedType(T1,
+                                  T2.getNonReferenceType().getQualifiers()));
+
   if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
     Sequence.AddQualificationConversionStep(cv1T1, Category);
   
@@ -2467,9 +2483,11 @@
   bool isLValueRef = DestType->isLValueReferenceType();
   bool isRValueRef = !isLValueRef;
   bool DerivedToBase = false;
+  bool ObjCConversion = false;
   Expr::Classification InitCategory = Initializer->Classify(S.Context);
   Sema::ReferenceCompareResult RefRelationship
-    = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase);
+    = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
+                                     ObjCConversion);
 
   // C++0x [dcl.init.ref]p5:
   //   A reference to type "cv1 T1" is initialized by an expression of type 
@@ -2497,6 +2515,10 @@
         Sequence.AddDerivedToBaseCastStep(
                          S.Context.getQualifiedType(T1, T2Quals), 
                          ImplicitCastExpr::LValue);
+      else if (ObjCConversion)
+        Sequence.AddObjCObjectConversionStep(
+                                     S.Context.getQualifiedType(T1, T2Quals));
+
       if (T1Quals != T2Quals)
         Sequence.AddQualificationConversionStep(cv1T1,ImplicitCastExpr::LValue);
       bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
@@ -2577,6 +2599,10 @@
                          S.Context.getQualifiedType(T1, T2Quals), 
                          isXValue ? ImplicitCastExpr::XValue
                                   : ImplicitCastExpr::RValue);
+      else if (ObjCConversion)
+        Sequence.AddObjCObjectConversionStep(
+                                     S.Context.getQualifiedType(T1, T2Quals));
+
       if (T1Quals != T2Quals)
         Sequence.AddQualificationConversionStep(cv1T1,
                      isXValue ? ImplicitCastExpr::XValue
@@ -3546,6 +3572,7 @@
   case SK_ListInitialization:
   case SK_CAssignment:
   case SK_StringInit:
+  case SK_ObjCObjectConversion:
     assert(Args.size() == 1);
     CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain());
     if (CurInit.isInvalid())
@@ -3926,6 +3953,14 @@
       CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
       break;
     }
+
+    case SK_ObjCObjectConversion:
+      S.ImpCastExprToType(CurInitExpr, Step->Type, 
+                          CastExpr::CK_ObjCObjectLValueCast,
+                          S.CastCategory(CurInitExpr));
+      CurInit.release();
+      CurInit = S.Owned(CurInitExpr);
+      break;
     }
   }
   
@@ -4392,6 +4427,10 @@
     case SK_StringInit:
       OS << "string initialization";
       break;
+
+    case SK_ObjCObjectConversion:
+      OS << "Objective-C object conversion";
+      break;
     }
   }
 }

Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Sat Aug  7 06:51:51 2010
@@ -479,7 +479,10 @@
     /// \brief C assignment
     SK_CAssignment,
     /// \brief Initialization by string
-    SK_StringInit
+    SK_StringInit,
+    /// \brief An initialization that "converts" an Objective-C object
+    /// (not a point to an object) to another Objective-C object type.
+    SK_ObjCObjectConversion
   };
   
   /// \brief A single step in the initialization sequence.
@@ -737,6 +740,10 @@
   /// \brief Add a string init step.
   void AddStringInitStep(QualType T);
 
+  /// \brief Add an Objective-C object conversion step, which is
+  /// always a no-op.
+  void AddObjCObjectConversionStep(QualType T);
+
   /// \brief Note that this initialization sequence failed.
   void SetFailed(FailureKind Failure) {
     SequenceKind = FailedSequence;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Aug  7 06:51:51 2010
@@ -2575,7 +2575,8 @@
 Sema::ReferenceCompareResult
 Sema::CompareReferenceRelationship(SourceLocation Loc,
                                    QualType OrigT1, QualType OrigT2,
-                                   bool& DerivedToBase) {
+                                   bool &DerivedToBase,
+                                   bool &ObjCConversion) {
   assert(!OrigT1->isReferenceType() &&
     "T1 must be the pointee type of the reference type");
   assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
@@ -2590,11 +2591,17 @@
   //   Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
   //   reference-related to "cv2 T2" if T1 is the same type as T2, or
   //   T1 is a base class of T2.
-  if (UnqualT1 == UnqualT2)
-    DerivedToBase = false;
-  else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
+  DerivedToBase = false;
+  ObjCConversion = false;
+  if (UnqualT1 == UnqualT2) {
+    // Nothing to do.
+  } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
            IsDerivedFrom(UnqualT2, UnqualT1))
     DerivedToBase = true;
+  else if (UnqualT1->isObjCObjectOrInterfaceType() &&
+           UnqualT2->isObjCObjectOrInterfaceType() &&
+           Context.canBindObjCObjectType(UnqualT1, UnqualT2))
+    ObjCConversion = true;
   else
     return Ref_Incompatible;
 
@@ -2741,9 +2748,11 @@
   // Compute some basic properties of the types and the initializer.
   bool isRValRef = DeclType->isRValueReferenceType();
   bool DerivedToBase = false;
+  bool ObjCConversion = false;
   Expr::Classification InitCategory = Init->Classify(S.Context);
   Sema::ReferenceCompareResult RefRelationship
-    = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
+    = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase,
+                                     ObjCConversion);
 
 
   // C++0x [dcl.init.ref]p5:
@@ -2769,7 +2778,9 @@
       //   derived-to-base Conversion (13.3.3.1).
       ICS.setStandard();
       ICS.Standard.First = ICK_Identity;
-      ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+      ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+                         : ObjCConversion? ICK_Compatible_Conversion
+                         : ICK_Identity;
       ICS.Standard.Third = ICK_Identity;
       ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
       ICS.Standard.setToType(0, T2);
@@ -2857,7 +2868,9 @@
       RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
     ICS.setStandard();
     ICS.Standard.First = ICK_Identity;
-    ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+    ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base 
+                        : ObjCConversion? ICK_Compatible_Conversion
+                        : ICK_Identity;
     ICS.Standard.Third = ICK_Identity;
     ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
     ICS.Standard.setToType(0, T2);

Modified: cfe/trunk/test/CodeGenObjCXX/references.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/references.mm?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/references.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/references.mm Sat Aug  7 06:51:51 2010
@@ -24,3 +24,22 @@
 void f(B* b) {
   (void)[b getA];
 }
+
+// PR7741
+ at protocol P1 @end
+ at protocol P2 @end
+ at protocol P3 @end
+ at interface foo<P1> {} @end
+ at interface bar : foo <P1, P2> {} @end
+typedef bar baz;
+void f5(foo&);
+void f5b(foo<P1>&);
+void f5c(foo<P2>&);
+void f5d(foo<P3>&);
+void f6(baz* x) { 
+  f5(*x); 
+  f5b(*x); 
+  f5c(*x); 
+  f5d(*x);
+  (void)((foo&)*x);  
+}

Modified: cfe/trunk/test/SemaObjCXX/references.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/references.mm?rev=110513&r1=110512&r2=110513&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/references.mm (original)
+++ cfe/trunk/test/SemaObjCXX/references.mm Sat Aug  7 06:51:51 2010
@@ -31,3 +31,22 @@
 void f4(NSString &tmpstr) {
   f3(&tmpstr);
 }
+
+// PR7741
+ at protocol P1 @end
+ at protocol P2 @end
+ at protocol P3 @end
+ at interface foo<P1> {} @end
+ at interface bar : foo <P1, P2> {} @end
+typedef bar baz;
+void f5(foo&);
+void f5b(foo<P1>&);
+void f5c(foo<P2>&);
+void f5d(foo<P3>&);
+void f6(baz* x) { 
+  f5(*x); 
+  f5b(*x); 
+  f5c(*x); 
+  f5d(*x);
+  (void)((foo&)*x);  
+}





More information about the cfe-commits mailing list