/// \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;
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);
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() {
}
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()];
addedClassSubobject(Type->getAsCXXRecordDecl());
data().getVBases()[I] = *VBases[I];
}
+
+ data().IsParsingBaseSpecifiers = false;
}
void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
}
MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const {
- if (!hasDefinition())
+ if (!hasDefinition() || isParsingBaseSpecifiers())
return MSInheritanceAttr::Keyword_unspecified_inheritance;
if (getNumVBases() > 0)
return MSInheritanceAttr::Keyword_virtual_inheritance;
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()) {
-// 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.
// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*)
}
+namespace pr19987 {
+template <typename T>
+struct S {
+ int T::*x;
+};
+
+struct U : S<U> {};
+
+static_assert(sizeof(S<U>::x) == 12, "");
+}
+
#else
struct __virtual_inheritance A;
#ifdef MEMFUN