[cfe-commits] r102287 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/CXX/class.access/p4.cpp

Douglas Gregor dgregor at apple.com
Sat Apr 24 16:45:46 PDT 2010


Author: dgregor
Date: Sat Apr 24 18:45:46 2010
New Revision: 102287

URL: http://llvm.org/viewvc/llvm-project?rev=102287&view=rev
Log:
When we create a temporary of class type that we don't immediately
bind, check accessibility of the destructor and mark the declaration
as referenced. Fixes a bunch of Boost.Regex failures.

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/class.access/p4.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=102287&r1=102286&r2=102287&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Apr 24 18:45:46 2010
@@ -3138,6 +3138,8 @@
   return Sema::AA_Converting;
 }
 
+/// \brief Whether we should binding a created object as a temporary when
+/// initializing the given entity.
 static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
   switch (Entity.getKind()) {
   case InitializedEntity::EK_ArrayElement:
@@ -3158,6 +3160,28 @@
   llvm_unreachable("missed an InitializedEntity kind?");
 }
 
+/// \brief Whether the given entity, when initialized with an object
+/// created for that initialization, requires destruction.
+static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
+  switch (Entity.getKind()) {
+    case InitializedEntity::EK_Member:
+    case InitializedEntity::EK_Result:
+    case InitializedEntity::EK_New:
+    case InitializedEntity::EK_Base:
+    case InitializedEntity::EK_VectorElement:
+      return false;
+      
+    case InitializedEntity::EK_Variable:
+    case InitializedEntity::EK_Parameter:
+    case InitializedEntity::EK_Temporary:
+    case InitializedEntity::EK_ArrayElement:
+    case InitializedEntity::EK_Exception:
+      return true;
+  }
+  
+  llvm_unreachable("missed an InitializedEntity kind?");  
+}
+
 /// \brief Make a (potentially elidable) temporary copy of the object
 /// provided by the given initializer by calling the appropriate copy
 /// constructor.
@@ -3551,6 +3575,7 @@
       bool IsCopy = false;
       FunctionDecl *Fn = Step->Function.Function;
       DeclAccessPair FoundFn = Step->Function.FoundDecl;
+      bool CreatedObject = false;
       bool IsLvalue = false;
       if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
         // Build a call to the selected constructor.
@@ -3581,6 +3606,8 @@
         if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
             S.IsDerivedFrom(SourceType, Class))
           IsCopy = true;
+        
+        CreatedObject = true;
       } else {
         // Build a call to the conversion function.
         CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
@@ -3606,23 +3633,37 @@
           return S.ExprError();
         
         CastKind = CastExpr::CK_UserDefinedConversion;
+        
+        CreatedObject = Conversion->getResultType()->isRecordType();
       }
       
       bool RequiresCopy = !IsCopy && 
         getKind() != InitializationSequence::ReferenceBinding;
       if (RequiresCopy || shouldBindAsTemporary(Entity))
         CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
-
+      else if (CreatedObject && shouldDestroyTemporary(Entity)) {
+        CurInitExpr = static_cast<Expr *>(CurInit.get());
+        QualType T = CurInitExpr->getType();
+        if (const RecordType *Record = T->getAs<RecordType>()) {
+          CXXDestructorDecl *Destructor
+            = cast<CXXRecordDecl>(Record->getDecl())->getDestructor(S.Context);
+          S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor, 
+                                  S.PDiag(diag::err_access_dtor_temp) << T);
+          S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
+        }
+      }
+      
       CurInitExpr = CurInit.takeAs<Expr>();
       CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
-                                                        CastKind, 
-                                                        CurInitExpr,
+                                                         CastKind, 
+                                                         CurInitExpr,
                                                         CXXBaseSpecifierArray(),
-                                                        IsLvalue));
+                                                         IsLvalue));
       
       if (RequiresCopy)
         CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
                              move(CurInit), /*IsExtraneousCopy=*/false);
+      
       break;
     }
         
@@ -3705,7 +3746,7 @@
       
       if (shouldBindAsTemporary(Entity))
         CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
-
+      
       break;
     }
         

Modified: cfe/trunk/test/CXX/class.access/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=102287&r1=102286&r2=102287&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Sat Apr 24 18:45:46 2010
@@ -349,4 +349,17 @@
   void test() {
     foo(); // expected-error {{temporary of type 'test14::A' has private destructor}}
   }
+
+  class X {
+    ~X(); // expected-note {{declared private here}}
+  };
+  
+  struct Y1 {
+    operator X();
+  };
+  
+  void g() {
+    const X &xr = Y1(); // expected-error{{temporary of type 'test14::X' has private destructor}}
+  }
 }
+





More information about the cfe-commits mailing list