summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp13
-rw-r--r--clang/lib/AST/CXXABI.h9
-rw-r--r--clang/lib/AST/ItaniumCXXABI.cpp8
-rw-r--r--clang/lib/AST/MicrosoftCXXABI.cpp23
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp28
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp19
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp80
7 files changed, 150 insertions, 30 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index fc40f7e8e23..9cfc97b926d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8189,6 +8189,19 @@ MangleNumberingContext *ASTContext::createMangleNumberingContext() const {
return ABI->createMangleNumberingContext();
}
+const CXXConstructorDecl *
+ASTContext::getCopyConstructorForExceptionObject(CXXRecordDecl *RD) {
+ return ABI->getCopyConstructorForExceptionObject(
+ cast<CXXRecordDecl>(RD->getFirstDecl()));
+}
+
+void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) {
+ return ABI->addCopyConstructorForExceptionObject(
+ cast<CXXRecordDecl>(RD->getFirstDecl()),
+ cast<CXXConstructorDecl>(CD->getFirstDecl()));
+}
+
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
ParamIndices[D] = index;
}
diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h
index 8e9e358525e..62c96f901e6 100644
--- a/clang/lib/AST/CXXABI.h
+++ b/clang/lib/AST/CXXABI.h
@@ -20,6 +20,7 @@
namespace clang {
class ASTContext;
+class CXXConstructorDecl;
class MemberPointerType;
class MangleNumberingContext;
@@ -41,6 +42,14 @@ public:
/// Returns a new mangling number context for this C++ ABI.
virtual MangleNumberingContext *createMangleNumberingContext() const = 0;
+
+ /// Adds a mapping from class to copy constructor for this C++ ABI.
+ virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *,
+ CXXConstructorDecl *) = 0;
+
+ /// Retrieves the mapping from class to copy constructor for this C++ ABI.
+ virtual const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0;
};
/// Creates an instance of a C++ ABI class.
diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp
index 378121c8e5b..13d4dbf1f46 100644
--- a/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/clang/lib/AST/ItaniumCXXABI.cpp
@@ -133,6 +133,14 @@ public:
return Layout.getNonVirtualSize() == PointerSize;
}
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
+ return nullptr;
+ }
+
+ void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) override {}
+
MangleNumberingContext *createMangleNumberingContext() const override {
return new ItaniumNumberingContext();
}
diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp
index 0603d3b7b9b..71b21bff77c 100644
--- a/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -63,6 +63,8 @@ public:
class MicrosoftCXXABI : public CXXABI {
ASTContext &Context;
+ llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
+
public:
MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
@@ -82,13 +84,26 @@ public:
return false;
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
+
// In the Microsoft ABI, classes can have one or two vtable pointers.
- CharUnits PointerSize =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+ CharUnits PointerSize =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
return Layout.getNonVirtualSize() == PointerSize ||
Layout.getNonVirtualSize() == PointerSize * 2;
- }
+ }
+
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
+ return RecordToCopyCtor[RD];
+ }
+
+ void
+ addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD) override {
+ assert(CD != nullptr);
+ assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
+ RecordToCopyCtor[RD] = CD;
+ }
MangleNumberingContext *createMangleNumberingContext() const override {
return new MicrosoftNumberingContext();
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 29af2cb9c2c..3f660c9f69e 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -114,8 +114,8 @@ public:
uint32_t NumEntries, raw_ostream &Out) override;
void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
raw_ostream &Out) override;
- void mangleCXXCatchableType(QualType T, uint32_t Size,
- raw_ostream &Out) override;
+ void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
+ uint32_t Size, raw_ostream &Out) override;
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
@@ -2307,13 +2307,25 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray(
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
-void MicrosoftMangleContextImpl::mangleCXXCatchableType(QualType T,
- uint32_t Size,
- raw_ostream &Out) {
+void MicrosoftMangleContextImpl::mangleCXXCatchableType(
+ QualType T, const CXXConstructorDecl *CD, uint32_t Size, raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_CT??_R0";
- Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
- Mangler.getStream() << "@8";
+ Mangler.getStream() << "_CT";
+
+ llvm::SmallString<64> RTTIMangling;
+ {
+ llvm::raw_svector_ostream Stream(RTTIMangling);
+ mangleCXXRTTI(T, Stream);
+ }
+ Mangler.getStream() << RTTIMangling.substr(1);
+
+ llvm::SmallString<64> CopyCtorMangling;
+ if (CD) {
+ llvm::raw_svector_ostream Stream(CopyCtorMangling);
+ mangleCXXCtor(CD, Ctor_Complete, Stream);
+ }
+ Mangler.getStream() << CopyCtorMangling.substr(1);
+
Mangler.getStream() << Size;
}
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index dd4c274e245..4e3d50b408e 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -17,6 +17,7 @@
#include "CGCXXABI.h"
#include "CGVTables.h"
#include "CodeGenModule.h"
+#include "CodeGenTypes.h"
#include "TargetInfo.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -3225,11 +3226,14 @@ llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
uint32_t VBIndex) {
assert(!T->isReferenceType());
+ CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+ const CXXConstructorDecl *CD =
+ RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr;
uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();
SmallString<256> MangledName;
{
llvm::raw_svector_ostream Out(MangledName);
- getMangleContext().mangleCXXCatchableType(T, Size, Out);
+ getMangleContext().mangleCXXCatchableType(T, CD, Size, Out);
}
if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
return getImageRelativeConstant(GV);
@@ -3241,16 +3245,15 @@ llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
// The runtime is responsible for calling the copy constructor if the
// exception is caught by value.
llvm::Constant *CopyCtor =
- getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy));
+ CD ? llvm::ConstantExpr::getBitCast(
+ CGM.getAddrOfCXXStructor(CD, StructorType::Complete),
+ CGM.Int8PtrTy)
+ : llvm::Constant::getNullValue(CGM.Int8PtrTy);
+ CopyCtor = getImageRelativeConstant(CopyCtor);
- bool IsScalar = true;
+ bool IsScalar = !RD;
bool HasVirtualBases = false;
bool IsStdBadAlloc = false; // std::bad_alloc is special for some reason.
- if (T->getAsCXXRecordDecl()) {
- IsScalar = false;
- // TODO: Fill in the CopyCtor here! This is not trivial due to
- // copy-constructors possessing things like default arguments.
- }
QualType PointeeType = T;
if (T->isPointerType())
PointeeType = T->getPointeeType();
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 29e5150073d..0cedf349b95 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -657,6 +657,55 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope);
}
+static void
+collectPublicBases(CXXRecordDecl *RD,
+ llvm::DenseMap<CXXRecordDecl *, unsigned> &SubobjectsSeen,
+ llvm::SmallPtrSetImpl<CXXRecordDecl *> &VBases,
+ llvm::SetVector<CXXRecordDecl *> &PublicSubobjectsSeen,
+ bool ParentIsPublic) {
+ for (const CXXBaseSpecifier &BS : RD->bases()) {
+ CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl();
+ bool NewSubobject;
+ // Virtual bases constitute the same subobject. Non-virtual bases are
+ // always distinct subobjects.
+ if (BS.isVirtual())
+ NewSubobject = VBases.insert(BaseDecl).second;
+ else
+ NewSubobject = true;
+
+ if (NewSubobject)
+ ++SubobjectsSeen[BaseDecl];
+
+ // Only add subobjects which have public access throughout the entire chain.
+ bool PublicPath = ParentIsPublic && BS.getAccessSpecifier() == AS_public;
+ if (PublicPath)
+ PublicSubobjectsSeen.insert(BaseDecl);
+
+ // Recurse on to each base subobject.
+ collectPublicBases(BaseDecl, SubobjectsSeen, VBases, PublicSubobjectsSeen,
+ PublicPath);
+ }
+}
+
+static void getUnambiguousPublicSubobjects(
+ CXXRecordDecl *RD, llvm::SmallVectorImpl<CXXRecordDecl *> &Objects) {
+ llvm::DenseMap<CXXRecordDecl *, unsigned> SubobjectsSeen;
+ llvm::SmallSet<CXXRecordDecl *, 2> VBases;
+ llvm::SetVector<CXXRecordDecl *> PublicSubobjectsSeen;
+ SubobjectsSeen[RD] = 1;
+ PublicSubobjectsSeen.insert(RD);
+ collectPublicBases(RD, SubobjectsSeen, VBases, PublicSubobjectsSeen,
+ /*ParentIsPublic=*/true);
+
+ for (CXXRecordDecl *PublicSubobject : PublicSubobjectsSeen) {
+ // Skip ambiguous objects.
+ if (SubobjectsSeen[PublicSubobject] > 1)
+ continue;
+
+ Objects.push_back(PublicSubobject);
+ }
+}
+
/// CheckCXXThrowOperand - Validate the operand of a throw.
ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
bool IsThrownVarInScope) {
@@ -723,18 +772,29 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
return E;
// If the class has a destructor, we must be able to call it.
- if (RD->hasIrrelevantDestructor())
- return E;
+ if (!RD->hasIrrelevantDestructor()) {
+ if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
+ MarkFunctionReferenced(E->getExprLoc(), Destructor);
+ CheckDestructorAccess(E->getExprLoc(), Destructor,
+ PDiag(diag::err_access_dtor_exception) << Ty);
+ if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
+ return ExprError();
+ }
+ }
- CXXDestructorDecl *Destructor = LookupDestructor(RD);
- if (!Destructor)
- return E;
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects;
+ getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects);
+ for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) {
+ if (CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0)) {
+ if (CD->isTrivial())
+ continue;
+ MarkFunctionReferenced(E->getExprLoc(), CD);
+ Context.addCopyConstructorForExceptionObject(Subobject, CD);
+ }
+ }
+ }
- MarkFunctionReferenced(E->getExprLoc(), Destructor);
- CheckDestructorAccess(E->getExprLoc(), Destructor,
- PDiag(diag::err_access_dtor_exception) << Ty);
- if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
- return ExprError();
return E;
}
OpenPOWER on IntegriCloud