]> granicus.if.org Git - clang/commitdiff
Don't mark decls with mismatching exception specs invalid in MS mode (PR18683)
authorHans Wennborg <hans@hanshq.net>
Wed, 5 Feb 2014 02:37:58 +0000 (02:37 +0000)
committerHans Wennborg <hans@hanshq.net>
Wed, 5 Feb 2014 02:37:58 +0000 (02:37 +0000)
We accept these with a warning in MS mode, but we would previously mark them
invalid, causing us not to emit code for them.

Differential Revision: http://llvm-reviews.chandlerc.com/D2681

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200815 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExceptionSpec.cpp
test/CodeGenCXX/pr18661.cpp [new file with mode: 0644]

index c1b7e988c59cf9195c9ee1b3eadf1b29b52798bb..2eee07c0afdf1f4d20ef9932832004b472c1bee4 100644 (file)
@@ -155,9 +155,13 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
   bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
   bool MissingExceptionSpecification = false;
   bool MissingEmptyExceptionSpecification = false;
+
   unsigned DiagID = diag::err_mismatched_exception_spec;
-  if (getLangOpts().MicrosoftExt)
+  bool ReturnValueOnError = true;
+  if (getLangOpts().MicrosoftExt) {
     DiagID = diag::warn_mismatched_exception_spec; 
+    ReturnValueOnError = false;
+  }
 
   // Check the types as written: they must match before any exception
   // specification adjustment is applied.
@@ -182,9 +186,9 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
   }
 
   // The failure was something other than an missing exception
-  // specification; return an error.
+  // specification; return an error, except in MS mode where this is a warning.
   if (!MissingExceptionSpecification)
-    return true;
+    return ReturnValueOnError;
 
   const FunctionProtoType *NewProto =
     New->getType()->castAs<FunctionProtoType>();
@@ -302,10 +306,14 @@ bool Sema::CheckEquivalentExceptionSpec(
     const FunctionProtoType *New, SourceLocation NewLoc) {
   unsigned DiagID = diag::err_mismatched_exception_spec;
   if (getLangOpts().MicrosoftExt)
-    DiagID = diag::warn_mismatched_exception_spec; 
-  return CheckEquivalentExceptionSpec(PDiag(DiagID),
-                                      PDiag(diag::note_previous_declaration),
-                                      Old, OldLoc, New, NewLoc);
+    DiagID = diag::warn_mismatched_exception_spec;
+  bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID),
+      PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc);
+
+  // In Microsoft mode, mismatching exception specifications just cause a warning.
+  if (getLangOpts().MicrosoftExt)
+    return false;
+  return Result;
 }
 
 /// CheckEquivalentExceptionSpec - Check if the two types have compatible
diff --git a/test/CodeGenCXX/pr18661.cpp b/test/CodeGenCXX/pr18661.cpp
new file mode 100644 (file)
index 0000000..2358678
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fcxx-exceptions -fms-extensions -emit-llvm -o - | FileCheck %s
+
+extern "C" {
+  void f();
+
+  // In MS mode we don't validate the exception specification.
+  void f() throw() {
+  }
+}
+
+// PR18661: Clang would fail to emit function definition with mismatching
+// exception specification, even though it was just treated as a warning.
+
+// CHECK: define void @f()