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 @@ -2940,6 +2940,13 @@ let ASTNode = 0; } +def DisableSanitizerInstrumentation : InheritableAttr { + let Spellings = [Clang<"disable_sanitizer_instrumentation">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [DisableSanitizerInstrumentationDocs]; + let SimpleHandler = 1; +} + def CFICanonicalJumpTable : InheritableAttr { let Spellings = [Clang<"cfi_canonical_jump_table">]; let Subjects = SubjectList<[Function], ErrorDiag>; 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 @@ -2592,6 +2592,17 @@ }]; } +def DisableSanitizerInstrumentationDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Use the ``disable_sanitizer_instrumentation`` attribute on a function to +specify that no sanitizer instrumentation should be applied. + +This is not the same as ``__attribute__((no_sanitize(...)))``, which depending +on the tool may still insert instrumentation to prevent false positive reports. + }]; +} + def NoSanitizeAddressDocs : Documentation { let Category = DocCatFunction; // This function has multiple distinct spellings, and so it requires a custom diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2286,6 +2286,10 @@ /// instrumented with __cyg_profile_func_* calls bool ShouldInstrumentFunction(); + /// ShouldSkipSanitizerInstrumentation - Return true if the current function + /// should not be instrumented with sanitizers. + bool ShouldSkipSanitizerInstrumentation(); + /// ShouldXRayInstrument - Return true if the current function should be /// instrumented with XRay nop sleds. bool ShouldXRayInstrumentFunction() const; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -381,6 +381,9 @@ "__cyg_profile_func_exit"); } + if (ShouldSkipSanitizerInstrumentation()) + CurFn->addFnAttr(llvm::Attribute::DisableSanitizerInstrumentation); + // Emit debug descriptor for function end. if (CGDebugInfo *DI = getDebugInfo()) DI->EmitFunctionEnd(Builder, CurFn); @@ -517,6 +520,14 @@ return true; } +bool CodeGenFunction::ShouldSkipSanitizerInstrumentation() { + if (!CurFuncDecl) + return false; + if (CurFuncDecl->hasAttr()) + return true; + return false; +} + /// ShouldXRayInstrument - Return true if the current function should be /// instrumented with XRay nop sleds. bool CodeGenFunction::ShouldXRayInstrumentFunction() const { diff --git a/clang/test/CodeGen/attr-no-sanitize-coverage.c b/clang/test/CodeGen/attr-no-sanitize-coverage.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/attr-no-sanitize-coverage.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -debug-info-kind=limited %s -emit-llvm -o - | FileCheck %s + +void t1() __attribute__((disable_sanitizer_instrumentation)) { +} +// CHECK: disable_sanitizer_instrumentation +// CHECK-NEXT: void @t1 + +// CHECK-NOT: disable_sanitizer_instrumentation +// CHECK: void @t2 +void t2() { +} 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 @@ -56,6 +56,7 @@ // CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: Destructor (SubjectMatchRule_function) +// CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function) // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: EnableIf (SubjectMatchRule_function) // CHECK-NEXT: EnforceTCB (SubjectMatchRule_function) diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -190,6 +190,7 @@ kw_convergent, kw_dereferenceable, kw_dereferenceable_or_null, + kw_disable_sanitizer_instrumentation, kw_elementtype, kw_inaccessiblememonly, kw_inaccessiblemem_or_argmemonly, diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -671,6 +671,7 @@ ATTR_KIND_SWIFT_ASYNC = 75, ATTR_KIND_NO_SANITIZE_COVERAGE = 76, ATTR_KIND_ELEMENTTYPE = 77, + ATTR_DISABLE_SANITIZER_INSTRUMENTATION = 78, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -86,6 +86,9 @@ def DereferenceableOrNull : IntAttr<"dereferenceable_or_null", [ParamAttr, RetAttr]>; +/// Do not instrument function with sanitizers. +def DisableSanitizerInstrumentation: EnumAttr<"disable_sanitizer_instrumentation", [FnAttr]>; + /// Provide pointer element type to intrinsic. def ElementType : TypeAttr<"elementtype", [ParamAttr]>; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -628,6 +628,8 @@ return bitc::ATTR_KIND_IN_ALLOCA; case Attribute::Cold: return bitc::ATTR_KIND_COLD; + case Attribute::DisableSanitizerInstrumentation: + return bitc::ATTR_DISABLE_SANITIZER_INSTRUMENTATION; case Attribute::Hot: return bitc::ATTR_KIND_HOT; case Attribute::ElementType: diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -943,6 +943,7 @@ // Those attributes should be safe to propagate to the extracted function. case Attribute::AlwaysInline: case Attribute::Cold: + case Attribute::DisableSanitizerInstrumentation: case Attribute::Hot: case Attribute::NoRecurse: case Attribute::InlineHint: