diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -128,6 +128,11 @@ Attribute Changes in Clang -------------------------- +- Added support for ``__attribute__((guard(nocf)))`` and C++-style + ``[[clang::guard(nocf)]]``, which is equivalent to ``__declspec(guard(nocf))`` + when using the MSVC environment. This is to support enabling Windows Control + Flow Guard checks with the ability to disable them for specific functions when + using the MinGW environment. Windows Support --------------- 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 @@ -3494,7 +3494,7 @@ def CFGuard : InheritableAttr { // Currently only the __declspec(guard(nocf)) modifier is supported. In future // we might also want to support __declspec(guard(suppress)). - let Spellings = [Declspec<"guard">]; + let Spellings = [Declspec<"guard">, Clang<"guard">]; let Subjects = SubjectList<[Function]>; let Args = [EnumArgument<"Guard", "GuardArg", ["nocf"], ["nocf"]>]; let Documentation = [CFGuardDocs]; diff --git a/clang/test/CodeGen/guard_nocf.c b/clang/test/CodeGen/guard_nocf.c --- a/clang/test/CodeGen/guard_nocf.c +++ b/clang/test/CodeGen/guard_nocf.c @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -emit-llvm -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -O2 -o - %s | FileCheck %s + +// The x86_64-w64-windows-gnu version tests mingw target, which relies on +// __declspec(...) being defined as __attribute__((...)) by compiler built-in. void target_func(void); void (*func_ptr)(void) = &target_func; @@ -10,6 +14,15 @@ // CHECK-LABEL: nocf0 // CHECK: call{{.*}}[[NOCF:#[0-9]+]] +// Explicitly test using the GNU-style attribute without relying on the +// __declspec define for mingw. +// The "guard_nocf" attribute must be added. +__attribute__((guard(nocf))) void nocf0_gnu_style(void) { + (*func_ptr)(); +} +// CHECK-LABEL: nocf0_gnu_style +// CHECK: call{{.*}}[[NOCF:#[0-9]+]] + // The "guard_nocf" attribute must *not* be added. void cf0(void) { (*func_ptr)(); diff --git a/clang/test/CodeGenCXX/guard_nocf.cpp b/clang/test/CodeGenCXX/guard_nocf.cpp --- a/clang/test/CodeGenCXX/guard_nocf.cpp +++ b/clang/test/CodeGenCXX/guard_nocf.cpp @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -std=c++11 -emit-llvm -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -std=c++11 -emit-llvm -O2 -o - %s | FileCheck %s + +// The x86_64-w64-windows-gnu version tests mingw target, which relies on +// __declspec(...) being defined as __attribute__((...)) by compiler built-in. void target_func(); void (*func_ptr)() = &target_func; @@ -10,6 +14,23 @@ // CHECK-LABEL: nocf0 // CHECK: call{{.*}}[[NOCF:#[0-9]+]] +// Explicitly test using the GNU-style attribute without relying on the +// __declspec define for mingw. +// The "guard_nocf" attribute must be added. +__attribute__((guard(nocf))) void nocf0_gnu_style() { + (*func_ptr)(); +} +// CHECK-LABEL: nocf0_gnu_style +// CHECK: call{{.*}}[[NOCF:#[0-9]+]] + +// Test using the c++-style attribute. +// The "guard_nocf" attribute must be added. +[[clang::guard(nocf)]] void nocf0_cxx_style() { + (*func_ptr)(); +} +// CHECK-LABEL: nocf0_cxx_style +// CHECK: call{{.*}}[[NOCF:#[0-9]+]] + // The "guard_nocf" attribute must *not* be added. void cf0() { (*func_ptr)(); 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 @@ -26,6 +26,7 @@ // CHECK-NEXT: BuiltinAlias (SubjectMatchRule_function) // CHECK-NEXT: CFAuditedTransfer (SubjectMatchRule_function) // CHECK-NEXT: CFConsumed (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: CFGuard (SubjectMatchRule_function) // CHECK-NEXT: CFICanonicalJumpTable (SubjectMatchRule_function) // CHECK-NEXT: CFUnknownTransfer (SubjectMatchRule_function) // CHECK-NEXT: CPUDispatch (SubjectMatchRule_function) diff --git a/clang/test/Sema/attr-guard_nocf.c b/clang/test/Sema/attr-guard_nocf.c --- a/clang/test/Sema/attr-guard_nocf.c +++ b/clang/test/Sema/attr-guard_nocf.c @@ -1,10 +1,20 @@ // RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -verify -fsyntax-only %s // RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -verify -std=c++11 -fsyntax-only -x c++ %s +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -verify -fsyntax-only %s +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -verify -std=c++11 -fsyntax-only -x c++ %s + +// The x86_64-w64-windows-gnu version tests mingw target, which relies on +// __declspec(...) being defined as __attribute__((...)) by compiler built-in. // Function definition. __declspec(guard(nocf)) void testGuardNoCF(void) { // no warning } +// Function definition using GNU-style attribute without relying on the +// __declspec define for mingw. +__attribute__((guard(nocf))) void testGNUStyleGuardNoCF(void) { // no warning +} + // Can not be used on variable, parameter, or function pointer declarations. int __declspec(guard(nocf)) i; // expected-warning {{'guard' attribute only applies to functions}} void testGuardNoCFFuncParam(double __declspec(guard(nocf)) i) {} // expected-warning {{'guard' attribute only applies to functions}}