From: David Majnemer Date: Fri, 13 Jun 2014 06:43:46 +0000 (+0000) Subject: MS ABI: Fix inheritance model calculation in CRTP X-Git-Tag: llvmorg-3.5.0-rc1~2633 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5ef4fe7d8ee31c83c4ebc118b21402e7ea14c9f2;p=platform%2Fupstream%2Fllvm.git MS ABI: Fix inheritance model calculation in CRTP CRTP-like patterns involve a class which inherits from another class using itself as a template parameter. However, the base class itself may try to create a pointer-to-member which involves the derived class. This is problematic because we may not have finished parsing the most derived classes' base specifiers yet. It turns out that MSVC simply uses the unspecified inheritance model instead of doing anything fancy. This fixes PR19987. llvm-svn: 210886 --- diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 56bbbb16910c..72fad7c28e49 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -462,6 +462,9 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether this class describes a C++ lambda. bool IsLambda : 1; + /// \brief Whether we are currently parsing base specifiers. + bool IsParsingBaseSpecifiers : 1; + /// \brief The number of base class specifiers in Bases. unsigned NumBases; @@ -685,6 +688,12 @@ public: return data().Polymorphic || data().NumVBases != 0; } + void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; } + + bool isParsingBaseSpecifiers() const { + return data().IsParsingBaseSpecifiers; + } + /// \brief Sets the base classes of this struct or class. void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 0ac8b73e306e..43d0fca9f924 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -70,7 +70,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), - IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), + IsLambda(false), IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), + Bases(), VBases(), Definition(D), FirstFriend() { } @@ -334,8 +335,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, addedClassSubobject(BaseClassDecl); } - if (VBases.empty()) + if (VBases.empty()) { + data().IsParsingBaseSpecifiers = false; return; + } // Create base specifier for any direct or indirect virtual bases. data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; @@ -346,6 +349,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, addedClassSubobject(Type->getAsCXXRecordDecl()); data().getVBases()[I] = *VBases[I]; } + + data().IsParsingBaseSpecifiers = false; } void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index 359e8648278e..6870315b2160 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -93,7 +93,7 @@ static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { } MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const { - if (!hasDefinition()) + if (!hasDefinition() || isParsingBaseSpecifiers()) return MSInheritanceAttr::Keyword_unspecified_inheritance; if (getNumVBases() > 0) return MSInheritanceAttr::Keyword_virtual_inheritance; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 57e6550cec52..ed7908dfc924 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1431,6 +1431,9 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, if (!Class) return true; + // We haven't yet attached the base specifiers. + Class->setIsParsingBaseSpecifiers(); + // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. if (!Attributes.empty()) { diff --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 48bc2c721f04..18e8c827eebe 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64 -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64 +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify // FIXME: Test x86_64 member pointers when codegen no longer asserts on records // with virtual bases. @@ -630,6 +630,17 @@ void test() { void (B::*a)() = &B::f; } // CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*) } +namespace pr19987 { +template +struct S { + int T::*x; +}; + +struct U : S {}; + +static_assert(sizeof(S::x) == 12, ""); +} + #else struct __virtual_inheritance A; #ifdef MEMFUN