diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4f3ba0d694b6..2de09873f6fb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3151,9 +3151,12 @@ def err_qualified_objc_catch_parm : Error< "@catch parameter declarator cannot be qualified">; def err_objc_pointer_cxx_catch_gnu : Error< "can't catch Objective C exceptions in C++ in the GNU runtime">; -def err_objc_pointer_cxx_catch_fragile : Error< - "can't catch Objective C exceptions in C++ in the non-unified " +def warn_objc_pointer_cxx_catch_fragile : Warning< + "catching Objective C id's exceptions in C++ in the non-unified " "exception model">; +def err_objc_pointer_cxx_catch_fragile : Error< +"can't catch Objective C exceptions in C++ in the non-unified " +"exception model">; def err_objc_object_catch : Error< "can't catch an Objective C object by value">; def err_incomplete_type_objc_at_encode : Error< diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 1a4a5f988a58..79a730eb7ea5 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -521,7 +521,7 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { llvm::Value *TypeInfo = 0; if (CaughtType->isObjCObjectPointerType()) - TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType); + TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType, this); else TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true); CatchScope->setHandler(I, TypeInfo, Handler); diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 6a711bff5595..ed194d9c9180 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -438,7 +438,7 @@ public: bool lval = false); virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method); - virtual llvm::Constant *GetEHType(QualType T); + virtual llvm::Constant *GetEHType(QualType T, const CodeGenFunction *CGF=0); virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD); @@ -832,7 +832,7 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl return GetSelector(Builder, Method->getSelector(), SelTypes, false); } -llvm::Constant *CGObjCGNU::GetEHType(QualType T) { +llvm::Constant *CGObjCGNU::GetEHType(QualType T, const CodeGenFunction *CGF) { if (!CGM.getLangOptions().CPlusPlus) { if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index f98770071ecd..52dd520aa861 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -200,7 +200,7 @@ public: const llvm::Type *CacheTy; /// CachePtrTy - LLVM type for struct objc_cache *. const llvm::Type *CachePtrTy; - + llvm::Constant *getGetPropertyFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); @@ -452,7 +452,7 @@ public: /// ExceptionDataTy - LLVM type for struct _objc_exception_data. const llvm::Type *ExceptionDataTy; - + /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. llvm::Constant *getExceptionTryEnterFn() { const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; @@ -633,7 +633,7 @@ public: const llvm::StructType *EHTypeTy; const llvm::Type *EHTypePtrTy; - + ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); ~ObjCNonFragileABITypesHelper(){} }; @@ -1010,7 +1010,7 @@ public: virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method); - virtual llvm::Constant *GetEHType(QualType T); + virtual llvm::Constant *GetEHType(QualType T, const CodeGenFunction *CGF=0); virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); @@ -1271,7 +1271,7 @@ public: virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD); - virtual llvm::Constant *GetEHType(QualType T); + virtual llvm::Constant *GetEHType(QualType T, const CodeGenFunction *CGF=0); virtual llvm::Constant *GetPropertyGetFunction() { return ObjCTypes.getGetPropertyFn(); @@ -1414,7 +1414,12 @@ llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl return EmitSelector(Builder, Method->getSelector()); } -llvm::Constant *CGObjCMac::GetEHType(QualType T) { +llvm::Constant *CGObjCMac::GetEHType(QualType T, const CodeGenFunction *CGF) { + if (T->isObjCIdType() || + T->isObjCQualifiedIdType()) { + return CGM.GetAddrOfRTTIDescriptor( + CGF->getContext().ObjCIdRedefinitionType, /*ForEH=*/true); + } llvm_unreachable("asking for catch type for ObjC type in fragile runtime"); return 0; } @@ -4176,6 +4181,7 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) CacheTy = llvm::OpaqueType::get(VMContext); CGM.getModule().addTypeName("struct._objc_cache", CacheTy); CachePtrTy = llvm::PointerType::getUnqual(CacheTy); + } ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) @@ -4580,7 +4586,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); - + // struct objc_typeinfo { // const void** vtable; // objc_ehtype_vtable + 2 @@ -6015,7 +6021,7 @@ CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } llvm::Constant * -CGObjCNonFragileABIMac::GetEHType(QualType T) { +CGObjCNonFragileABIMac::GetEHType(QualType T, const CodeGenFunction *CGF) { // There's a particular fixed type info for 'id'. if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 7accc70c9623..510143f76781 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -128,7 +128,8 @@ public: /// This is used externally to implement catching ObjC types in C++. /// Runtimes which don't support this should add the appropriate /// error to Sema. - virtual llvm::Constant *GetEHType(QualType T) = 0; + virtual llvm::Constant *GetEHType(QualType T, + const CodeGenFunction *CGF=0) = 0; /// Generate a constant string object. virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0a7ca4d2f9c2..93f97f66eec3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8046,8 +8046,12 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Invalid = true; } else if (T->isObjCObjectPointerType()) { if (!getLangOptions().ObjCNonFragileABI) { - Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile); - Invalid = true; + if (T->isObjCIdType() || T->isObjCQualifiedIdType()) + Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile); + else { + Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile); + Invalid = true; + } } } } diff --git a/clang/test/CodeGenObjCXX/catch-id-type.mm b/clang/test/CodeGenObjCXX/catch-id-type.mm new file mode 100644 index 000000000000..25d36550e8e2 --- /dev/null +++ b/clang/test/CodeGenObjCXX/catch-id-type.mm @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple i386-apple-macosx10.6.6 -emit-llvm -fobjc-exceptions -fcxx-exceptions -fexceptions -o - %s | FileCheck %s +// rdar://8940528 + +@interface ns_array ++ (id) array; +@end + +@implementation ns_array ++ (id) array { return 0; } +@end + +id Groups(); + +id FUNC() { + id groups; + try + { + groups = Groups(); // throws on errors. + } + catch( id error ) + { + // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gxx_personality_v0 {{.*}} @_ZTIP11objc_object + error = error; + groups = [ns_array array]; + } + return groups; + +} + +int main() { + FUNC(); + return 0; +}