diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2018-09-07 02:38:01 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-09-07 02:38:01 +0000 |
commit | 2ccb31977c87081a668c11938a2e34cbf9d1abca (patch) | |
tree | 8888bcb2a839469f596bb2eb98022e4694e2eab6 /clang/lib/Sema/SemaInit.cpp | |
parent | b9dd61c13c7c8b353b7ba027f046062668125cd4 (diff) | |
download | bcm5719-llvm-2ccb31977c87081a668c11938a2e34cbf9d1abca.tar.gz bcm5719-llvm-2ccb31977c87081a668c11938a2e34cbf9d1abca.zip |
[Sema] Check that the destructor for each element of class type is
accessible from the context where aggregate initialization occurs.
rdar://problem/38168772
Differential Revision: https://reviews.llvm.org/D45898
llvm-svn: 341629
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 634554e0964..18a7aab1f5d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1818,6 +1818,30 @@ 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, @@ -1838,6 +1862,15 @@ void InitListChecker::CheckStructUnionTypes( if (DeclType->isUnionType() && IList->getNumInits() == 0) { RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); + if (!VerifyOnly) + for (FieldDecl *FD : RD->fields()) { + QualType ET = SemaRef.Context.getBaseElementType(FD->getType()); + if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) { + hadError = true; + return; + } + } + // If there's a default initializer, use it. if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->hasInClassInitializer()) { if (VerifyOnly) @@ -1874,13 +1907,13 @@ void InitListChecker::CheckStructUnionTypes( // If we have any base classes, they are initialized prior to the fields. for (auto &Base : Bases) { Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr; - SourceLocation InitLoc = Init ? Init->getBeginLoc() : IList->getEndLoc(); // Designated inits always initialize fields, so if we see one, all // remaining base classes have no explicit initializer. if (Init && isa<DesignatedInitExpr>(Init)) Init = nullptr; + SourceLocation InitLoc = Init ? Init->getBeginLoc() : IList->getEndLoc(); InitializedEntity BaseEntity = InitializedEntity::InitializeBase( SemaRef.Context, &Base, false, &Entity); if (Init) { @@ -1890,6 +1923,12 @@ void InitListChecker::CheckStructUnionTypes( } else if (VerifyOnly) { CheckEmptyInitializable(BaseEntity, InitLoc); } + + if (!VerifyOnly) + if (hasAccessibleDestructor(Base.getType(), InitLoc, SemaRef)) { + hadError = true; + return; + } } // If structDecl is a forward declaration, this loop won't do @@ -1900,9 +1939,11 @@ void InitListChecker::CheckStructUnionTypes( RecordDecl::field_iterator FieldEnd = RD->field_end(); bool CheckForMissingFields = !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); + bool HasDesignatedInit = false; while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); + SourceLocation InitLoc = Init->getBeginLoc(); if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) { // If we're not the subobject that matches up with the '{' for @@ -1911,6 +1952,8 @@ void InitListChecker::CheckStructUnionTypes( if (!SubobjectIsDesignatorContext) return; + HasDesignatedInit = true; + // Handle this designated initializer. Field will be updated to // the next field that we'll be initializing. if (CheckDesignatedInitializer(Entity, IList, DIE, 0, @@ -1918,6 +1961,17 @@ void InitListChecker::CheckStructUnionTypes( StructuredList, StructuredIndex, true, TopLevelObject)) hadError = true; + else if (!VerifyOnly) { + // Find the field named by the designated initializer. + RecordDecl::field_iterator F = RD->field_begin(); + while (std::next(F) != Field) + ++F; + QualType ET = SemaRef.Context.getBaseElementType(F->getType()); + if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { + hadError = true; + return; + } + } InitializedSomething = true; @@ -1960,6 +2014,14 @@ void InitListChecker::CheckStructUnionTypes( continue; } + if (!VerifyOnly) { + QualType ET = SemaRef.Context.getBaseElementType(Field->getType()); + if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) { + hadError = true; + return; + } + } + InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); CheckSubElementType(MemberEntity, IList, Field->getType(), Index, @@ -2002,6 +2064,21 @@ void InitListChecker::CheckStructUnionTypes( } } + // Check that the types of the remaining fields have accessible destructors. + if (!VerifyOnly) { + // If the initializer expression has a designated initializer, check the + // elements for which a designated initializer is not provided too. + RecordDecl::field_iterator I = HasDesignatedInit ? RD->field_begin() + : 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)) { + hadError = true; + return; + } + } + } + if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() || Index >= IList->getNumInits()) return; |