r232188 - MS ABI: Implement __GetExceptionInfo for std::make_exception_ptr
David Majnemer
david.majnemer at gmail.com
Fri Mar 13 11:26:17 PDT 2015
Author: majnemer
Date: Fri Mar 13 13:26:17 2015
New Revision: 232188
URL: http://llvm.org/viewvc/llvm-project?rev=232188&view=rev
Log:
MS ABI: Implement __GetExceptionInfo for std::make_exception_ptr
std::make_exception_ptr calls std::__GetExceptionInfo in order to figure
out how to properly copy the exception object.
Differential Revision: http://reviews.llvm.org/D8280
Modified:
cfe/trunk/include/clang/Basic/Builtins.def
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp
Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Fri Mar 13 13:26:17 2015
@@ -701,6 +701,7 @@ LANGBUILTIN(__exception_info, "v*", "n"
LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 13 13:26:17 2015
@@ -4362,8 +4362,7 @@ public:
ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr);
ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
bool IsThrownVarInScope);
- ExprResult CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
- bool IsThrownVarInScope);
+ bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E);
/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
/// Can be interpreted either as function-style casting ("int(x)")
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Mar 13 13:26:17 2015
@@ -7840,6 +7840,9 @@ QualType ASTContext::GetBuiltinType(unsi
ArgTypes.push_back(Ty);
}
+ if (Id == Builtin::BI__GetExceptionInfo)
+ return QualType();
+
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Mar 13 13:26:17 2015
@@ -2634,7 +2634,14 @@ unsigned FunctionDecl::getBuiltinID() co
// extern "C".
// FIXME: A recognised library function may not be directly in an extern "C"
// declaration, for instance "extern "C" { namespace std { decl } }".
- if (!LinkageDecl || LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
+ if (!LinkageDecl) {
+ if (BuiltinID == Builtin::BI__GetExceptionInfo &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ isInStdNamespace())
+ return Builtin::BI__GetExceptionInfo;
+ return 0;
+ }
+ if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
return 0;
}
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Mar 13 13:26:17 2015
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
@@ -1720,6 +1721,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(
return RValue::get(CS.getInstruction());
}
}
+
+ case Builtin::BI__GetExceptionInfo: {
+ if (llvm::GlobalVariable *GV =
+ CGM.getCXXABI().getThrowInfo(FD->getParamDecl(0)->getType()))
+ return RValue::get(llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy));
+ break;
+ }
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Fri Mar 13 13:26:17 2015
@@ -216,6 +216,7 @@ public:
const CXXDestructorDecl *Dtor) = 0;
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) = 0;
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
+ virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Mar 13 13:26:17 2015
@@ -644,7 +644,7 @@ public:
llvm::GlobalVariable *getCatchableTypeArray(QualType T);
- llvm::GlobalVariable *getThrowInfo(QualType T);
+ llvm::GlobalVariable *getThrowInfo(QualType T) override;
private:
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Mar 13 13:26:17 2015
@@ -503,6 +503,19 @@ Sema::CheckBuiltinFunctionCall(FunctionD
break;
}
+ case Builtin::BI__GetExceptionInfo:
+ if (checkArgCount(*this, TheCall, 1))
+ return ExprError();
+
+ if (CheckCXXThrowOperand(
+ TheCall->getLocStart(),
+ Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()),
+ TheCall))
+ return ExprError();
+
+ TheCall->setType(Context.VoidPtrTy);
+ break;
+
}
// Since the target specific builtins for each arch overlap, only check those
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Mar 13 13:26:17 2015
@@ -647,12 +647,39 @@ ExprResult Sema::BuildCXXThrow(SourceLoc
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
if (Ex && !Ex->isTypeDependent()) {
- ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope);
- if (ExRes.isInvalid())
+ QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
+ if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
return ExprError();
- Ex = ExRes.get();
+
+ // Initialize the exception result. This implicitly weeds out
+ // abstract types or types with inaccessible copy constructors.
+
+ // C++0x [class.copymove]p31:
+ // When certain criteria are met, an implementation is allowed to omit the
+ // copy/move construction of a class object [...]
+ //
+ // - in a throw-expression, when the operand is the name of a
+ // non-volatile automatic object (other than a function or
+ // catch-clause
+ // parameter) whose scope does not extend beyond the end of the
+ // innermost enclosing try-block (if there is one), the copy/move
+ // operation from the operand to the exception object (15.1) can be
+ // omitted by constructing the automatic object directly into the
+ // exception object
+ const VarDecl *NRVOVariable = nullptr;
+ if (IsThrownVarInScope)
+ NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false);
+
+ InitializedEntity Entity = InitializedEntity::InitializeException(
+ OpLoc, ExceptionObjectTy,
+ /*NRVO=*/NRVOVariable != nullptr);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope);
+ if (Res.isInvalid())
+ return ExprError();
+ Ex = Res.get();
}
-
+
return new (Context)
CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope);
}
@@ -707,9 +734,8 @@ static void getUnambiguousPublicSubobjec
}
/// CheckCXXThrowOperand - Validate the operand of a throw.
-ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
- bool IsThrownVarInScope) {
- QualType ExceptionObjectTy = Context.getExceptionObjectType(E->getType());
+bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
+ QualType ExceptionObjectTy, Expr *E) {
// If the type of the exception would be an incomplete type or a pointer
// to an incomplete type other than (cv) void the program is ill-formed.
QualType Ty = ExceptionObjectTy;
@@ -720,48 +746,20 @@ ExprResult Sema::CheckCXXThrowOperand(So
}
if (!isPointer || !Ty->isVoidType()) {
if (RequireCompleteType(ThrowLoc, Ty,
- isPointer? diag::err_throw_incomplete_ptr
- : diag::err_throw_incomplete,
+ isPointer ? diag::err_throw_incomplete_ptr
+ : diag::err_throw_incomplete,
E->getSourceRange()))
- return ExprError();
+ return true;
if (RequireNonAbstractType(ThrowLoc, ExceptionObjectTy,
diag::err_throw_abstract_type, E))
- return ExprError();
+ return true;
}
- // Initialize the exception result. This implicitly weeds out
- // abstract types or types with inaccessible copy constructors.
-
- // C++0x [class.copymove]p31:
- // When certain criteria are met, an implementation is allowed to omit the
- // copy/move construction of a class object [...]
- //
- // - in a throw-expression, when the operand is the name of a
- // non-volatile automatic object (other than a function or catch-clause
- // parameter) whose scope does not extend beyond the end of the
- // innermost enclosing try-block (if there is one), the copy/move
- // operation from the operand to the exception object (15.1) can be
- // omitted by constructing the automatic object directly into the
- // exception object
- const VarDecl *NRVOVariable = nullptr;
- if (IsThrownVarInScope)
- NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
-
- InitializedEntity Entity =
- InitializedEntity::InitializeException(ThrowLoc, ExceptionObjectTy,
- /*NRVO=*/NRVOVariable != nullptr);
- ExprResult Res = PerformMoveOrCopyInitialization(
- Entity, NRVOVariable, QualType(), E, IsThrownVarInScope);
- if (Res.isInvalid())
- return ExprError();
- E = Res.get();
-
// If the exception has class type, we need additional handling.
- const RecordType *RecordTy = Ty->getAs<RecordType>();
- if (!RecordTy)
- return E;
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ if (!RD)
+ return false;
// If we are throwing a polymorphic class type or pointer thereof,
// exception handling will make use of the vtable.
@@ -769,7 +767,7 @@ ExprResult Sema::CheckCXXThrowOperand(So
// If a pointer is thrown, the referenced object will not be destroyed.
if (isPointer)
- return E;
+ return false;
// If the class has a destructor, we must be able to call it.
if (!RD->hasIrrelevantDestructor()) {
@@ -778,7 +776,7 @@ ExprResult Sema::CheckCXXThrowOperand(So
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_exception) << Ty);
if (DiagnoseUseOfDecl(Destructor, E->getExprLoc()))
- return ExprError();
+ return true;
}
}
@@ -831,7 +829,7 @@ ExprResult Sema::CheckCXXThrowOperand(So
}
}
- return E;
+ return false;
}
QualType Sema::getCurrentThisType() {
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp?rev=232188&r1=232187&r2=232188&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp Fri Mar 13 13:26:17 2015
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s
// CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE at ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE at ABU0@@Z" to i8*) }, section ".xdata", comdat
@@ -89,6 +89,18 @@ void j(TemplateWithDefault &twd) {
throw twd;
}
+
void h() {
throw nullptr;
}
+
+namespace std {
+template <typename T>
+void *__GetExceptionInfo(T);
+}
+
+void *GetExceptionInfo_test0() {
+// CHECK-LABEL: @"\01?GetExceptionInfo_test0@@YAPAXXZ"
+// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1H to i8*)
+ return std::__GetExceptionInfo(0);
+}
More information about the cfe-commits
mailing list