forked from OSchip/llvm-project
Revert "Revert r199416, "MS ABI: Improve selection of an inheritance model""
This reverts commit r199475 (which reverted r199416) with fixes for the breakages. We wouldn't lock an inheritance model if we saw a pointer-to-member formed as a result of the address-of operator. llvm-svn: 199482
This commit is contained in:
parent
a64851bccb
commit
1cdd96d6ad
clang
include/clang
lib
|
@ -17,6 +17,7 @@
|
||||||
#define LLVM_CLANG_AST_DECLCXX_H
|
#define LLVM_CLANG_AST_DECLCXX_H
|
||||||
|
|
||||||
#include "clang/AST/ASTUnresolvedSet.h"
|
#include "clang/AST/ASTUnresolvedSet.h"
|
||||||
|
#include "clang/AST/Attr.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
|
@ -258,16 +259,6 @@ public:
|
||||||
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
|
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The inheritance model to use for member pointers of a given CXXRecordDecl.
|
|
||||||
enum MSInheritanceModel {
|
|
||||||
MSIM_Single,
|
|
||||||
MSIM_SinglePolymorphic,
|
|
||||||
MSIM_Multiple,
|
|
||||||
MSIM_MultiplePolymorphic,
|
|
||||||
MSIM_Virtual,
|
|
||||||
MSIM_Unspecified
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief Represents a C++ struct/union/class.
|
/// \brief Represents a C++ struct/union/class.
|
||||||
///
|
///
|
||||||
/// FIXME: This class will disappear once we've properly taught RecordDecl
|
/// FIXME: This class will disappear once we've properly taught RecordDecl
|
||||||
|
@ -1608,7 +1599,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns the inheritance model used for this record.
|
/// \brief Returns the inheritance model used for this record.
|
||||||
MSInheritanceModel getMSInheritanceModel() const;
|
MSInheritanceAttr::Spelling getMSInheritanceModel() const;
|
||||||
|
/// \brief Locks-in the inheritance model for this class.
|
||||||
|
void setMSInheritanceModel();
|
||||||
|
|
||||||
/// \brief Determine whether this lambda expression was known to be dependent
|
/// \brief Determine whether this lambda expression was known to be dependent
|
||||||
/// at the time it was created, even if its context does not appear to be
|
/// at the time it was created, even if its context does not appear to be
|
||||||
|
|
|
@ -2205,6 +2205,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const Type *getClass() const { return Class; }
|
const Type *getClass() const { return Class; }
|
||||||
|
CXXRecordDecl *getMostRecentCXXRecordDecl() const;
|
||||||
|
|
||||||
bool isSugared() const { return false; }
|
bool isSugared() const { return false; }
|
||||||
QualType desugar() const { return QualType(this, 0); }
|
QualType desugar() const { return QualType(this, 0); }
|
||||||
|
|
|
@ -1378,16 +1378,11 @@ def MSInheritance : InheritableAttr {
|
||||||
let Spellings = [Keyword<"__single_inheritance">,
|
let Spellings = [Keyword<"__single_inheritance">,
|
||||||
Keyword<"__multiple_inheritance">,
|
Keyword<"__multiple_inheritance">,
|
||||||
Keyword<"__virtual_inheritance">,
|
Keyword<"__virtual_inheritance">,
|
||||||
// We use an empty string to denote an unspecified
|
Keyword<"__unspecified_inheritance">];
|
||||||
// inheritance attribute.
|
|
||||||
Keyword<"">];
|
|
||||||
let Accessors = [Accessor<"IsSingle", [Keyword<"__single_inheritance">]>,
|
let Accessors = [Accessor<"IsSingle", [Keyword<"__single_inheritance">]>,
|
||||||
Accessor<"IsMultiple", [Keyword<"__multiple_inheritance">]>,
|
Accessor<"IsMultiple", [Keyword<"__multiple_inheritance">]>,
|
||||||
Accessor<"IsVirtual", [Keyword<"__virtual_inheritance">]>,
|
Accessor<"IsVirtual", [Keyword<"__virtual_inheritance">]>,
|
||||||
Accessor<"IsUnspecified", [Keyword<"">]>];
|
Accessor<"IsUnspecified", [Keyword<"__unspecified_inheritance">]>];
|
||||||
// This index is based off the Spellings list and corresponds to the empty
|
|
||||||
// keyword "spelling."
|
|
||||||
let AdditionalMembers = [{static const int UnspecifiedSpellingIndex = 3;}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def Unaligned : IgnoredAttr {
|
def Unaligned : IgnoredAttr {
|
||||||
|
|
|
@ -92,28 +92,43 @@ static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MSInheritanceModel MSInheritanceAttrToModel(MSInheritanceAttr *Attr) {
|
static MSInheritanceAttr::Spelling
|
||||||
|
MSInheritanceAttrToModel(const MSInheritanceAttr *Attr) {
|
||||||
if (Attr->IsSingle())
|
if (Attr->IsSingle())
|
||||||
return MSIM_Single;
|
return MSInheritanceAttr::Keyword_single_inheritance;
|
||||||
else if (Attr->IsMultiple())
|
else if (Attr->IsMultiple())
|
||||||
return MSIM_Multiple;
|
return MSInheritanceAttr::Keyword_multiple_inheritance;
|
||||||
else if (Attr->IsVirtual())
|
else if (Attr->IsVirtual())
|
||||||
return MSIM_Virtual;
|
return MSInheritanceAttr::Keyword_virtual_inheritance;
|
||||||
|
|
||||||
assert(Attr->IsUnspecified() && "Expected unspecified inheritance attr");
|
assert(Attr->IsUnspecified() && "Expected unspecified inheritance attr");
|
||||||
return MSIM_Unspecified;
|
return MSInheritanceAttr::Keyword_unspecified_inheritance;
|
||||||
}
|
}
|
||||||
|
|
||||||
MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
|
static MSInheritanceAttr::Spelling
|
||||||
if (MSInheritanceAttr *IA = this->getAttr<MSInheritanceAttr>())
|
calculateInheritanceModel(const CXXRecordDecl *RD) {
|
||||||
return MSInheritanceAttrToModel(IA);
|
if (!RD->hasDefinition())
|
||||||
// If there was no explicit attribute, the record must be defined already, and
|
return MSInheritanceAttr::Keyword_unspecified_inheritance;
|
||||||
// we can figure out the inheritance model from its other properties.
|
if (RD->getNumVBases() > 0)
|
||||||
if (this->getNumVBases() > 0)
|
return MSInheritanceAttr::Keyword_virtual_inheritance;
|
||||||
return MSIM_Virtual;
|
if (usesMultipleInheritanceModel(RD))
|
||||||
if (usesMultipleInheritanceModel(this))
|
return MSInheritanceAttr::Keyword_multiple_inheritance;
|
||||||
return this->isPolymorphic() ? MSIM_MultiplePolymorphic : MSIM_Multiple;
|
return MSInheritanceAttr::Keyword_single_inheritance;
|
||||||
return this->isPolymorphic() ? MSIM_SinglePolymorphic : MSIM_Single;
|
}
|
||||||
|
|
||||||
|
MSInheritanceAttr::Spelling
|
||||||
|
CXXRecordDecl::getMSInheritanceModel() const {
|
||||||
|
MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
|
||||||
|
assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
|
||||||
|
return MSInheritanceAttrToModel(IA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXXRecordDecl::setMSInheritanceModel() {
|
||||||
|
if (hasAttr<MSInheritanceAttr>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
addAttr(MSInheritanceAttr::CreateImplicit(
|
||||||
|
getASTContext(), calculateInheritanceModel(this), getSourceRange()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of pointer and integer slots used to represent a member
|
// Returns the number of pointer and integer slots used to represent a member
|
||||||
|
@ -146,9 +161,9 @@ MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
|
||||||
// };
|
// };
|
||||||
static std::pair<unsigned, unsigned>
|
static std::pair<unsigned, unsigned>
|
||||||
getMSMemberPointerSlots(const MemberPointerType *MPT) {
|
getMSMemberPointerSlots(const MemberPointerType *MPT) {
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
unsigned Ptrs;
|
unsigned Ptrs = 0;
|
||||||
unsigned Ints = 0;
|
unsigned Ints = 0;
|
||||||
if (MPT->isMemberFunctionPointer()) {
|
if (MPT->isMemberFunctionPointer()) {
|
||||||
// Member function pointers are a struct of a function pointer followed by a
|
// Member function pointers are a struct of a function pointer followed by a
|
||||||
|
@ -156,26 +171,29 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) {
|
||||||
// function pointer is a real function if it is non-virtual and a vftable
|
// function pointer is a real function if it is non-virtual and a vftable
|
||||||
// slot thunk if it is virtual. The ints select the object base passed for
|
// slot thunk if it is virtual. The ints select the object base passed for
|
||||||
// the 'this' pointer.
|
// the 'this' pointer.
|
||||||
Ptrs = 1; // First slot is always a function pointer.
|
Ptrs = 1; // First slot is always a function pointer.
|
||||||
switch (Inheritance) {
|
switch (Inheritance) {
|
||||||
case MSIM_Unspecified: ++Ints; // VBTableOffset
|
case MSInheritanceAttr::Keyword_unspecified_inheritance:
|
||||||
case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset
|
++Ints; // VBTableOffset
|
||||||
case MSIM_MultiplePolymorphic:
|
case MSInheritanceAttr::Keyword_virtual_inheritance:
|
||||||
case MSIM_Multiple: ++Ints; // NonVirtualBaseAdjustment
|
++Ints; // VirtualBaseAdjustmentOffset
|
||||||
case MSIM_SinglePolymorphic:
|
case MSInheritanceAttr::Keyword_multiple_inheritance:
|
||||||
case MSIM_Single: break; // Nothing
|
++Ints; // NonVirtualBaseAdjustment
|
||||||
|
case MSInheritanceAttr::Keyword_single_inheritance:
|
||||||
|
break; // Nothing
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Data pointers are an aggregate of ints. The first int is an offset
|
// Data pointers are an aggregate of ints. The first int is an offset
|
||||||
// followed by vbtable-related offsets.
|
// followed by vbtable-related offsets.
|
||||||
Ptrs = 0;
|
Ints = 1; // We always have a field offset.
|
||||||
switch (Inheritance) {
|
switch (Inheritance) {
|
||||||
case MSIM_Unspecified: ++Ints; // VBTableOffset
|
case MSInheritanceAttr::Keyword_unspecified_inheritance:
|
||||||
case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset
|
++Ints; // VBTableOffset
|
||||||
case MSIM_MultiplePolymorphic:
|
case MSInheritanceAttr::Keyword_virtual_inheritance:
|
||||||
case MSIM_Multiple: // Nothing
|
++Ints; // VirtualBaseAdjustmentOffset
|
||||||
case MSIM_SinglePolymorphic:
|
case MSInheritanceAttr::Keyword_multiple_inheritance:
|
||||||
case MSIM_Single: ++Ints; // Field offset
|
case MSInheritanceAttr::Keyword_single_inheritance:
|
||||||
|
break; // Nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::make_pair(Ptrs, Ints);
|
return std::make_pair(Ptrs, Ints);
|
||||||
|
|
|
@ -2469,3 +2469,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
|
||||||
|
|
||||||
return DK_none;
|
return DK_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
|
||||||
|
return getClass()->getAsCXXRecordDecl()->getMostRecentDecl();
|
||||||
|
}
|
||||||
|
|
|
@ -1322,25 +1322,29 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Member pointer helpers.
|
// Member pointer helpers.
|
||||||
static bool hasVBPtrOffsetField(MSInheritanceModel Inheritance) {
|
static bool hasVBPtrOffsetField(MSInheritanceAttr::Spelling Inheritance) {
|
||||||
return Inheritance == MSIM_Unspecified;
|
return Inheritance == MSInheritanceAttr::Keyword_unspecified_inheritance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasOnlyOneField(bool IsMemberFunction,
|
static bool hasOnlyOneField(bool IsMemberFunction,
|
||||||
MSInheritanceModel Inheritance) {
|
MSInheritanceAttr::Spelling Inheritance) {
|
||||||
return Inheritance <= MSIM_SinglePolymorphic ||
|
if (IsMemberFunction)
|
||||||
(!IsMemberFunction && Inheritance <= MSIM_MultiplePolymorphic);
|
return Inheritance <= MSInheritanceAttr::Keyword_single_inheritance;
|
||||||
|
return Inheritance <= MSInheritanceAttr::Keyword_multiple_inheritance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only member pointers to functions need a this adjustment, since it can be
|
// Only member pointers to functions need a this adjustment, since it can be
|
||||||
// combined with the field offset for data pointers.
|
// combined with the field offset for data pointers.
|
||||||
static bool hasNonVirtualBaseAdjustmentField(bool IsMemberFunction,
|
static bool
|
||||||
MSInheritanceModel Inheritance) {
|
hasNonVirtualBaseAdjustmentField(bool IsMemberFunction,
|
||||||
return (IsMemberFunction && Inheritance >= MSIM_Multiple);
|
MSInheritanceAttr::Spelling Inheritance) {
|
||||||
|
return IsMemberFunction &&
|
||||||
|
Inheritance >= MSInheritanceAttr::Keyword_multiple_inheritance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) {
|
static bool
|
||||||
return Inheritance >= MSIM_Virtual;
|
hasVirtualBaseAdjustmentField(MSInheritanceAttr::Spelling Inheritance) {
|
||||||
|
return Inheritance >= MSInheritanceAttr::Keyword_virtual_inheritance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use zero for the field offset of a null data member pointer if we can
|
// Use zero for the field offset of a null data member pointer if we can
|
||||||
|
@ -1349,8 +1353,10 @@ static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) {
|
||||||
// use zero for null. If there are multiple fields, we can use zero even if it
|
// use zero for null. If there are multiple fields, we can use zero even if it
|
||||||
// is a valid field offset because null-ness testing will check the other
|
// is a valid field offset because null-ness testing will check the other
|
||||||
// fields.
|
// fields.
|
||||||
static bool nullFieldOffsetIsZero(MSInheritanceModel Inheritance) {
|
static bool nullFieldOffsetIsZero(const CXXRecordDecl *RD) {
|
||||||
return Inheritance != MSIM_Multiple && Inheritance != MSIM_Single;
|
return RD->getMSInheritanceModel() >=
|
||||||
|
MSInheritanceAttr::Keyword_virtual_inheritance ||
|
||||||
|
(RD->hasDefinition() && RD->isPolymorphic());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
|
bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
|
||||||
|
@ -1362,16 +1368,16 @@ bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
|
||||||
// The virtual base adjustment field is always -1 for null, so if we have one
|
// The virtual base adjustment field is always -1 for null, so if we have one
|
||||||
// we can't zero initialize. The field offset is sometimes also -1 if 0 is a
|
// we can't zero initialize. The field offset is sometimes also -1 if 0 is a
|
||||||
// valid field offset.
|
// valid field offset.
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
return (!hasVirtualBaseAdjustmentField(Inheritance) &&
|
return (!hasVirtualBaseAdjustmentField(Inheritance) &&
|
||||||
nullFieldOffsetIsZero(Inheritance));
|
nullFieldOffsetIsZero(RD));
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Type *
|
llvm::Type *
|
||||||
MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
|
MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
llvm::SmallVector<llvm::Type *, 4> fields;
|
llvm::SmallVector<llvm::Type *, 4> fields;
|
||||||
if (MPT->isMemberFunctionPointer())
|
if (MPT->isMemberFunctionPointer())
|
||||||
fields.push_back(CGM.VoidPtrTy); // FunctionPointerOrVirtualThunk
|
fields.push_back(CGM.VoidPtrTy); // FunctionPointerOrVirtualThunk
|
||||||
|
@ -1395,13 +1401,13 @@ void MicrosoftCXXABI::
|
||||||
GetNullMemberPointerFields(const MemberPointerType *MPT,
|
GetNullMemberPointerFields(const MemberPointerType *MPT,
|
||||||
llvm::SmallVectorImpl<llvm::Constant *> &fields) {
|
llvm::SmallVectorImpl<llvm::Constant *> &fields) {
|
||||||
assert(fields.empty());
|
assert(fields.empty());
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
if (MPT->isMemberFunctionPointer()) {
|
if (MPT->isMemberFunctionPointer()) {
|
||||||
// FunctionPointerOrVirtualThunk
|
// FunctionPointerOrVirtualThunk
|
||||||
fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));
|
fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));
|
||||||
} else {
|
} else {
|
||||||
if (nullFieldOffsetIsZero(Inheritance))
|
if (nullFieldOffsetIsZero(RD))
|
||||||
fields.push_back(getZeroInt()); // FieldOffset
|
fields.push_back(getZeroInt()); // FieldOffset
|
||||||
else
|
else
|
||||||
fields.push_back(getAllOnesInt()); // FieldOffset
|
fields.push_back(getAllOnesInt()); // FieldOffset
|
||||||
|
@ -1433,7 +1439,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
|
||||||
const CXXRecordDecl *RD,
|
const CXXRecordDecl *RD,
|
||||||
CharUnits NonVirtualBaseAdjustment)
|
CharUnits NonVirtualBaseAdjustment)
|
||||||
{
|
{
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
|
|
||||||
// Single inheritance class member pointer are represented as scalars instead
|
// Single inheritance class member pointer are represented as scalars instead
|
||||||
// of aggregates.
|
// of aggregates.
|
||||||
|
@ -1464,7 +1470,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
|
||||||
llvm::Constant *
|
llvm::Constant *
|
||||||
MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
|
MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
|
||||||
CharUnits offset) {
|
CharUnits offset) {
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
llvm::Constant *FirstField =
|
llvm::Constant *FirstField =
|
||||||
llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
|
llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
|
||||||
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
|
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
|
||||||
|
@ -1487,8 +1493,8 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
|
||||||
// FIXME PR15713: Support virtual inheritance paths.
|
// FIXME PR15713: Support virtual inheritance paths.
|
||||||
|
|
||||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
|
||||||
return BuildMemberPointer(MPT->getClass()->getAsCXXRecordDecl(),
|
return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD,
|
||||||
MD, ThisAdjustment);
|
ThisAdjustment);
|
||||||
|
|
||||||
CharUnits FieldOffset =
|
CharUnits FieldOffset =
|
||||||
getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
|
getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
|
||||||
|
@ -1501,6 +1507,7 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
|
||||||
CharUnits NonVirtualBaseAdjustment) {
|
CharUnits NonVirtualBaseAdjustment) {
|
||||||
assert(MD->isInstance() && "Member function must not be static!");
|
assert(MD->isInstance() && "Member function must not be static!");
|
||||||
MD = MD->getCanonicalDecl();
|
MD = MD->getCanonicalDecl();
|
||||||
|
RD = RD->getMostRecentDecl();
|
||||||
CodeGenTypes &Types = CGM.getTypes();
|
CodeGenTypes &Types = CGM.getTypes();
|
||||||
|
|
||||||
llvm::Constant *FirstField;
|
llvm::Constant *FirstField;
|
||||||
|
@ -1578,8 +1585,8 @@ MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
|
||||||
|
|
||||||
// If this is a single field member pointer (single inheritance), this is a
|
// If this is a single field member pointer (single inheritance), this is a
|
||||||
// single icmp.
|
// single icmp.
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
if (hasOnlyOneField(MPT->isMemberFunctionPointer(), Inheritance))
|
if (hasOnlyOneField(MPT->isMemberFunctionPointer(), Inheritance))
|
||||||
return Builder.CreateICmp(Eq, L, R);
|
return Builder.CreateICmp(Eq, L, R);
|
||||||
|
|
||||||
|
@ -1760,8 +1767,8 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||||
llvm::Type *PType =
|
llvm::Type *PType =
|
||||||
CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
|
CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
|
||||||
CGBuilderTy &Builder = CGF.Builder;
|
CGBuilderTy &Builder = CGF.Builder;
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
|
|
||||||
// Extract the fields we need, regardless of model. We'll apply them if we
|
// Extract the fields we need, regardless of model. We'll apply them if we
|
||||||
// have them.
|
// have them.
|
||||||
|
@ -1795,9 +1802,9 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||||
return Builder.CreateBitCast(Addr, PType);
|
return Builder.CreateBitCast(Addr, PType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MSInheritanceModel
|
static MSInheritanceAttr::Spelling
|
||||||
getInheritanceFromMemptr(const MemberPointerType *MPT) {
|
getInheritanceFromMemptr(const MemberPointerType *MPT) {
|
||||||
return MPT->getClass()->getAsCXXRecordDecl()->getMSInheritanceModel();
|
return MPT->getMostRecentCXXRecordDecl()->getMSInheritanceModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *
|
llvm::Value *
|
||||||
|
@ -1817,15 +1824,17 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||||
const MemberPointerType *SrcTy =
|
const MemberPointerType *SrcTy =
|
||||||
E->getSubExpr()->getType()->castAs<MemberPointerType>();
|
E->getSubExpr()->getType()->castAs<MemberPointerType>();
|
||||||
const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
|
const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
|
||||||
MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
|
|
||||||
MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
|
|
||||||
bool IsFunc = SrcTy->isMemberFunctionPointer();
|
bool IsFunc = SrcTy->isMemberFunctionPointer();
|
||||||
|
|
||||||
// If the classes use the same null representation, reinterpret_cast is a nop.
|
// If the classes use the same null representation, reinterpret_cast is a nop.
|
||||||
bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;
|
bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;
|
||||||
if (IsReinterpret && (IsFunc ||
|
if (IsReinterpret && IsFunc)
|
||||||
nullFieldOffsetIsZero(SrcInheritance) ==
|
return Src;
|
||||||
nullFieldOffsetIsZero(DstInheritance)))
|
|
||||||
|
CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl();
|
||||||
|
CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
|
||||||
|
if (IsReinterpret &&
|
||||||
|
nullFieldOffsetIsZero(SrcRD) == nullFieldOffsetIsZero(DstRD))
|
||||||
return Src;
|
return Src;
|
||||||
|
|
||||||
CGBuilderTy &Builder = CGF.Builder;
|
CGBuilderTy &Builder = CGF.Builder;
|
||||||
|
@ -1854,6 +1863,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||||
llvm::Value *NonVirtualBaseAdjustment = 0;
|
llvm::Value *NonVirtualBaseAdjustment = 0;
|
||||||
llvm::Value *VirtualBaseAdjustmentOffset = 0;
|
llvm::Value *VirtualBaseAdjustmentOffset = 0;
|
||||||
llvm::Value *VBPtrOffset = 0;
|
llvm::Value *VBPtrOffset = 0;
|
||||||
|
MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel();
|
||||||
if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
|
if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
|
||||||
// We need to extract values.
|
// We need to extract values.
|
||||||
unsigned I = 0;
|
unsigned I = 0;
|
||||||
|
@ -1884,6 +1894,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||||
// FIXME PR15713: Support conversions through virtually derived classes.
|
// FIXME PR15713: Support conversions through virtually derived classes.
|
||||||
|
|
||||||
// Recompose dst from the null struct and the adjusted fields from src.
|
// Recompose dst from the null struct and the adjusted fields from src.
|
||||||
|
MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel();
|
||||||
llvm::Value *Dst;
|
llvm::Value *Dst;
|
||||||
if (hasOnlyOneField(IsFunc, DstInheritance)) {
|
if (hasOnlyOneField(IsFunc, DstInheritance)) {
|
||||||
Dst = FirstField;
|
Dst = FirstField;
|
||||||
|
@ -1929,8 +1940,8 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
|
||||||
if (E->getCastKind() == CK_ReinterpretMemberPointer)
|
if (E->getCastKind() == CK_ReinterpretMemberPointer)
|
||||||
return Src;
|
return Src;
|
||||||
|
|
||||||
MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
|
MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy);
|
||||||
MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
|
MSInheritanceAttr::Spelling DstInheritance = getInheritanceFromMemptr(DstTy);
|
||||||
|
|
||||||
// Decompose src.
|
// Decompose src.
|
||||||
llvm::Constant *FirstField = Src;
|
llvm::Constant *FirstField = Src;
|
||||||
|
@ -1991,13 +2002,13 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||||
assert(MPT->isMemberFunctionPointer());
|
assert(MPT->isMemberFunctionPointer());
|
||||||
const FunctionProtoType *FPT =
|
const FunctionProtoType *FPT =
|
||||||
MPT->getPointeeType()->castAs<FunctionProtoType>();
|
MPT->getPointeeType()->castAs<FunctionProtoType>();
|
||||||
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
|
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
|
||||||
llvm::FunctionType *FTy =
|
llvm::FunctionType *FTy =
|
||||||
CGM.getTypes().GetFunctionType(
|
CGM.getTypes().GetFunctionType(
|
||||||
CGM.getTypes().arrangeCXXMethodType(RD, FPT));
|
CGM.getTypes().arrangeCXXMethodType(RD, FPT));
|
||||||
CGBuilderTy &Builder = CGF.Builder;
|
CGBuilderTy &Builder = CGF.Builder;
|
||||||
|
|
||||||
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
|
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
|
||||||
|
|
||||||
// Extract the fields we need, regardless of model. We'll apply them if we
|
// Extract the fields we need, regardless of model. We'll apply them if we
|
||||||
// have them.
|
// have them.
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "clang/AST/ExprObjC.h"
|
#include "clang/AST/ExprObjC.h"
|
||||||
#include "clang/AST/RecordLayout.h"
|
#include "clang/AST/RecordLayout.h"
|
||||||
#include "clang/Basic/PartialDiagnostic.h"
|
#include "clang/Basic/PartialDiagnostic.h"
|
||||||
|
#include "clang/Basic/TargetInfo.h"
|
||||||
#include "clang/Sema/Initialization.h"
|
#include "clang/Sema/Initialization.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -1779,6 +1780,13 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
||||||
return TC_Failed;
|
return TC_Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
|
||||||
|
// We need to determine the inheritance model that the class will use if
|
||||||
|
// haven't yet.
|
||||||
|
Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
|
||||||
|
Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Don't allow casting between member pointers of different sizes.
|
// Don't allow casting between member pointers of different sizes.
|
||||||
if (Self.Context.getTypeSize(DestMemPtr) !=
|
if (Self.Context.getTypeSize(DestMemPtr) !=
|
||||||
Self.Context.getTypeSize(SrcMemPtr)) {
|
Self.Context.getTypeSize(SrcMemPtr)) {
|
||||||
|
|
|
@ -8855,8 +8855,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
|
||||||
if (isa<CXXDestructorDecl>(MD))
|
if (isa<CXXDestructorDecl>(MD))
|
||||||
Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
|
Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
|
||||||
|
|
||||||
return Context.getMemberPointerType(op->getType(),
|
QualType MPTy = Context.getMemberPointerType(
|
||||||
Context.getTypeDeclType(MD->getParent()).getTypePtr());
|
op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
|
||||||
|
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
|
||||||
|
RequireCompleteType(OpLoc, MPTy, 0);
|
||||||
|
return MPTy;
|
||||||
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
|
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
|
||||||
// C99 6.5.3.2p1
|
// C99 6.5.3.2p1
|
||||||
// The operand must be either an l-value or a function designator
|
// The operand must be either an l-value or a function designator
|
||||||
|
@ -8904,8 +8907,13 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
|
||||||
|
|
||||||
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
|
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
|
||||||
Ctx = Ctx->getParent();
|
Ctx = Ctx->getParent();
|
||||||
return Context.getMemberPointerType(op->getType(),
|
|
||||||
Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
|
QualType MPTy = Context.getMemberPointerType(
|
||||||
|
op->getType(),
|
||||||
|
Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
|
||||||
|
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
|
||||||
|
RequireCompleteType(OpLoc, MPTy, 0);
|
||||||
|
return MPTy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
|
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
|
||||||
|
|
|
@ -1753,35 +1753,6 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
|
||||||
return QualType();
|
return QualType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ allows the class type in a member pointer to be an incomplete type.
|
|
||||||
// In the Microsoft ABI, the size of the member pointer can vary
|
|
||||||
// according to the class type, which means that we really need a
|
|
||||||
// complete type if possible, which means we need to instantiate templates.
|
|
||||||
//
|
|
||||||
// If template instantiation fails or the type is just incomplete, we have to
|
|
||||||
// add an extra slot to the member pointer. Yes, this does cause problems
|
|
||||||
// when passing pointers between TUs that disagree about the size.
|
|
||||||
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
|
|
||||||
CXXRecordDecl *RD = Class->getAsCXXRecordDecl();
|
|
||||||
if (RD && !RD->hasAttr<MSInheritanceAttr>()) {
|
|
||||||
// Lock in the inheritance model on the first use of a member pointer.
|
|
||||||
// Otherwise we may disagree about the size at different points in the TU.
|
|
||||||
// FIXME: MSVC picks a model on the first use that needs to know the size,
|
|
||||||
// rather than on the first mention of the type, e.g. typedefs.
|
|
||||||
if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) {
|
|
||||||
// We know it doesn't have an attribute and it's incomplete, so use the
|
|
||||||
// unspecified inheritance model. If we're in the record body, we can
|
|
||||||
// figure out the inheritance model.
|
|
||||||
for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
|
|
||||||
E = RD->redecls_end(); I != E; ++I) {
|
|
||||||
I->addAttr(::new (Context) MSInheritanceAttr(RD->getSourceRange(),
|
|
||||||
Context,
|
|
||||||
MSInheritanceAttr::UnspecifiedSpellingIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust the default free function calling convention to the default method
|
// Adjust the default free function calling convention to the default method
|
||||||
// calling convention.
|
// calling convention.
|
||||||
if (T->isFunctionType())
|
if (T->isFunctionType())
|
||||||
|
@ -5096,6 +5067,18 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We lock in the inheritance model once somebody has asked us to ensure
|
||||||
|
// that a pointer-to-member type is complete.
|
||||||
|
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
|
||||||
|
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
|
||||||
|
if (!MPTy->getClass()->isDependentType()) {
|
||||||
|
RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
|
||||||
|
|
||||||
|
MPTy->getMostRecentCXXRecordDecl()->setMSInheritanceModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue