mirror of https://github.com/microsoft/clang.git
Unify clang/llvm attributes for asan/tsan/msan (Clang part)
These are two related changes (one in llvm, one in clang). LLVM: - rename address_safety => sanitize_address (the enum value is the same, so we preserve binary compatibility with old bitcode) - rename thread_safety => sanitize_thread - rename no_uninitialized_checks -> sanitize_memory CLANG: - add __attribute__((no_sanitize_address)) as a synonym for __attribute__((no_address_safety_analysis)) - add __attribute__((no_sanitize_thread)) - add __attribute__((no_sanitize_memory)) for S in address thread memory If -fsanitize=S is present and __attribute__((no_sanitize_S)) is not set llvm attribute sanitize_S git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176076 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d8be0abf30
commit
85aee96c62
|
@ -105,12 +105,13 @@ this purpose.
|
|||
# endif
|
||||
#endif
|
||||
|
||||
``__attribute__((no_address_safety_analysis))``
|
||||
``__attribute__((no_sanitize_address))``
|
||||
-----------------------------------------------
|
||||
|
||||
Some code should not be instrumented by AddressSanitizer. One may use the
|
||||
function attribute
|
||||
:ref:`no_address_safety_analysis <langext-address_sanitizer>`
|
||||
:ref:`no_sanitize_address <langext-address_sanitizer>`
|
||||
(or a deprecated synonym `no_address_safety_analysis`)
|
||||
to disable instrumentation of a particular function. This attribute may not be
|
||||
supported by other compilers, so we suggest to use it together with
|
||||
``__has_feature(address_sanitizer)``. Note: currently, this attribute will be
|
||||
|
|
|
@ -1616,10 +1616,38 @@ AddressSanitizer
|
|||
Use ``__has_feature(address_sanitizer)`` to check if the code is being built
|
||||
with :doc:`AddressSanitizer`.
|
||||
|
||||
Use ``__attribute__((no_address_safety_analysis))`` on a function declaration
|
||||
Use ``__attribute__((no_sanitize_address))``
|
||||
on a function declaration
|
||||
to specify that address safety instrumentation (e.g. AddressSanitizer) should
|
||||
not be applied to that function.
|
||||
|
||||
.. _langext-thread_sanitizer:
|
||||
|
||||
ThreadSanitizer
|
||||
----------------
|
||||
|
||||
Use ``__has_feature(thread_sanitizer)`` to check if the code is being built
|
||||
with :doc:`ThreadSanitizer`.
|
||||
|
||||
Use ``__attribute__((no_sanitize_thread))`` on a function declaration
|
||||
to specify that checks for data races on plain (non-atomic) memory accesses
|
||||
should not be inserted by ThreadSanitizer.
|
||||
The function may still be instrumented by the tool
|
||||
to avoid false positives in other places.
|
||||
|
||||
.. _langext-memory_sanitizer:
|
||||
|
||||
MemorySanitizer
|
||||
----------------
|
||||
Use ``__has_feature(memory_sanitizer)`` to check if the code is being built
|
||||
with :doc:`MemorySanitizer`.
|
||||
|
||||
Use ``__attribute__((no_sanitize_memory))`` on a function declaration
|
||||
to specify that checks for uninitialized memory should not be inserted
|
||||
(e.g. by MemorySanitizer). The function may still be instrumented by the tool
|
||||
to avoid false positives in other places.
|
||||
|
||||
|
||||
Thread-Safety Annotation Checking
|
||||
=================================
|
||||
|
||||
|
|
|
@ -80,6 +80,19 @@ whether MemorySanitizer is enabled. :ref:`\_\_has\_feature
|
|||
# endif
|
||||
#endif
|
||||
|
||||
``__attribute__((no_sanitize_memory))``
|
||||
-----------------------------------------------
|
||||
|
||||
Some code should not be checked by MemorySanitizer.
|
||||
One may use the function attribute
|
||||
:ref:`no_sanitize_memory <langext-memory_sanitizer>`
|
||||
to disable uninitialized checks in a particular function.
|
||||
MemorySanitizer may still instrument such functions to avoid false positives.
|
||||
This attribute may not be
|
||||
supported by other compilers, so we suggest to use it together with
|
||||
``__has_feature(memory_sanitizer)``. Note: currently, this attribute will be
|
||||
lost if the function is inlined.
|
||||
|
||||
Origin Tracking
|
||||
===============
|
||||
|
||||
|
|
|
@ -78,10 +78,25 @@ this purpose.
|
|||
|
||||
.. code-block:: c
|
||||
|
||||
#if defined(__has_feature) && __has_feature(thread_sanitizer)
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(thread_sanitizer)
|
||||
// code that builds only under ThreadSanitizer
|
||||
# endif
|
||||
#endif
|
||||
|
||||
``__attribute__((no_sanitize_thread))``
|
||||
-----------------------------------------------
|
||||
|
||||
Some code should not be instrumented by ThreadSanitizer.
|
||||
One may use the function attribute
|
||||
:ref:`no_sanitize_thread <langext-thread_sanitizer>`
|
||||
to disable instrumentation of plain (non-atomic) loads/stores in a particular function.
|
||||
ThreadSanitizer may still instrument such functions to avoid false positives.
|
||||
This attribute may not be
|
||||
supported by other compilers, so we suggest to use it together with
|
||||
``__has_feature(thread_sanitizer)``. Note: currently, this attribute will be
|
||||
lost if the function is inlined.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
|
|
|
@ -767,9 +767,20 @@ def X86ForceAlignArgPointer : InheritableAttr {
|
|||
let Spellings = [];
|
||||
}
|
||||
|
||||
// AddressSafety attribute (e.g. for AddressSanitizer)
|
||||
def NoAddressSafetyAnalysis : InheritableAttr {
|
||||
let Spellings = [GNU<"no_address_safety_analysis">];
|
||||
// Attribute to disable AddressSanitizer (or equivalent) checks.
|
||||
def NoSanitizeAddress : InheritableAttr {
|
||||
let Spellings = [GNU<"no_address_safety_analysis">,
|
||||
GNU<"no_sanitize_address">];
|
||||
}
|
||||
|
||||
// Attribute to disable ThreadSanitizer checks.
|
||||
def NoSanitizeThread : InheritableAttr {
|
||||
let Spellings = [GNU<"no_sanitize_thread">];
|
||||
}
|
||||
|
||||
// Attribute to disable MemorySanitizer checks.
|
||||
def NoSanitizeMemory : InheritableAttr {
|
||||
let Spellings = [GNU<"no_sanitize_memory">];
|
||||
}
|
||||
|
||||
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
|
||||
|
|
|
@ -233,7 +233,11 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
|
|||
Fn->setDoesNotThrow();
|
||||
|
||||
if (CGM.getSanOpts().Address)
|
||||
Fn->addFnAttr(llvm::Attribute::AddressSafety);
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
|
||||
if (CGM.getSanOpts().Thread)
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
|
||||
if (CGM.getSanOpts().Memory)
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
|
||||
|
||||
return Fn;
|
||||
}
|
||||
|
|
|
@ -617,12 +617,16 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
|||
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
|
||||
F->addFnAttr(llvm::Attribute::StackProtectReq);
|
||||
|
||||
if (SanOpts.Address) {
|
||||
// When AddressSanitizer is enabled, set AddressSafety attribute
|
||||
// unless __attribute__((no_address_safety_analysis)) is used.
|
||||
if (!D->hasAttr<NoAddressSafetyAnalysisAttr>())
|
||||
F->addFnAttr(llvm::Attribute::AddressSafety);
|
||||
}
|
||||
// When AddressSanitizer is enabled, set SanitizeAddress attribute
|
||||
// unless __attribute__((no_sanitize_address)) is used.
|
||||
if (SanOpts.Address && !D->hasAttr<NoSanitizeAddressAttr>())
|
||||
F->addFnAttr(llvm::Attribute::SanitizeAddress);
|
||||
// Same for ThreadSanitizer and __attribute__((no_sanitize_thread))
|
||||
if (SanOpts.Thread && !D->hasAttr<NoSanitizeThreadAttr>())
|
||||
F->addFnAttr(llvm::Attribute::SanitizeThread);
|
||||
// Same for MemorySanitizer and __attribute__((no_sanitize_memory))
|
||||
if (SanOpts.Memory && !D->hasAttr<NoSanitizeMemoryAttr>())
|
||||
F->addFnAttr(llvm::Attribute::SanitizeMemory);
|
||||
|
||||
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
|
||||
if (alignment)
|
||||
|
|
|
@ -610,8 +610,8 @@ static void handleScopedLockableAttr(Sema &S, Decl *D,
|
|||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
assert(!Attr.isInvalid());
|
||||
|
||||
if (!checkAttributeNumArgs(S, Attr, 0))
|
||||
|
@ -627,7 +627,7 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
|
|||
S.Context));
|
||||
}
|
||||
|
||||
static void handleNoAddressSafetyAttr(Sema &S, Decl *D,
|
||||
static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
assert(!Attr.isInvalid());
|
||||
|
||||
|
@ -635,14 +635,48 @@ static void handleNoAddressSafetyAttr(Sema &S, Decl *D,
|
|||
return;
|
||||
|
||||
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
|
||||
<< Attr.getName() << ExpectedFunctionOrMethod;
|
||||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context)
|
||||
NoAddressSafetyAnalysisAttr(Attr.getRange(), S.Context,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
NoSanitizeAddressAttr(Attr.getRange(), S.Context,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleNoSanitizeMemory(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
assert(!Attr.isInvalid());
|
||||
|
||||
if (!checkAttributeNumArgs(S, Attr, 0))
|
||||
return;
|
||||
|
||||
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
|
||||
<< Attr.getName() << ExpectedFunctionOrMethod;
|
||||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(),
|
||||
S.Context));
|
||||
}
|
||||
|
||||
static void handleNoSanitizeThread(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
assert(!Attr.isInvalid());
|
||||
|
||||
if (!checkAttributeNumArgs(S, Attr, 0))
|
||||
return;
|
||||
|
||||
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
|
||||
<< Attr.getName() << ExpectedFunctionOrMethod;
|
||||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(),
|
||||
S.Context));
|
||||
}
|
||||
|
||||
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
|
||||
|
@ -4817,11 +4851,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
|
|||
case AttributeList::AT_ScopedLockable:
|
||||
handleScopedLockableAttr(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_NoAddressSafetyAnalysis:
|
||||
handleNoAddressSafetyAttr(S, D, Attr);
|
||||
case AttributeList::AT_NoSanitizeAddress:
|
||||
handleNoSanitizeAddressAttr(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_NoThreadSafetyAnalysis:
|
||||
handleNoThreadSafetyAttr(S, D, Attr);
|
||||
handleNoThreadSafetyAnalysis(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_NoSanitizeThread:
|
||||
handleNoSanitizeThread(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_NoSanitizeMemory:
|
||||
handleNoSanitizeMemory(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_Lockable:
|
||||
handleLockableAttr(S, D, Attr);
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
// FIXME: %t is like "src:x:\path\to\clang\test\CodeGen\address-safety-attr.cpp"
|
||||
// REQUIRES: shell
|
||||
|
||||
// The address_safety attribute should be attached to functions
|
||||
// when AddressSanitizer is enabled, unless no_address_safety_analysis attribute
|
||||
// The sanitize_address attribute should be attached to functions
|
||||
// when AddressSanitizer is enabled, unless no_sanitize_address attribute
|
||||
// is present.
|
||||
|
||||
// WITHOUT: NoAddressSafety1{{.*}}) #[[NOATTR:[0-9]+]]
|
||||
// BL: NoAddressSafety1{{.*}}) #[[NOATTR:[0-9]+]]
|
||||
// ASAN: NoAddressSafety1{{.*}}) #[[NOATTR:[0-9]+]]
|
||||
__attribute__((no_address_safety_analysis))
|
||||
__attribute__((no_sanitize_address))
|
||||
int NoAddressSafety1(int *a) { return *a; }
|
||||
|
||||
// WITHOUT: NoAddressSafety2{{.*}}) #[[NOATTR]]
|
||||
// BL: NoAddressSafety2{{.*}}) #[[NOATTR]]
|
||||
// ASAN: NoAddressSafety2{{.*}}) #[[NOATTR]]
|
||||
__attribute__((no_address_safety_analysis))
|
||||
__attribute__((no_sanitize_address))
|
||||
int NoAddressSafety2(int *a);
|
||||
int NoAddressSafety2(int *a) { return *a; }
|
||||
|
||||
|
@ -38,13 +38,13 @@ int TemplateAddressSafetyOk() { return i; }
|
|||
// BL: TemplateNoAddressSafety{{.*}}) #[[NOATTR]]
|
||||
// ASAN: TemplateNoAddressSafety{{.*}}) #[[NOATTR]]
|
||||
template<int i>
|
||||
__attribute__((no_address_safety_analysis))
|
||||
__attribute__((no_sanitize_address))
|
||||
int TemplateNoAddressSafety() { return i; }
|
||||
|
||||
int force_instance = TemplateAddressSafetyOk<42>()
|
||||
+ TemplateNoAddressSafety<42>();
|
||||
|
||||
// Check that __cxx_global_var_init* get the address_safety attribute.
|
||||
// Check that __cxx_global_var_init* get the sanitize_address attribute.
|
||||
int global1 = 0;
|
||||
int global2 = *(int*)((char*)&global1+1);
|
||||
// WITHOUT: @__cxx_global_var_init{{.*}}#[[GVI:[0-9]+]]
|
||||
|
@ -57,5 +57,5 @@ int global2 = *(int*)((char*)&global1+1);
|
|||
// BL: attributes #[[GVI]] = { nounwind{{.*}} }
|
||||
|
||||
// ASAN: attributes #[[NOATTR]] = { nounwind{{.*}} }
|
||||
// ASAN: attributes #[[WITH]] = { address_safety nounwind{{.*}} }
|
||||
// ASAN: attributes #[[GVI]] = { address_safety nounwind{{.*}} }
|
||||
// ASAN: attributes #[[WITH]] = {{.*}}sanitize_address
|
||||
// ASAN: attributes #[[GVI]] = {{.*}}sanitize_address
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
|
||||
// RUN: echo "src:%s" > %t
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread -fsanitize-blacklist=%t | FileCheck -check-prefix=BL %s
|
||||
|
||||
// REQUIRES: shell
|
||||
|
||||
// The sanitize_thread attribute should be attached to functions
|
||||
// when ThreadSanitizer is enabled, unless no_sanitize_thread attribute
|
||||
// is present.
|
||||
|
||||
// WITHOUT: NoTSAN1{{.*}}) #[[NOATTR:[0-9]+]]
|
||||
// BL: NoTSAN1{{.*}}) #[[NOATTR:[0-9]+]]
|
||||
// TSAN: NoTSAN1{{.*}}) #[[NOATTR:[0-9]+]]
|
||||
__attribute__((no_sanitize_thread))
|
||||
int NoTSAN1(int *a) { return *a; }
|
||||
|
||||
// WITHOUT: NoTSAN2{{.*}}) #[[NOATTR]]
|
||||
// BL: NoTSAN2{{.*}}) #[[NOATTR]]
|
||||
// TSAN: NoTSAN2{{.*}}) #[[NOATTR]]
|
||||
__attribute__((no_sanitize_thread))
|
||||
int NoTSAN2(int *a);
|
||||
int NoTSAN2(int *a) { return *a; }
|
||||
|
||||
// WITHOUT: TSANOk{{.*}}) #[[NOATTR]]
|
||||
// BL: TSANOk{{.*}}) #[[NOATTR]]
|
||||
// TSAN: TSANOk{{.*}}) #[[WITH:[0-9]+]]
|
||||
int TSANOk(int *a) { return *a; }
|
||||
|
||||
// WITHOUT: TemplateTSANOk{{.*}}) #[[NOATTR]]
|
||||
// BL: TemplateTSANOk{{.*}}) #[[NOATTR]]
|
||||
// TSAN: TemplateTSANOk{{.*}}) #[[WITH]]
|
||||
template<int i>
|
||||
int TemplateTSANOk() { return i; }
|
||||
|
||||
// WITHOUT: TemplateNoTSAN{{.*}}) #[[NOATTR]]
|
||||
// BL: TemplateNoTSAN{{.*}}) #[[NOATTR]]
|
||||
// TSAN: TemplateNoTSAN{{.*}}) #[[NOATTR]]
|
||||
template<int i>
|
||||
__attribute__((no_sanitize_thread))
|
||||
int TemplateNoTSAN() { return i; }
|
||||
|
||||
int force_instance = TemplateTSANOk<42>()
|
||||
+ TemplateNoTSAN<42>();
|
||||
|
||||
// Check that __cxx_global_var_init* get the sanitize_thread attribute.
|
||||
int global1 = 0;
|
||||
int global2 = *(int*)((char*)&global1+1);
|
||||
// WITHOUT: @__cxx_global_var_init{{.*}}#[[GVI:[0-9]+]]
|
||||
// BL: @__cxx_global_var_init{{.*}}#[[GVI:[0-9]+]]
|
||||
// TSAN: @__cxx_global_var_init{{.*}}#[[GVI:[0-9]+]]
|
||||
|
||||
// WITHOUT: attributes #[[NOATTR]] = { nounwind{{.*}} }
|
||||
// WITHOUT: attributes #[[GVI]] = { nounwind{{.*}} }
|
||||
// BL: attributes #[[NOATTR]] = { nounwind{{.*}} }
|
||||
// BL: attributes #[[GVI]] = { nounwind{{.*}} }
|
||||
|
||||
// TSAN: attributes #[[NOATTR]] = { nounwind{{.*}} }
|
||||
// TSAN: attributes #[[WITH]] = { nounwind{{.*}} sanitize_thread
|
||||
// TSAN: attributes #[[GVI]] = { nounwind{{.*}} sanitize_thread
|
|
@ -17,5 +17,5 @@
|
|||
|
||||
@end
|
||||
|
||||
// WITHOUT: attributes #0 = { nounwind{{.*}} }
|
||||
// ASAN: attributes #0 = { address_safety nounwind{{.*}} }
|
||||
// ASAN: attributes #0 = {{.*}}sanitize_address
|
||||
// WITHOUT-NOT: attributes #0 = {{.*}}sanitize_address
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
|
||||
|
||||
#if !__has_attribute(no_sanitize_address)
|
||||
#error "Should support no_sanitize_address"
|
||||
#endif
|
||||
|
||||
void noanal_fun() NO_SANITIZE_ADDRESS;
|
||||
|
||||
void noanal_fun_args() __attribute__((no_sanitize_address(1))); // \
|
||||
// expected-error {{attribute takes no arguments}}
|
||||
|
||||
int noanal_testfn(int y) NO_SANITIZE_ADDRESS;
|
||||
|
||||
int noanal_testfn(int y) {
|
||||
int x NO_SANITIZE_ADDRESS = y; // \
|
||||
// expected-error {{'no_sanitize_address' attribute only applies to functions and methods}}
|
||||
return x;
|
||||
}
|
||||
|
||||
int noanal_test_var NO_SANITIZE_ADDRESS; // \
|
||||
// expected-error {{'no_sanitize_address' attribute only applies to functions and methods}}
|
||||
|
||||
class NoanalFoo {
|
||||
private:
|
||||
int test_field NO_SANITIZE_ADDRESS; // \
|
||||
// expected-error {{'no_sanitize_address' attribute only applies to functions and methods}}
|
||||
void test_method() NO_SANITIZE_ADDRESS;
|
||||
};
|
||||
|
||||
class NO_SANITIZE_ADDRESS NoanalTestClass { // \
|
||||
// expected-error {{'no_sanitize_address' attribute only applies to functions and methods}}
|
||||
};
|
||||
|
||||
void noanal_fun_params(int lvar NO_SANITIZE_ADDRESS); // \
|
||||
// expected-error {{'no_sanitize_address' attribute only applies to functions and methods}}
|
|
@ -0,0 +1,37 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
||||
|
||||
#if !__has_attribute(no_sanitize_memory)
|
||||
#error "Should support no_sanitize_memory"
|
||||
#endif
|
||||
|
||||
void noanal_fun() NO_SANITIZE_MEMORY;
|
||||
|
||||
void noanal_fun_args() __attribute__((no_sanitize_memory(1))); // \
|
||||
// expected-error {{attribute takes no arguments}}
|
||||
|
||||
int noanal_testfn(int y) NO_SANITIZE_MEMORY;
|
||||
|
||||
int noanal_testfn(int y) {
|
||||
int x NO_SANITIZE_MEMORY = y; // \
|
||||
// expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}}
|
||||
return x;
|
||||
}
|
||||
|
||||
int noanal_test_var NO_SANITIZE_MEMORY; // \
|
||||
// expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}}
|
||||
|
||||
class NoanalFoo {
|
||||
private:
|
||||
int test_field NO_SANITIZE_MEMORY; // \
|
||||
// expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}}
|
||||
void test_method() NO_SANITIZE_MEMORY;
|
||||
};
|
||||
|
||||
class NO_SANITIZE_MEMORY NoanalTestClass { // \
|
||||
// expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}}
|
||||
};
|
||||
|
||||
void noanal_fun_params(int lvar NO_SANITIZE_MEMORY); // \
|
||||
// expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}}
|
|
@ -0,0 +1,37 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
#define NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
|
||||
#if !__has_attribute(no_sanitize_thread)
|
||||
#error "Should support no_sanitize_thread"
|
||||
#endif
|
||||
|
||||
void noanal_fun() NO_SANITIZE_THREAD;
|
||||
|
||||
void noanal_fun_args() __attribute__((no_sanitize_thread(1))); // \
|
||||
// expected-error {{attribute takes no arguments}}
|
||||
|
||||
int noanal_testfn(int y) NO_SANITIZE_THREAD;
|
||||
|
||||
int noanal_testfn(int y) {
|
||||
int x NO_SANITIZE_THREAD = y; // \
|
||||
// expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}}
|
||||
return x;
|
||||
}
|
||||
|
||||
int noanal_test_var NO_SANITIZE_THREAD; // \
|
||||
// expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}}
|
||||
|
||||
class NoanalFoo {
|
||||
private:
|
||||
int test_field NO_SANITIZE_THREAD; // \
|
||||
// expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}}
|
||||
void test_method() NO_SANITIZE_THREAD;
|
||||
};
|
||||
|
||||
class NO_SANITIZE_THREAD NoanalTestClass { // \
|
||||
// expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}}
|
||||
};
|
||||
|
||||
void noanal_fun_params(int lvar NO_SANITIZE_THREAD); // \
|
||||
// expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}}
|
Loading…
Reference in New Issue