]> granicus.if.org Git - clang/commitdiff
Avoid using NoThrow Exception Specifier in non-C++ Modes.
authorErich Keane <erich.keane@intel.com>
Wed, 5 Jun 2019 14:10:39 +0000 (14:10 +0000)
committerErich Keane <erich.keane@intel.com>
Wed, 5 Jun 2019 14:10:39 +0000 (14:10 +0000)
As reported in https://bugs.llvm.org/show_bug.cgi?id=42113, there are a
number of locations in Clang where it is assumed that exception
specifications are only valid in C++ mode. Since the original
justification for the NoThrow Exception Specifier Type was C++ related,
this patch just makes C mode use the attribute-based nothrow handling.

Additionally, I noticed that the handling of non-prototype functions
regressed the behavior of the nothrow attribute, in part because it is
was listed in the function type macro(which I did in the previous
patch).  In reality, it should only be doing so in a conditional nature,
so this patch removes it there and puts it directly in the switch to be
handled correctly.

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

include/clang/Sema/ParsedAttr.h
lib/Sema/SemaType.cpp
test/Sema/attr-nothrow.c [new file with mode: 0644]

index a42e4547a9679dcac3b6a83a9ba2a9a0980aeec2..d87d5da04accf112d0a687ef7cd79320462de65a 100644 (file)
@@ -440,7 +440,7 @@ public:
   }
 
   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
-  void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
+  void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; }
 
   /// True if the attribute is specified using '#pragma clang attribute'.
   bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; }
index d473fb6c8f3dcac03c190c2a6f146a1678cba11a..27f034bd1404ec607f6ae91529201c9de11bc069 100644 (file)
@@ -130,7 +130,6 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
   case ParsedAttr::AT_Regparm:                                                 \
   case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:                            \
   case ParsedAttr::AT_AnyX86NoCfCheck:                                         \
-  case ParsedAttr::AT_NoThrow:                                                 \
     CALLING_CONV_ATTRS_CASELIST
 
 // Microsoft-specific type qualifiers.
@@ -6947,23 +6946,17 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
   }
 
   if (attr.getKind() == ParsedAttr::AT_NoThrow) {
-    if (S.CheckAttrNoArgs(attr))
-      return true;
-
     // Delay if this is not a function type.
     if (!unwrapped.isFunctionType())
       return false;
 
-    // Otherwise we can process right away.
-    auto *Proto = unwrapped.get()->getAs<FunctionProtoType>();
-
-    // In the case where this is a FunctionNoProtoType instead of a
-    // FunctionProtoType, let the existing NoThrowAttr implementation do its
-    // thing.
-    if (!Proto)
-      return false;
+    if (S.CheckAttrNoArgs(attr)) {
+      attr.setInvalid();
+      return true;
+    }
 
-    attr.setUsedAsTypeAttr();
+    // Otherwise we can process right away.
+    auto *Proto = unwrapped.get()->castAs<FunctionProtoType>();
 
     // MSVC ignores nothrow if it is in conflict with an explicit exception
     // specification.
@@ -7668,6 +7661,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
         attr.setInvalid();
       break;
 
+    case ParsedAttr::AT_NoThrow:
+    // Exception Specifications aren't generally supported in C mode throughout
+    // clang, so revert to attribute-based handling for C.
+      if (!state.getSema().getLangOpts().CPlusPlus)
+        break;
+      LLVM_FALLTHROUGH;
     FUNCTION_TYPE_ATTRS_CASELIST:
       attr.setUsedAsTypeAttr();
 
diff --git a/test/Sema/attr-nothrow.c b/test/Sema/attr-nothrow.c
new file mode 100644 (file)
index 0000000..c444628
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -verify
+// RUN: %clang_cc1 %s -ast-dump | FileCheck %s
+// expected-no-diagnostics
+
+// PR42113: The following caused an assertion in mergeFunctionTypes
+// because it causes one side to have an exception specification, which
+// isn't typically supported in C.
+void PR42113a();
+void PR42113a(void) __attribute__((nothrow));
+// CHECK: FunctionDecl {{.*}} PR42113a
+// CHECK: FunctionDecl {{.*}} PR42113a
+// CHECK: NoThrowAttr
+void PR42113b() __attribute__((nothrow));
+// CHECK: FunctionDecl {{.*}} PR42113b
+// CHECK: NoThrowAttr
+ __attribute__((nothrow)) void PR42113c();
+// CHECK: FunctionDecl {{.*}} PR42113c
+// CHECK: NoThrowAttr