diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2019-05-10 17:52:26 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2019-05-10 17:52:26 +0000 |
commit | f8ccf052935adaf405e581fd31e8bc634cc5bbc7 (patch) | |
tree | 9cd6c6c3082628abfbfaed9a9ccc5f4f774f70b4 /clang/lib/Sema | |
parent | d74b87150448ab9e2e61f1d5c47de0503fca322f (diff) | |
download | bcm5719-llvm-f8ccf052935adaf405e581fd31e8bc634cc5bbc7.tar.gz bcm5719-llvm-f8ccf052935adaf405e581fd31e8bc634cc5bbc7.zip |
[Sema] Mark array element destructors referenced during initialization
This fixes a crash where we would neglect to mark a destructor referenced for an
__attribute__((no_destory)) array. The destructor is needed though, since if an
exception is thrown we need to cleanup the elements.
rdar://48462498
Differential revision: https://reviews.llvm.org/D61165
llvm-svn: 360446
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 70 |
3 files changed, 52 insertions, 53 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index fac7d418d40..afd50f1438e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13098,12 +13098,17 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { return; CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); - MarkFunctionReferenced(VD->getLocation(), Destructor); - CheckDestructorAccess(VD->getLocation(), Destructor, - PDiag(diag::err_access_dtor_var) - << VD->getDeclName() - << VD->getType()); - DiagnoseUseOfDecl(Destructor, VD->getLocation()); + + // If this is an array, we'll require the destructor during initialization, so + // we can skip over this. We still want to emit exit-time destructor warnings + // though. + if (!VD->getType()->isArrayType()) { + MarkFunctionReferenced(VD->getLocation(), Destructor); + CheckDestructorAccess(VD->getLocation(), Destructor, + PDiag(diag::err_access_dtor_var) + << VD->getDeclName() << VD->getType()); + DiagnoseUseOfDecl(Destructor, VD->getLocation()); + } if (Destructor->isTrivial()) return; if (!VD->hasGlobalStorage()) return; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b256dc655fe..8f00887ebc4 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2200,24 +2200,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, MarkFunctionReferenced(StartLoc, OperatorDelete); } - // C++0x [expr.new]p17: - // If the new expression creates an array of objects of class type, - // access and ambiguity control are done for the destructor. - QualType BaseAllocType = Context.getBaseElementType(AllocType); - if (ArraySize && !BaseAllocType->isDependentType()) { - if (const RecordType *BaseRecordType = BaseAllocType->getAs<RecordType>()) { - if (CXXDestructorDecl *dtor = LookupDestructor( - cast<CXXRecordDecl>(BaseRecordType->getDecl()))) { - MarkFunctionReferenced(StartLoc, dtor); - CheckDestructorAccess(StartLoc, dtor, - PDiag(diag::err_access_dtor) - << BaseAllocType); - if (DiagnoseUseOfDecl(dtor, StartLoc)) - return ExprError(); - } - } - } - return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment, UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens, ArraySize, initStyle, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 8bcce39c5ef..45456aff364 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1707,6 +1707,30 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, } } +/// Check if the type of a class element has an accessible destructor, and marks +/// it referenced. Returns true if we shouldn't form a reference to the +/// destructor. +/// +/// Aggregate initialization requires a class element's destructor be +/// accessible per 11.6.1 [dcl.init.aggr]: +/// +/// The destructor for each element of class type is potentially invoked +/// (15.4 [class.dtor]) from the context where the aggregate initialization +/// occurs. +static bool checkDestructorReference(QualType ElementType, SourceLocation Loc, + Sema &SemaRef) { + auto *CXXRD = ElementType->getAsCXXRecordDecl(); + if (!CXXRD) + return false; + + CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD); + SemaRef.CheckDestructorAccess(Loc, Destructor, + SemaRef.PDiag(diag::err_access_dtor_temp) + << ElementType); + SemaRef.MarkFunctionReferenced(Loc, Destructor); + return SemaRef.DiagnoseUseOfDecl(Destructor, Loc); +} + void InitListChecker::CheckArrayType(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, @@ -1716,6 +1740,14 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, unsigned &StructuredIndex) { const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType); + if (!VerifyOnly) { + if (checkDestructorReference(arrayType->getElementType(), + IList->getEndLoc(), SemaRef)) { + hadError = true; + return; + } + } + // Check for the special-case of initializing an array with a string. if (Index < IList->getNumInits()) { if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) == @@ -1877,30 +1909,6 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, return FlexArrayDiag != diag::ext_flexible_array_init; } -/// Check if the type of a class element has an accessible destructor. -/// -/// Aggregate initialization requires a class element's destructor be -/// accessible per 11.6.1 [dcl.init.aggr]: -/// -/// The destructor for each element of class type is potentially invoked -/// (15.4 [class.dtor]) from the context where the aggregate initialization -/// occurs. -static bool hasAccessibleDestructor(QualType ElementType, SourceLocation Loc, - Sema &SemaRef) { - auto *CXXRD = ElementType->getAsCXXRecordDecl(); - if (!CXXRD) - return false; - - CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD); - SemaRef.CheckDestructorAccess(Loc, Destructor, - SemaRef.PDiag(diag::err_access_dtor_temp) - << ElementType); - SemaRef.MarkFunctionReferenced(Loc, Destructor); - if (SemaRef.DiagnoseUseOfDecl(Destructor, Loc)) - return true; - return false; -} - void InitListChecker::CheckStructUnionTypes( const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, @@ -1924,7 +1932,7 @@ void InitListChecker::CheckStructUnionTypes( if (!VerifyOnly) for (FieldDecl *FD : RD->fields()) { QualType ET = SemaRef.Context.getBaseElementType(FD->getType()); - if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) { + if (checkDestructorReference(ET, IList->getEndLoc(), SemaRef)) { hadError = true; return; } @@ -1984,7 +1992,7 @@ void InitListChecker::CheckStructUnionTypes( } if (!VerifyOnly) - if (hasAccessibleDestructor(Base.getType(), InitLoc, SemaRef)) { + if (checkDestructorReference(Base.getType(), InitLoc, SemaRef)) { hadError = true; return; } @@ -2026,7 +2034,7 @@ void InitListChecker::CheckStructUnionTypes( while (std::next(F) != Field) ++F; QualType ET = SemaRef.Context.getBaseElementType(F->getType()); - if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { + if (checkDestructorReference(ET, InitLoc, SemaRef)) { hadError = true; return; } @@ -2075,7 +2083,7 @@ void InitListChecker::CheckStructUnionTypes( if (!VerifyOnly) { QualType ET = SemaRef.Context.getBaseElementType(Field->getType()); - if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { + if (checkDestructorReference(ET, InitLoc, SemaRef)) { hadError = true; return; } @@ -2131,7 +2139,7 @@ void InitListChecker::CheckStructUnionTypes( : Field; for (RecordDecl::field_iterator E = RD->field_end(); I != E; ++I) { QualType ET = SemaRef.Context.getBaseElementType(I->getType()); - if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) { + if (checkDestructorReference(ET, IList->getEndLoc(), SemaRef)) { hadError = true; return; } @@ -6325,6 +6333,10 @@ PerformConstructorInitialization(Sema &S, if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc)) return ExprError(); + if (const ArrayType *AT = S.Context.getAsArrayType(Entity.getType())) + if (checkDestructorReference(S.Context.getBaseElementType(AT), Loc, S)) + return ExprError(); + if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); |