diff options
| author | Reid Kleckner <rnk@google.com> | 2018-05-31 18:42:29 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2018-05-31 18:42:29 +0000 |
| commit | 26fc531dbc652a7738f3c8a421b3023ca12ca1ad (patch) | |
| tree | d3e57bc853792f237164d2769825ed92043aa8e0 /clang | |
| parent | 38f7bb779854c3812ddd98cae4032788fa2722c4 (diff) | |
| download | bcm5719-llvm-26fc531dbc652a7738f3c8a421b3023ca12ca1ad.tar.gz bcm5719-llvm-26fc531dbc652a7738f3c8a421b3023ca12ca1ad.zip | |
Fix null MSInheritanceAttr deref in CXXRecordDecl::getMSInheritanceModel()
Ensure latest MPT decl has a MSInheritanceAttr when instantiating
templates, to avoid null MSInheritanceAttr deref in
CXXRecordDecl::getMSInheritanceModel().
See PR#37399 for repo / details.
Patch by Andrew Rogers!
Differential Revision: https://reviews.llvm.org/D46664
llvm-svn: 333680
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 15 | ||||
| -rw-r--r-- | clang/include/clang/AST/DeclTemplate.h | 10 | ||||
| -rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/AST/Type.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp | 118 |
7 files changed, 141 insertions, 14 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 242a9eb4ca8..a64593c79d9 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -751,6 +751,21 @@ public: return const_cast<CXXRecordDecl*>(this)->getMostRecentDecl(); } + CXXRecordDecl *getMostRecentNonInjectedDecl() { + CXXRecordDecl *Recent = + static_cast<CXXRecordDecl *>(this)->getMostRecentDecl(); + while (Recent->isInjectedClassName()) { + // FIXME: Does injected class name need to be in the redeclarations chain? + assert(Recent->getPreviousDecl()); + Recent = Recent->getPreviousDecl(); + } + return Recent; + } + + const CXXRecordDecl *getMostRecentNonInjectedDecl() const { + return const_cast<CXXRecordDecl*>(this)->getMostRecentNonInjectedDecl(); + } + CXXRecordDecl *getDefinition() const { // We only need an update if we don't already know which // declaration is the definition. diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index e15fe822bb7..a2f00ec9ffa 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1720,14 +1720,8 @@ public: // it's not clear that we should override that, because the most recent // declaration as a CXXRecordDecl sometimes is the injected-class-name. ClassTemplateSpecializationDecl *getMostRecentDecl() { - CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>( - this)->getMostRecentDecl(); - while (!isa<ClassTemplateSpecializationDecl>(Recent)) { - // FIXME: Does injected class name need to be in the redeclarations chain? - assert(Recent->isInjectedClassName() && Recent->getPreviousDecl()); - Recent = Recent->getPreviousDecl(); - } - return cast<ClassTemplateSpecializationDecl>(Recent); + return cast<ClassTemplateSpecializationDecl>( + getMostRecentNonInjectedDecl()); } /// Retrieve the template that this specialization specializes. diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 159938124be..f7b80d5b277 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1370,12 +1370,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, const NamedDecl *ND = TA.getAsDecl(); if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) { mangleMemberDataPointer( - cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentDecl(), + cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentNonInjectedDecl(), cast<ValueDecl>(ND)); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); if (MD && MD->isInstance()) { - mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD); + mangleMemberFunctionPointer(MD->getParent()->getMostRecentNonInjectedDecl(), MD); } else { Out << "$1?"; mangleName(FD); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e94ae9329f3..065a77aa507 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2040,7 +2040,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const { return false; // The inheritance attribute might only be present on the most recent // CXXRecordDecl, use that one. - RD = RD->getMostRecentDecl(); + RD = RD->getMostRecentNonInjectedDecl(); // Nothing interesting to do if the inheritance attribute is already set. if (RD->hasAttr<MSInheritanceAttr>()) return false; @@ -3936,5 +3936,5 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { } CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { - return getClass()->getAsCXXRecordDecl()->getMostRecentDecl(); + return getClass()->getAsCXXRecordDecl()->getMostRecentNonInjectedDecl(); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 2c3e1503857..a8260b49ed9 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2733,7 +2733,7 @@ MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { assert(MD->isInstance() && "Member function must not be static!"); CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); - const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl(); + const CXXRecordDecl *RD = MD->getParent()->getMostRecentNonInjectedDecl(); CodeGenTypes &Types = CGM.getTypes(); unsigned VBTableIndex = 0; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index b5a90af39ba..6839dd7de21 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -7544,7 +7544,7 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, /// Locks in the inheritance model for the given class and all of its bases. static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { - RD = RD->getMostRecentDecl(); + RD = RD->getMostRecentNonInjectedDecl(); if (!RD->hasAttr<MSInheritanceAttr>()) { MSInheritanceAttr::Spelling IM; diff --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 0f54d30ec46..471524ef720 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -3,6 +3,124 @@ // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify +namespace pr37399 { +template <typename T> +struct Functor { + void (T::*PtrToMemberFunction)(); +}; +// CHECK-DAG: %"struct.pr37399::Functor" = type { i8* } + +template <typename SomeType> +class SimpleDerivedFunctor; +template <typename SomeType> +class SimpleDerivedFunctor : public Functor<SimpleDerivedFunctor<SomeType>> {}; +// CHECK-DAG: %"class.pr37399::SimpleDerivedFunctor" = type { %"struct.pr37399::Functor" } + +SimpleDerivedFunctor<void> SimpleFunctor; +// CHECK-DAG: @"?SimpleFunctor@pr37399@@3V?$SimpleDerivedFunctor@X@1@A" = dso_local global %"class.pr37399::SimpleDerivedFunctor" zeroinitializer, align 4 + +short Global = 0; +template <typename SomeType> +class DerivedFunctor; +template <typename SomeType> +class DerivedFunctor + : public Functor<DerivedFunctor<void>> { +public: + void Foo() { + Global = 42; + } +}; + +class MultipleBase { +public: + MultipleBase() : Value() {} + short Value; +}; +// CHECK-DAG: %"class.pr37399::MultipleBase" = type { i16 } + +template <typename SomeType> +class MultiplyDerivedFunctor; +template <typename SomeType> +class MultiplyDerivedFunctor + : public Functor<MultiplyDerivedFunctor<void>>, + public MultipleBase { +public: + void Foo() { + MultipleBase::Value = 42*2; + } +}; + +class VirtualBase { +public: + VirtualBase() : Value() {} + short Value; +}; +// CHECK-DAG: %"class.pr37399::VirtualBase" = type { i16 } + +template <typename SomeType> +class VirtBaseFunctor + : public Functor<SomeType>, + public virtual VirtualBase{}; +template <typename SomeType> +class VirtuallyDerivedFunctor; +template <typename SomeType> +class VirtuallyDerivedFunctor + : public VirtBaseFunctor<VirtuallyDerivedFunctor<void>>, + public virtual VirtualBase { +public: + void Foo() { + VirtualBase::Value = 42*3; + } +}; +} // namespace pr37399 + +pr37399::DerivedFunctor<int> BFunctor; +// CHECK-DAG: @"?BFunctor@@3V?$DerivedFunctor@H@pr37399@@A" = dso_local global %"[[BFUNCTOR:class.pr37399::DerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8 +// CHECK-DAG: %"[[BFUNCTOR]]" = type { %"[[BFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]" } +// CHECK-DAG: %"[[BFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } } +pr37399::DerivedFunctor<void> AFunctor; +// CHECK-DAG: @"?AFunctor@@3V?$DerivedFunctor@X@pr37399@@A" = dso_local global %"[[AFUNCTOR:class.pr37399::DerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8 +// CHECK-DAG: %"[[AFUNCTOR]]" = type { %"[[AFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]" } +// CHECK-DAG: %"[[AFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } } + +pr37399::MultiplyDerivedFunctor<int> DFunctor; +// CHECK-DAG: @"?DFunctor@@3V?$MultiplyDerivedFunctor@H@pr37399@@A" = dso_local global %"[[DFUNCTOR:class.pr37399::MultiplyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8 +// CHECK-DAG: %"[[DFUNCTOR]]" = type { %"[[DFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", %"class.pr37399::MultipleBase", [6 x i8] } +// CHECK-DAG: %"[[DFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } } +pr37399::MultiplyDerivedFunctor<void> CFunctor; +// CHECK-DAG: @"?CFunctor@@3V?$MultiplyDerivedFunctor@X@pr37399@@A" = dso_local global %"[[CFUNCTOR:class.pr37399::MultiplyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8 +// CHECK-DAG: %"[[CFUNCTOR]]" = type { %"[[CFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", %"class.pr37399::MultipleBase", [6 x i8] } +// CHECK-DAG: %"[[CFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } } + +pr37399::VirtuallyDerivedFunctor<int> FFunctor; +// CHECK-DAG: @"?FFunctor@@3V?$VirtuallyDerivedFunctor@H@pr37399@@A" = dso_local global %"[[FFUNCTOR:class.pr37399::VirtuallyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8 +// CHECK-DAG: %"[[FFUNCTOR]]" = type { %"class.pr37399::VirtBaseFunctor.base", %"class.pr37399::VirtualBase" } +pr37399::VirtuallyDerivedFunctor<void> EFunctor; +// CHECK-DAG: @"?EFunctor@@3V?$VirtuallyDerivedFunctor@X@pr37399@@A" = dso_local global %"[[EFUNCTOR:class.pr37399::VirtuallyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8 +// CHECK-DAG: %"[[EFUNCTOR]]" = type { %"class.pr37399::VirtBaseFunctor.base", %"class.pr37399::VirtualBase" } + +// CHECK-DAG: %"class.pr37399::VirtBaseFunctor.base" = type <{ %"[[VFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", i32*, [4 x i8] }> +// CHECK-DAG: %"[[VFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } } + +namespace pr37399 { +void SingleInheritanceFnPtrCall() { + BFunctor.PtrToMemberFunction = &DerivedFunctor<void>::Foo; + (AFunctor.*(BFunctor.PtrToMemberFunction))(); +} +void MultipleInheritanceFnPtrCall() { + DFunctor.PtrToMemberFunction = &MultiplyDerivedFunctor<void>::Foo; + Global = CFunctor.MultipleBase::Value; + (CFunctor.*(DFunctor.PtrToMemberFunction))(); + Global = CFunctor.MultipleBase::Value; +} +void VirtualInheritanceFnPtrCall() { + FFunctor.PtrToMemberFunction = &VirtuallyDerivedFunctor<void>::Foo; + Global = EFunctor.VirtualBase::Value; + (EFunctor.*(FFunctor.PtrToMemberFunction))(); + Global = EFunctor.VirtualBase::Value; +} +} // namespace pr37399 + struct PR26313_Y; typedef void (PR26313_Y::*PR26313_FUNC)(); struct PR26313_X { |

