diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2086,6 +2086,13 @@ let Documentation = [NoThrowDocs]; } +def NoUwtable : InheritableAttr { + let Spellings = [Clang<"nouwtable">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [NoUwtableDocs]; + let SimpleHandler = 1; +} + def NvWeak : IgnoredAttr { // No Declspec spelling of this attribute; the CUDA headers use // __attribute__((nv_weak)) unconditionally. Does not receive an [[]] diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4537,6 +4537,16 @@ }]; } +def NoUwtableDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``nouwtable`` attribute which skips emitting +the unwind table entry for the specified function. This attribute is useful for +selectively suppressing the unwind table entry on some functions when building +with the ``-funwind-tables`` compiler option. + }]; +} + def InternalLinkageDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1942,7 +1942,7 @@ llvm::Function *F) { llvm::AttrBuilder B(F->getContext()); - if (CodeGenOpts.UnwindTables) + if ((!D || !D->hasAttr()) && CodeGenOpts.UnwindTables) B.addUWTableAttr(llvm::UWTableKind(CodeGenOpts.UnwindTables)); if (CodeGenOpts.StackClashProtector) diff --git a/clang/test/CodeGen/attr-nouwtable.c b/clang/test/CodeGen/attr-nouwtable.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/attr-nouwtable.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -funwind-tables=2 -S -emit-llvm %s -o - | FileCheck %s + +void t1(void) {} + +void t2(void) __attribute__((nouwtable)); +void t2(void) {} + +// CHECK: @t1{{.*}}[[ATTR1:#[0-9]+]] +// CHECK: @t2{{.*}}[[ATTR2:#[0-9]+]] + +// CHECK: attributes [[ATTR1]] = {{{.*}}uwtable{{.*}}} +// CHECK: attributes [[ATTR2]] = { +// CHECK-NOT: uwtable +// CHECK: } diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -114,6 +114,7 @@ // CHECK-NEXT: NoStackProtector (SubjectMatchRule_function) // CHECK-NEXT: NoThreadSafetyAnalysis (SubjectMatchRule_function) // CHECK-NEXT: NoThrow (SubjectMatchRule_hasType_functionType) +// CHECK-NEXT: NoUwtable (SubjectMatchRule_function) // CHECK-NEXT: NotTailCalled (SubjectMatchRule_function) // CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter) diff --git a/clang/test/Sema/attr-nouwtable.c b/clang/test/Sema/attr-nouwtable.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/attr-nouwtable.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void *t1() __attribute__((nouwtable(1))); // expected-error {{'nouwtable' attribute takes no arguments}} + +typedef void (*F)(void); +__attribute__((nouwtable)) F f; // expected-warning {{'nouwtable' attribute only applies to functions}}