diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2016-01-26 19:30:26 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2016-01-26 19:30:26 +0000 |
| commit | 929025d1a614bef2ef68a50898cccfb283d3abf3 (patch) | |
| tree | 758e87b50d534c9056b623580b78ade5983335b6 /clang/lib/CodeGen | |
| parent | 59066a0803e7cc10ba004cf862baf19a4ad161ca (diff) | |
| download | bcm5719-llvm-929025d1a614bef2ef68a50898cccfb283d3abf3.tar.gz bcm5719-llvm-929025d1a614bef2ef68a50898cccfb283d3abf3.zip | |
[MS ABI] Allow a member pointers' converted type to change
Member pointers in the MS ABI are tricky for a variety of reasons.
The size of a member pointer is indeterminate until the program reaches
a point where the representation is required to be known. However,
*pointers* to member pointers may exist without knowing the pointee
type's representation. In these cases, we synthesize an opaque LLVM
type for the pointee type.
However, we can be in a situation where the underlying member pointer's
representation became known mid-way through the program. To account for
this, we attempted to manicure CodeGen's type-cache so that we can
replace the opaque member pointer type with the real deal while leaving
the pointer types unperturbed. This, unfortunately, is a problematic
approach to take as we will violate CodeGen's invariants.
These violations are mostly harmless but let's do the right thing
instead: invalidate the type-cache if a member pointer's LLVM
representation changes.
This fixes PR26313.
llvm-svn: 258839
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CodeGenAction.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 2 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 6 | ||||
| -rw-r--r-- | clang/lib/CodeGen/ModuleBuilder.cpp | 7 |
6 files changed, 42 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index cdd9d09d048..f8ae031f0f3 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -210,6 +210,10 @@ namespace clang { Gen->CompleteTentativeDefinition(D); } + void AssignInheritanceModel(CXXRecordDecl *RD) override { + Gen->AssignInheritanceModel(RD); + } + void HandleVTable(CXXRecordDecl *RD) override { Gen->HandleVTable(RD); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index ae46b12b80d..be8171971bb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -489,6 +489,11 @@ void CodeGenModule::UpdateCompletedType(const TagDecl *TD) { Types.UpdateCompletedType(TD); } +void CodeGenModule::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { + // Make sure that this type is translated. + Types.RefreshTypeCacheForClass(RD); +} + llvm::MDNode *CodeGenModule::getTBAAInfo(QualType QTy) { if (!TBAA) return nullptr; diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 046bc2a9fe5..74087be3f6a 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -994,6 +994,8 @@ public: void EmitVTable(CXXRecordDecl *Class); + void RefreshTypeCacheForClass(const CXXRecordDecl *Class); + /// \brief Appends Opts to the "Linker Options" metadata value. void AppendLinkerOptions(StringRef Opts); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 09d9bf17b3b..554f9ff640a 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -272,6 +272,17 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { DI->completeType(RD); } +void CodeGenTypes::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { + QualType T = Context.getRecordType(RD); + T = Context.getCanonicalType(T); + + const Type *Ty = T.getTypePtr(); + if (RecordsWithOpaqueMemberPointers.count(Ty)) { + TypeCache.clear(); + RecordsWithOpaqueMemberPointers.clear(); + } +} + static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext, const llvm::fltSemantics &format, bool UseNativeHalf = false) { @@ -603,10 +614,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { } case Type::MemberPointer: { - if (!getCXXABI().isMemberPointerConvertible(cast<MemberPointerType>(Ty))) - return llvm::StructType::create(getLLVMContext()); - ResultType = - getCXXABI().ConvertMemberPointerType(cast<MemberPointerType>(Ty)); + auto *MPTy = cast<MemberPointerType>(Ty); + if (!getCXXABI().isMemberPointerConvertible(MPTy)) { + RecordsWithOpaqueMemberPointers.insert(MPTy->getClass()); + ResultType = llvm::StructType::create(getLLVMContext()); + } else { + ResultType = getCXXABI().ConvertMemberPointerType(MPTy); + } break; } diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index a96f23c4489..a673fa66810 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -162,6 +162,8 @@ class CodeGenTypes { /// corresponding llvm::Type. llvm::DenseMap<const Type *, llvm::Type *> TypeCache; + llvm::SmallSet<const Type *, 8> RecordsWithOpaqueMemberPointers; + public: CodeGenTypes(CodeGenModule &cgm); ~CodeGenTypes(); @@ -214,6 +216,10 @@ public: /// replace the 'opaque' type we previously made for it if applicable. void UpdateCompletedType(const TagDecl *TD); + /// \brief Remove stale types from the type cache when an inheritance model + /// gets assigned to a class. + void RefreshTypeCacheForClass(const CXXRecordDecl *RD); + /// getNullaryFunctionInfo - Get the function info for a void() /// function with standard CC. const CGFunctionInfo &arrangeNullaryFunction(); diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index bce19ab2fdb..9428bdf1db3 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -210,6 +210,13 @@ namespace { Builder->Release(); } + void AssignInheritanceModel(CXXRecordDecl *RD) override { + if (Diags.hasErrorOccurred()) + return; + + Builder->RefreshTypeCacheForClass(RD); + } + void CompleteTentativeDefinition(VarDecl *D) override { if (Diags.hasErrorOccurred()) return; |

