Save a copy expression for non-trivial copy constructions of catch variables.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125661 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 884a184..209e5d3 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2751,6 +2751,15 @@
}
}
+const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
+ if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
+ e = ewc->getSubExpr();
+ e = cast<CXXConstructExpr>(e)->getArg(0);
+ while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
+ e = ice->getSubExpr();
+ return cast<OpaqueValueExpr>(e);
+}
+
//===----------------------------------------------------------------------===//
// ExprIterator.
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index f110f79..cde2728 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -1034,7 +1034,8 @@
const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
- if (RD->hasTrivialCopyConstructor()) {
+ const Expr *copyExpr = CatchParam.getInit();
+ if (!copyExpr) {
llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, true);
llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
CGF.EmitAggregateCopy(ParamAddr, Cast, CatchType);
@@ -1043,38 +1044,37 @@
// We have to call __cxa_get_exception_ptr to get the adjusted
// pointer before copying.
- llvm::CallInst *AdjustedExn =
+ llvm::CallInst *rawAdjustedExn =
CGF.Builder.CreateCall(getGetExceptionPtrFn(CGF), Exn);
- AdjustedExn->setDoesNotThrow();
- llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+ rawAdjustedExn->setDoesNotThrow();
- CXXConstructorDecl *CD = RD->getCopyConstructor(CGF.getContext(), 0);
- assert(CD && "record has no copy constructor!");
- llvm::Value *CopyCtor = CGF.CGM.GetAddrOfCXXConstructor(CD, Ctor_Complete);
+ // Cast that to the appropriate type.
+ llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
- CallArgList CallArgs;
- CallArgs.push_back(std::make_pair(RValue::get(ParamAddr),
- CD->getThisType(CGF.getContext())));
- CallArgs.push_back(std::make_pair(RValue::get(Cast),
- CD->getParamDecl(0)->getType()));
-
- const FunctionProtoType *FPT
- = CD->getType()->getAs<FunctionProtoType>();
+ // The copy expression is defined in terms of an OpaqueValueExpr.
+ // Find it and map it to the adjusted expression.
+ CodeGenFunction::OpaqueValueMapping
+ opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), adjustedExn);
// Call the copy ctor in a terminate scope.
CGF.EHStack.pushTerminate();
- CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
- CopyCtor, ReturnValueSlot(), CallArgs, CD);
+
+ // Perform the copy construction.
+ CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, false, false));
+
+ // Leave the terminate scope.
CGF.EHStack.popTerminate();
+ // Undo the opaque value mapping.
+ opaque.pop();
+
// Finally we can call __cxa_begin_catch.
CallBeginCatch(CGF, Exn, true);
}
/// Begins a catch statement by initializing the catch variable and
/// calling __cxa_begin_catch.
-static void BeginCatch(CodeGenFunction &CGF,
- const CXXCatchStmt *S) {
+static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
// We have to be very careful with the ordering of cleanups here:
// C++ [except.throw]p4:
// The destruction [of the exception temporary] occurs
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 049aeee..56a9107 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -583,6 +583,8 @@
return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E));
case Expr::ChooseExprClass:
return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
+ case Expr::OpaqueValueExprClass:
+ return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
case Expr::ImplicitCastExprClass:
case Expr::CStyleCastExprClass:
case Expr::CXXFunctionalCastExprClass:
@@ -1888,6 +1890,12 @@
return LV;
}
+LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
+ assert(e->isGLValue() || e->getType()->isRecordType());
+ llvm::Value *value = getOpaqueValueMapping(e);
+ return MakeAddrLValue(value, e->getType());
+}
+
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index ad62a3b..0b3a617 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -129,6 +129,8 @@
void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
+ void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+
void VisitVAArgExpr(VAArgExpr *E);
void EmitInitializationToLValue(Expr *E, LValue Address, QualType T);
@@ -242,6 +244,10 @@
// Visitor Methods
//===----------------------------------------------------------------------===//
+void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
+ EmitFinalDestCopy(e, CGF.EmitOpaqueValueLValue(e));
+}
+
void AggExprEmitter::VisitCastExpr(CastExpr *E) {
if (Dest.isIgnored() && E->getCastKind() != CK_Dynamic) {
Visit(E->getSubExpr());
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 21c298a..15901eb 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -129,6 +129,14 @@
}
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
+ ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ if (E->isGLValue()) return EmitLoadOfLValue(E);
+
+ // Otherwise, the mapping is... what, exactly? Probably a
+ // first-class aggregate, but it's really just not worthwhile.
+ CGF.ErrorUnsupported(E, "complex opaque r-value");
+ return ComplexPairTy();
+ }
// FIXME: CompoundLiteralExpr
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index e2e404f..99f3f0d 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -199,6 +199,13 @@
return llvm::ConstantInt::get(ConvertType(E->getType()),
E->getPackLength());
}
+
+ Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ if (E->isGLValue()) return EmitLoadOfLValue(E);
+
+ // Otherwise, assume the mapping is the scalar directly.
+ return CGF.getOpaqueValueMapping(E);
+ }
// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 5ea1565..c497150 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -838,6 +838,31 @@
CGF.EnsureInsertPoint();
}
};
+
+ /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
+ class OpaqueValueMapping {
+ CodeGenFunction &CGF;
+ const OpaqueValueExpr *OpaqueValue;
+
+ public:
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const OpaqueValueExpr *opaqueValue,
+ llvm::Value *value)
+ : CGF(CGF), OpaqueValue(opaqueValue) {
+ assert(opaqueValue && "no opaque value expression!");
+ CGF.OpaqueValues.insert(std::make_pair(opaqueValue, value));
+ }
+
+ void pop() {
+ assert(OpaqueValue && "mapping already popped!");
+ CGF.OpaqueValues.erase(OpaqueValue);
+ OpaqueValue = 0;
+ }
+
+ ~OpaqueValueMapping() {
+ if (OpaqueValue) CGF.OpaqueValues.erase(OpaqueValue);
+ }
+ };
/// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
/// number that holds the value.
@@ -883,6 +908,10 @@
/// statement range in current switch instruction.
llvm::BasicBlock *CaseRangeBlock;
+ /// OpaqueValues - Keeps track of the current set of opaque value
+ /// expressions.
+ llvm::DenseMap<const OpaqueValueExpr *, llvm::Value*> OpaqueValues;
+
// VLASizeMap - This keeps track of the associated size for each VLA type.
// We track this by the size expression rather than the type itself because
// in certain situations, like a const qualifier applied to an VLA typedef,
@@ -1278,6 +1307,16 @@
return Res;
}
+ /// getOpaqueValueMapping - Given an opaque value expression (which
+ /// must be mapped), return its mapping. Whether this is an address
+ /// or a value depends on the expression's type and value kind.
+ llvm::Value *getOpaqueValueMapping(const OpaqueValueExpr *e) {
+ llvm::DenseMap<const OpaqueValueExpr*,llvm::Value*>::iterator
+ it = OpaqueValues.find(e);
+ assert(it != OpaqueValues.end() && "no mapping for opaque value!");
+ return it->second;
+ }
+
/// getAccessedFieldNo - Given an encoded value and a result number, return
/// the input field number being accessed.
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
@@ -1609,6 +1648,7 @@
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
+ LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f929aa0..58f656c 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -6593,7 +6593,7 @@
ExDecl->setExceptionVariable(true);
if (!Invalid) {
- if (const RecordType *RecordTy = ExDeclType->getAs<RecordType>()) {
+ if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) {
// C++ [except.handle]p16:
// The object declared in an exception-declaration or, if the
// exception-declaration does not specify a name, a temporary (12.2) is
@@ -6603,18 +6603,32 @@
//
// We just pretend to initialize the object with itself, then make sure
// it can be destroyed later.
- InitializedEntity Entity = InitializedEntity::InitializeVariable(ExDecl);
- Expr *ExDeclRef = DeclRefExpr::Create(Context, 0, SourceRange(), ExDecl,
- Loc, ExDeclType, VK_LValue, 0);
- InitializationKind Kind = InitializationKind::CreateCopy(Loc,
- SourceLocation());
- InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1);
- ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, &ExDeclRef, 1));
- if (Result.isInvalid())
+ QualType initType = ExDeclType;
+
+ InitializedEntity entity =
+ InitializedEntity::InitializeVariable(ExDecl);
+ InitializationKind initKind =
+ InitializationKind::CreateCopy(Loc, SourceLocation());
+
+ Expr *opaqueValue =
+ new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary);
+ InitializationSequence sequence(*this, entity, initKind, &opaqueValue, 1);
+ ExprResult result = sequence.Perform(*this, entity, initKind,
+ MultiExprArg(&opaqueValue, 1));
+ if (result.isInvalid())
Invalid = true;
- else
- FinalizeVarWithDestructor(ExDecl, RecordTy);
+ else {
+ // If the constructor used was non-trivial, set this as the
+ // "initializer".
+ CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take());
+ if (!construct->getConstructor()->isTrivial()) {
+ Expr *init = MaybeCreateExprWithCleanups(construct);
+ ExDecl->setInit(init);
+ }
+
+ // And make sure it's destructable.
+ FinalizeVarWithDestructor(ExDecl, recordType);
+ }
}
}