diff options
| -rw-r--r-- | clang/include/clang/Sema/ExternalSemaSource.h | 8 | ||||
| -rw-r--r-- | clang/include/clang/Sema/MultiplexExternalSemaSource.h | 8 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 8 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTBitCodes.h | 3 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/MultiplexExternalSemaSource.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 50 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 15 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 8 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/arm64.cpp | 30 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/cxx11-vtable-key-function.cpp | 6 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/key-function-vtable.cpp | 14 |
14 files changed, 53 insertions, 132 deletions
diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h index c0ef7121a6e..168835b1787 100644 --- a/clang/include/clang/Sema/ExternalSemaSource.h +++ b/clang/include/clang/Sema/ExternalSemaSource.h @@ -128,14 +128,6 @@ public: /// introduce the same declarations repeatedly. virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {} - /// \brief Read the set of dynamic classes known to the external Sema source. - /// - /// The external source should append its own dynamic classes to - /// the given vector of declarations. Note that this routine may be - /// invoked multiple times; the external source should take care not to - /// introduce the same declarations repeatedly. - virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {} - /// \brief Read the set of potentially unused typedefs known to the source. /// /// The external source should append its own potentially unused local diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index f06d19629a3..50e2553f2bf 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -274,14 +274,6 @@ public: /// introduce the same declarations repeatedly. void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override; - /// \brief Read the set of dynamic classes known to the external Sema source. - /// - /// The external source should append its own dynamic classes to - /// the given vector of declarations. Note that this routine may be - /// invoked multiple times; the external source should take care not to - /// introduce the same declarations repeatedly. - void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls) override; - /// \brief Read the set of potentially unused typedefs known to the source. /// /// The external source should append its own potentially unused local diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 712e0cedba4..e304bb8cd41 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5059,14 +5059,6 @@ public: /// \brief Load any externally-stored vtable uses. void LoadExternalVTableUses(); - typedef LazyVector<CXXRecordDecl *, ExternalSemaSource, - &ExternalSemaSource::ReadDynamicClasses, 2, 2> - DynamicClassesType; - - /// \brief A list of all of the dynamic classes in this translation - /// unit. - DynamicClassesType DynamicClasses; - /// \brief Note that the vtable for the given class was used at the /// given location. void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index ef5f1dd184c..b5136773d0e 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -425,8 +425,7 @@ namespace clang { /// \brief Record code for the array of VTable uses. VTABLE_USES = 19, - /// \brief Record code for the array of dynamic classes. - DYNAMIC_CLASSES = 20, + // ID 20 used to be for a list of dynamic classes. /// \brief Record code for referenced selector pool. REFERENCED_SELECTOR_POOL = 21, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 27af9995aa9..cfb35e33425 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -776,12 +776,6 @@ private: /// local extern "C" declarations. SmallVector<uint64_t, 16> LocallyScopedExternCDecls; - /// \brief The IDs of all dynamic class declarations in the chain. - /// - /// Sema tracks these because it checks for the key functions being defined - /// at the end of the TU, in which case it directs CodeGen to emit the VTable. - SmallVector<uint64_t, 16> DynamicClasses; - /// \brief The IDs of all potentially unused typedef names in the chain. /// /// Sema tracks these to emit warnings. @@ -1818,8 +1812,6 @@ public: void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) override; - void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) override; - void ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override; diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 449ddf43114..a0315777675 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -236,12 +236,6 @@ void MultiplexExternalSemaSource::ReadExtVectorDecls( Sources[i]->ReadExtVectorDecls(Decls); } -void MultiplexExternalSemaSource::ReadDynamicClasses( - SmallVectorImpl<CXXRecordDecl*> &Decls) { - for(size_t i = 0; i < Sources.size(); ++i) - Sources[i]->ReadDynamicClasses(Decls); -} - void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) { for(size_t i = 0; i < Sources.size(); ++i) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 5170c244bbf..a851ce14556 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -621,22 +621,6 @@ void Sema::ActOnEndOfTranslationUnit() { if (TUKind != TU_Prefix) { DiagnoseUseOfUnimplementedSelectors(); - // If any dynamic classes have their key function defined within - // this translation unit, then those vtables are considered "used" and must - // be emitted. - for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource), - E = DynamicClasses.end(); - I != E; ++I) { - assert(!(*I)->isDependentType() && - "Should not see dependent types here!"); - if (const CXXMethodDecl *KeyFunction = - Context.getCurrentKeyFunction(*I)) { - const FunctionDecl *Definition = nullptr; - if (KeyFunction->hasBody(Definition)) - MarkVTableUsed(Definition->getLocation(), *I, true); - } - } - // If DefinedUsedVTables ends up marking any virtual member functions it // might lead to more pending template instantiations, which we then need // to instantiate. @@ -668,6 +652,8 @@ void Sema::ActOnEndOfTranslationUnit() { // All delayed member exception specs should be checked or we end up accepting // incompatible declarations. + // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to + // write out the lists to the AST file (if any). assert(DelayedDefaultedMemberExceptionSpecs.empty()); assert(DelayedExceptionSpecChecks.empty()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e2547739f43..eb5b7154936 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8011,28 +8011,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // This needs to happen first so that 'inline' propagates. NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); - if (isa<CXXMethodDecl>(NewFD)) { - // A valid redeclaration of a C++ method must be out-of-line, - // but (unfortunately) it's not necessarily a definition - // because of templates, which means that the previous - // declaration is not necessarily from the class definition. - - // For just setting the access, that doesn't matter. - CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl); - NewFD->setAccess(oldMethod->getAccess()); - - // Update the key-function state if necessary for this ABI. - if (NewFD->isInlined() && - !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { - // setNonKeyFunction needs to work with the original - // declaration from the class definition, and isVirtual() is - // just faster in that case, so map back to that now. - oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDecl()); - if (oldMethod->isVirtual()) { - Context.setNonKeyFunction(oldMethod); - } - } - } + if (isa<CXXMethodDecl>(NewFD)) + NewFD->setAccess(OldDecl->getAccess()); } } @@ -10559,7 +10539,31 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, !FD->isDependentContext()) computeNRVO(Body, getCurFunction()); } - + + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { + const CXXMethodDecl *KeyFunction; + if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) && + MD->isVirtual() && + (KeyFunction = Context.getCurrentKeyFunction(MD->getParent())) && + MD == KeyFunction->getCanonicalDecl()) { + // Update the key-function state if necessary for this ABI. + if (FD->isInlined() && + !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { + Context.setNonKeyFunction(MD); + + // If the newly-chosen key function is already defined, then we + // need to mark the vtable as used retroactively. + KeyFunction = Context.getCurrentKeyFunction(MD->getParent()); + const FunctionDecl *Definition; + if (KeyFunction && KeyFunction->isDefined(Definition)) + MarkVTableUsed(Definition->getLocation(), MD->getParent(), true); + } else { + // We just defined they key function; mark the vtable as used. + MarkVTableUsed(FD->getLocation(), MD->getParent(), true); + } + } + } + assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c41dc3309a5..c78f214fbca 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4875,9 +4875,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } - if (Record->isDynamicClass() && !Record->isDependentType()) - DynamicClasses.push_back(Record); - if (Record->getIdentifier()) { // C++ [class.mem]p13: // If T is the name of a class, then each of the following shall have a diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 9d9885b7930..78c44d17887 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3099,11 +3099,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } break; - case DYNAMIC_CLASSES: - for (unsigned I = 0, N = Record.size(); I != N; ++I) - DynamicClasses.push_back(getGlobalDeclID(F, Record[I])); - break; - case PENDING_IMPLICIT_INSTANTIATIONS: if (PendingInstantiations.size() % 2 != 0) { Error("Invalid existing PendingInstantiations"); @@ -7312,16 +7307,6 @@ void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) { ExtVectorDecls.clear(); } -void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) { - for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) { - CXXRecordDecl *D - = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I])); - if (D) - Decls.push_back(D); - } - DynamicClasses.clear(); -} - void ASTReader::ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) { for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index c70935c0c7d..e04c46ed982 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4344,10 +4344,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) AddDeclRef(TD, UnusedLocalTypedefNameCandidates); - // Build a record containing all of dynamic classes declarations. - RecordData DynamicClasses; - AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses); - // Build a record containing all of pending implicit instantiations. RecordData PendingInstantiations; for (std::deque<Sema::PendingImplicitInstantiation>::iterator @@ -4628,10 +4624,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, if (!VTableUses.empty()) Stream.EmitRecord(VTABLE_USES, VTableUses); - // Write the record containing dynamic classes declarations. - if (!DynamicClasses.empty()) - Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses); - // Write the record containing potentially unused local typedefs. if (!UnusedLocalTypedefNameCandidates.empty()) Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, diff --git a/clang/test/CodeGenCXX/arm64.cpp b/clang/test/CodeGenCXX/arm64.cpp index d0d4f4f70ef..a1c46bc9e55 100644 --- a/clang/test/CodeGenCXX/arm64.cpp +++ b/clang/test/CodeGenCXX/arm64.cpp @@ -45,33 +45,34 @@ namespace test2 { virtual void foo(); }; void A::foo() {} - // Tested below because these globals get kindof oddly rearranged. + // CHECK-GLOBALS-DAG: @_ZTSN5test21AE = constant [11 x i8] + // CHECK-GLOBALS-DAG: @_ZTIN5test21AE = constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21AE, i32 0, i32 0) } struct __attribute__((visibility("hidden"))) B {}; const std::type_info &b0 = typeid(B); - // CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant - // CHECK-GLOBALS: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21BE, i32 0, i32 0) } + // CHECK-GLOBALS-DAG: @_ZTSN5test21BE = linkonce_odr hidden constant + // CHECK-GLOBALS-DAG: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21BE, i32 0, i32 0) } const std::type_info &b1 = typeid(B*); - // CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant - // CHECK-GLOBALS: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([12 x i8]* @_ZTSPN5test21BE, i32 0, i32 0), i32 0, i8* bitcast + // CHECK-GLOBALS-DAG: @_ZTSPN5test21BE = linkonce_odr hidden constant + // CHECK-GLOBALS-DAG: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([12 x i8]* @_ZTSPN5test21BE, i32 0, i32 0), i32 0, i8* bitcast struct C {}; const std::type_info &c0 = typeid(C); - // CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr hidden constant - // CHECK-GLOBALS: @_ZTIN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([11 x i8]* @_ZTSN5test21CE to i64), i64 -9223372036854775808) to i8*) } + // CHECK-GLOBALS-DAG: @_ZTSN5test21CE = linkonce_odr hidden constant + // CHECK-GLOBALS-DAG: @_ZTIN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([11 x i8]* @_ZTSN5test21CE to i64), i64 -9223372036854775808) to i8*) } const std::type_info &c1 = typeid(C*); - // CHECK-GLOBALS: @_ZTSPN5test21CE = linkonce_odr hidden constant - // CHECK-GLOBALS: @_ZTIPN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([12 x i8]* @_ZTSPN5test21CE to i64), i64 -9223372036854775808) to i8*), i32 0, i8* bitcast + // CHECK-GLOBALS-DAG: @_ZTSPN5test21CE = linkonce_odr hidden constant + // CHECK-GLOBALS-DAG: @_ZTIPN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([12 x i8]* @_ZTSPN5test21CE to i64), i64 -9223372036854775808) to i8*), i32 0, i8* bitcast // This class is explicitly-instantiated, but that instantiation // doesn't guarantee to emit RTTI, so we can still demote the visibility. template <class T> class D {}; template class D<int>; const std::type_info &d0 = typeid(D<int>); - // CHECK-GLOBALS: @_ZTSN5test21DIiEE = linkonce_odr hidden constant - // CHECK-GLOBALS: @_ZTIN5test21DIiEE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21DIiEE to i64), i64 -9223372036854775808) to i8*) } + // CHECK-GLOBALS-DAG: @_ZTSN5test21DIiEE = linkonce_odr hidden constant + // CHECK-GLOBALS-DAG: @_ZTIN5test21DIiEE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21DIiEE to i64), i64 -9223372036854775808) to i8*) } // This class is explicitly-instantiated and *does* guarantee to // emit RTTI, so we're stuck with having to use default visibility. @@ -79,10 +80,7 @@ namespace test2 { virtual void foo() {} }; template class E<int>; - // CHECK-GLOBALS: @_ZTSN5test21EIiEE = weak_odr constant [14 x i8] - // CHECK-GLOBALS: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to i8*) } - - // CHECK-GLOBALS: @_ZTSN5test21AE = constant [11 x i8] - // CHECK-GLOBALS: @_ZTIN5test21AE = constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21AE, i32 0, i32 0) } + // CHECK-GLOBALS-DAG: @_ZTSN5test21EIiEE = weak_odr constant [14 x i8] + // CHECK-GLOBALS-DAG: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to i8*) } } diff --git a/clang/test/CodeGenCXX/cxx11-vtable-key-function.cpp b/clang/test/CodeGenCXX/cxx11-vtable-key-function.cpp index cd2ab59506d..a4a00026487 100644 --- a/clang/test/CodeGenCXX/cxx11-vtable-key-function.cpp +++ b/clang/test/CodeGenCXX/cxx11-vtable-key-function.cpp @@ -10,7 +10,7 @@ struct X { X::~X() = default; // Verify that the vtable is emitted. -// CHECK: @_ZTVN5Test11XE = unnamed_addr constant +// CHECK-DAG: @_ZTVN5Test11XE = unnamed_addr constant } namespace Test2 { @@ -22,7 +22,7 @@ struct X { void X::f() {} // Verify that the vtable is emitted. -// CHECK: @_ZTVN5Test21XE = unnamed_addr constant +// CHECK-DAG: @_ZTVN5Test21XE = unnamed_addr constant } namespace Test3 { @@ -34,5 +34,5 @@ struct X { void X::f() {} // Verify that the vtable is emitted. -// CHECK: @_ZTVN5Test31XE = unnamed_addr constant +// CHECK-DAG: @_ZTVN5Test31XE = unnamed_addr constant } diff --git a/clang/test/CodeGenCXX/key-function-vtable.cpp b/clang/test/CodeGenCXX/key-function-vtable.cpp index 80ce497505d..f6aa16e51a9 100644 --- a/clang/test/CodeGenCXX/key-function-vtable.cpp +++ b/clang/test/CodeGenCXX/key-function-vtable.cpp @@ -43,11 +43,9 @@ inline void X1::f() { } void use_X1() { X1 x1; } -// FIXME: The checks are extremely difficult to get right when the globals -// aren't alphabetized -// CHECK: @_ZTV2X1 = linkonce_odr unnamed_addr constant -// CHECK: @_ZTV5testa = unnamed_addr constant [3 x i8*] [i8* null -// CHECK: @_ZTV5testc = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null -// CHECK: @_ZTV5testb = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null -// CHECK: @_ZTV5teste = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null -// CHECK: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV2X1 = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTV5testa = unnamed_addr constant [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null +// CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant [3 x i8*] [i8* null |

