| // 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; | 
 |  | 
 | // The "guard_nocf" attribute must be added. | 
 | __declspec(guard(nocf)) void nocf0() { | 
 |   (*func_ptr)(); | 
 | } | 
 | // 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)(); | 
 | } | 
 | // CHECK-LABEL: cf0 | 
 | // CHECK: call{{.*}}[[CF:#[0-9]+]] | 
 |  | 
 | // If the modifier is present on either the function declaration or definition, | 
 | // the "guard_nocf" attribute must be added. | 
 | __declspec(guard(nocf)) void nocf1(); | 
 | void nocf1() { | 
 |   (*func_ptr)(); | 
 | } | 
 | // CHECK-LABEL: nocf1 | 
 | // CHECK: call{{.*}}[[NOCF:#[0-9]+]] | 
 |  | 
 | void nocf2(); | 
 | __declspec(guard(nocf)) void nocf2() { | 
 |   (*func_ptr)(); | 
 | } | 
 | // CHECK-LABEL: nocf2 | 
 | // CHECK: call{{.*}}[[NOCF:#[0-9]+]] | 
 |  | 
 | // When inlining a function, the "guard_nocf" attribute on indirect calls must | 
 | // be preserved. | 
 | void nocf3() { | 
 |   nocf0(); | 
 | } | 
 | // CHECK-LABEL: nocf3 | 
 | // CHECK: call{{.*}}[[NOCF:#[0-9]+]] | 
 |  | 
 | // When inlining into a function marked as __declspec(guard(nocf)), the | 
 | // "guard_nocf" attribute must *not* be added to the inlined calls. | 
 | __declspec(guard(nocf)) void cf1() { | 
 |   cf0(); | 
 | } | 
 | // CHECK-LABEL: cf1 | 
 | // CHECK: call{{.*}}[[CF:#[0-9]+]] | 
 |  | 
 | // When the __declspec(guard(nocf)) modifier is present on an override function, | 
 | // the "guard_nocf" attribute must be added. | 
 | struct Base { | 
 |   virtual void nocf4(); | 
 | }; | 
 |  | 
 | struct Derived : Base { | 
 |   __declspec(guard(nocf)) void nocf4() override { | 
 |     (*func_ptr)(); | 
 |   } | 
 | }; | 
 | Derived d; | 
 | // CHECK-LABEL: nocf4 | 
 | // CHECK: call{{.*}}[[NOCF:#[0-9]+]] | 
 |  | 
 | // When the modifier is not present on an override function, the "guard_nocf" | 
 | // attribute must *not* be added, even if the modifier is present on the virtual | 
 | // function. | 
 | struct Base1 { | 
 |   __declspec(guard(nocf)) virtual void cf2(); | 
 | }; | 
 |  | 
 | struct Derived1 : Base1 { | 
 |   void cf2() override { | 
 |     (*func_ptr)(); | 
 |   } | 
 | }; | 
 | Derived1 d1; | 
 | // CHECK-LABEL: cf2 | 
 | // CHECK: call{{.*}}[[CF:#[0-9]+]] | 
 |  | 
 | // CHECK: attributes [[NOCF]] = { {{.*}}"guard_nocf"{{.*}} } | 
 | // CHECK-NOT: attributes [[CF]] = { {{.*}}"guard_nocf"{{.*}} } |