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.

llvm-svn: 102287
This commit is contained in:
Douglas Gregor 2010-04-24 23:45:46 +00:00
parent dde8b46e62
commit 9556257252
2 changed files with 59 additions and 5 deletions

View File

@ -3138,6 +3138,8 @@ getAssignmentAction(const InitializedEntity &Entity) {
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 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
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 @@ InitializationSequence::Perform(Sema &S,
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 @@ InitializationSequence::Perform(Sema &S,
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 @@ InitializationSequence::Perform(Sema &S,
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 @@ InitializationSequence::Perform(Sema &S,
if (shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
break;
}

View File

@ -349,4 +349,17 @@ namespace test14 {
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}}
}
}