]> granicus.if.org Git - clang/commitdiff
Code generation for noexcept.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 14 Mar 2011 20:33:20 +0000 (20:33 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 14 Mar 2011 20:33:20 +0000 (20:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127617 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGException.cpp
test/CXX/except/except.spec/p9-dynamic.cpp [new file with mode: 0644]
test/CXX/except/except.spec/p9-noexcept.cpp [new file with mode: 0644]

index f05bc700b4ffe1b2d7750e70bd43aa8a4949938f..7fdfe700421e718424af2c96db239c9be960ec6a 100644 (file)
@@ -449,19 +449,23 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
   if (Proto == 0)
     return;
 
-  // FIXME: What about noexcept?
-  if (!Proto->hasDynamicExceptionSpec())
-    return;
-
-  unsigned NumExceptions = Proto->getNumExceptions();
-  EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);
-
-  for (unsigned I = 0; I != NumExceptions; ++I) {
-    QualType Ty = Proto->getExceptionType(I);
-    QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType();
-    llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType,
-                                                      /*ForEH=*/true);
-    Filter->setFilter(I, EHType);
+  ExceptionSpecificationType EST = Proto->getExceptionSpecType();
+  if (isNoexceptExceptionSpec(EST)) {
+    if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) {
+      // noexcept functions are simple terminate scopes.
+      EHStack.pushTerminate();
+    }
+  } else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
+    unsigned NumExceptions = Proto->getNumExceptions();
+    EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);
+
+    for (unsigned I = 0; I != NumExceptions; ++I) {
+      QualType Ty = Proto->getExceptionType(I);
+      QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType();
+      llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType,
+                                                        /*ForEH=*/true);
+      Filter->setFilter(I, EHType);
+    }
   }
 }
 
@@ -476,10 +480,14 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
   if (Proto == 0)
     return;
 
-  if (!Proto->hasDynamicExceptionSpec())
-    return;
-
-  EHStack.popFilter();
+  ExceptionSpecificationType EST = Proto->getExceptionSpecType();
+  if (isNoexceptExceptionSpec(EST)) {
+    if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) {
+      EHStack.popTerminate();
+    }
+  } else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
+    EHStack.popFilter();
+  }
 }
 
 void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
diff --git a/test/CXX/except/except.spec/p9-dynamic.cpp b/test/CXX/except/except.spec/p9-dynamic.cpp
new file mode 100644 (file)
index 0000000..3e7f931
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s
+
+void external();
+
+void target() throw(int)
+{
+  // CHECK: invoke void @_Z8externalv()
+  external();
+}
+// CHECK: %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 2, i8* bitcast (i8** @_ZTIi to i8*), i8* null) nounwind
+// CHECK: ehspec.unexpected:
+// CHECK: call void @__cxa_call_unexpected(i8* %1) noreturn
diff --git a/test/CXX/except/except.spec/p9-noexcept.cpp b/test/CXX/except/except.spec/p9-noexcept.cpp
new file mode 100644 (file)
index 0000000..71a8dee
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -std=c++0x -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s
+
+void external();
+
+void target() noexcept
+{
+  // CHECK: invoke void @_Z8externalv()
+  external();
+}
+// CHECK: terminate.lpad:
+// CHECK:  %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) nounwind
+// CHECK-NEXT: call void @_ZSt9terminatev() noreturn nounwind
+// CHECK-NEXT: unreachable
+
+void reverse() noexcept(false)
+{
+  // CHECK: call void @_Z8externalv()
+  external();
+}