Hi samsonov,
http://reviews.llvm.org/D9631
Files:
include/clang/AST/Attr.h
include/clang/Basic/Attr.td
include/clang/Basic/AttrDocs.td
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/address-safety-attr.cpp
test/CodeGen/sanitize-thread-attr.cpp
test/CodeGenCXX/cfi-vcall.cpp
test/Sema/attr-no-sanitize.c
utils/TableGen/ClangAttrEmitter.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/AST/Attr.h
===================================================================
--- include/clang/AST/Attr.h
+++ include/clang/AST/Attr.h
@@ -20,6 +20,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/SmallVector.h"
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -137,6 +137,7 @@
class BoolArgument<string name, bit opt = 0> : Argument<name, opt>;
class IdentifierArgument<string name, bit opt = 0> : Argument<name, opt>;
class IntArgument<string name, bit opt = 0> : Argument<name, opt>;
+class SanitizerMaskArgument<string name, bit opt = 0> : Argument<name, opt>;
class StringArgument<string name, bit opt = 0> : Argument<name, opt>;
class ExprArgument<string name, bit opt = 0> : Argument<name, opt>;
class FunctionArgument<string name, bit opt = 0> : Argument<name, opt>;
@@ -1386,6 +1387,14 @@
let Documentation = [Undocumented];
}
+def NoSanitize : InheritableAttr {
+ let Spellings = [GNU<"no_sanitize">];
+ let Args = [SanitizerMaskArgument<"Mask">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let HasCustomParsing = 1;
+ let Documentation = [NoSanitizeDocs];
+}
+
// Attribute to disable AddressSanitizer (or equivalent) checks.
def NoSanitizeAddress : InheritableAttr {
let Spellings = [GCC<"no_address_safety_analysis">,
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -920,6 +920,19 @@
}];
}
+def NoSanitizeDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Use the ``no_sanitize`` attribute on a function declaration to specify
+that a particular instrumentation or set of instrumentations should not be
+applied to that function. The attribute takes a list of string literals,
+which have the same meaning as values accepted by the ``-fno-sanitize=``
+flag. For example, ``__attribute__((no_sanitize("address", "thread")))``
+specifies that AddressSanitizer and ThreadSanitizer should not be applied
+to the function.
+ }];
+}
+
def NoSanitizeAddressDocs : Documentation {
let Category = DocCatFunction;
// This function has multiple distinct spellings, and so it requires a custom
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -608,6 +608,26 @@
if (CGM.isInSanitizerBlacklist(Fn, Loc))
SanOpts.clear();
+ if (D) {
+ // Apply the no_sanitize* attributes to SanOpts.
+ if (auto NoSanAttr = D->getAttr<NoSanitizeAttr>())
+ SanOpts.Mask &= ~NoSanAttr->getMask();
+ if (D->hasAttr<NoSanitizeAddressAttr>())
+ SanOpts.set(SanitizerKind::Address, false);
+ if (D->hasAttr<NoSanitizeThreadAttr>())
+ SanOpts.set(SanitizerKind::Thread, false);
+ if (D->hasAttr<NoSanitizeMemoryAttr>())
+ SanOpts.set(SanitizerKind::Memory, false);
+ }
+
+ // Apply sanitizer attributes to the function.
+ if (SanOpts.has(SanitizerKind::Address))
+ Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
+ if (SanOpts.has(SanitizerKind::Thread))
+ Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+ if (SanOpts.has(SanitizerKind::Memory))
+ Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+
// Pass inline keyword to optimizer if it appears explicitly on any
// declaration. Also, in the case of -fno-inline attach NoInline
// attribute to all function that are not marked AlwaysInline.
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -745,23 +745,6 @@
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
B.addAttribute(llvm::Attribute::StackProtectReq);
- // Add sanitizer attributes if function is not blacklisted.
- if (!isInSanitizerBlacklist(F, D->getLocation())) {
- // When AddressSanitizer is enabled, set SanitizeAddress attribute
- // unless __attribute__((no_sanitize_address)) is used.
- if (LangOpts.Sanitize.has(SanitizerKind::Address) &&
- !D->hasAttr<NoSanitizeAddressAttr>())
- B.addAttribute(llvm::Attribute::SanitizeAddress);
- // Same for ThreadSanitizer and __attribute__((no_sanitize_thread))
- if (LangOpts.Sanitize.has(SanitizerKind::Thread) &&
- !D->hasAttr<NoSanitizeThreadAttr>())
- B.addAttribute(llvm::Attribute::SanitizeThread);
- // Same for MemorySanitizer and __attribute__((no_sanitize_memory))
- if (LangOpts.Sanitize.has(SanitizerKind::Memory) &&
- !D->hasAttr<NoSanitizeMemoryAttr>())
- B.addAttribute(llvm::Attribute::SanitizeMemory);
- }
-
F->addAttributes(llvm::AttributeSet::FunctionIndex,
llvm::AttributeSet::get(
F->getContext(), llvm::AttributeSet::FunctionIndex, B));
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -4354,6 +4354,28 @@
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
}
+static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ SanitizerMask Mask = 0;
+
+ for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+ StringRef SanitizerName;
+ SourceLocation LiteralLoc;
+
+ if (!S.checkStringLiteralArgumentAttr(Attr, I, SanitizerName, &LiteralLoc))
+ return;
+
+ SanitizerMask ParsedMask =
+ parseSanitizerValue(SanitizerName, /*AllowGroups=*/true);
+ Mask |= expandSanitizerGroups(ParsedMask);
+ }
+
+ D->addAttr(::new (S.Context) NoSanitizeAttr(
+ Attr.getRange(), S.Context, Mask, Attr.getAttributeSpellingListIndex()));
+}
+
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
@@ -4822,6 +4844,9 @@
case AttributeList::AT_ScopedLockable:
handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
break;
+ case AttributeList::AT_NoSanitize:
+ handleNoSanitizeAttr(S, D, Attr);
+ break;
case AttributeList::AT_NoSanitizeAddress:
handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr);
break;
Index: test/CodeGen/address-safety-attr.cpp
===================================================================
--- test/CodeGen/address-safety-attr.cpp
+++ test/CodeGen/address-safety-attr.cpp
@@ -52,6 +52,21 @@
int NoAddressSafety2(int *a);
int NoAddressSafety2(int *a) { return *a; }
+// WITHOUT: NoAddressSafety3{{.*}}) [[NOATTR]]
+// BLFILE: NoAddressSafety3{{.*}}) [[NOATTR]]
+// BLFUNC: NoAddressSafety3{{.*}}) [[NOATTR]]
+// ASAN: NoAddressSafety3{{.*}}) [[NOATTR]]
+__attribute__((no_sanitize("address")))
+int NoAddressSafety3(int *a) { return *a; }
+
+// WITHOUT: NoAddressSafety4{{.*}}) [[NOATTR]]
+// BLFILE: NoAddressSafety4{{.*}}) [[NOATTR]]
+// BLFUNC: NoAddressSafety4{{.*}}) [[NOATTR]]
+// ASAN: NoAddressSafety4{{.*}}) [[NOATTR]]
+__attribute__((no_sanitize("address")))
+int NoAddressSafety4(int *a);
+int NoAddressSafety4(int *a) { return *a; }
+
// WITHOUT: AddressSafetyOk{{.*}}) [[NOATTR]]
// BLFILE: AddressSafetyOk{{.*}}) [[NOATTR]]
// BLFUNC: AddressSafetyOk{{.*}}) [[WITH]]
@@ -86,16 +101,25 @@
template<int i>
int TemplateAddressSafetyOk() { return i; }
-// WITHOUT: TemplateNoAddressSafety{{.*}}) [[NOATTR]]
-// BLFILE: TemplateNoAddressSafety{{.*}}) [[NOATTR]]
-// BLFUNC: TemplateNoAddressSafety{{.*}}) [[NOATTR]]
-// ASAN: TemplateNoAddressSafety{{.*}}) [[NOATTR]]
+// WITHOUT: TemplateNoAddressSafety1{{.*}}) [[NOATTR]]
+// BLFILE: TemplateNoAddressSafety1{{.*}}) [[NOATTR]]
+// BLFUNC: TemplateNoAddressSafety1{{.*}}) [[NOATTR]]
+// ASAN: TemplateNoAddressSafety1{{.*}}) [[NOATTR]]
template<int i>
__attribute__((no_sanitize_address))
-int TemplateNoAddressSafety() { return i; }
+int TemplateNoAddressSafety1() { return i; }
+
+// WITHOUT: TemplateNoAddressSafety2{{.*}}) [[NOATTR]]
+// BLFILE: TemplateNoAddressSafety2{{.*}}) [[NOATTR]]
+// BLFUNC: TemplateNoAddressSafety2{{.*}}) [[NOATTR]]
+// ASAN: TemplateNoAddressSafety2{{.*}}) [[NOATTR]]
+template<int i>
+__attribute__((no_sanitize("address")))
+int TemplateNoAddressSafety2() { return i; }
int force_instance = TemplateAddressSafetyOk<42>()
- + TemplateNoAddressSafety<42>();
+ + TemplateNoAddressSafety1<42>()
+ + TemplateNoAddressSafety2<42>();
// Check that __cxx_global_var_init* get the sanitize_address attribute.
int global1 = 0;
Index: test/CodeGen/sanitize-thread-attr.cpp
===================================================================
--- test/CodeGen/sanitize-thread-attr.cpp
+++ test/CodeGen/sanitize-thread-attr.cpp
@@ -22,6 +22,12 @@
int NoTSAN2(int *a);
int NoTSAN2(int *a) { return *a; }
+// WITHOUT: NoTSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// BL: NoTSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// TSAN: NoTSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+__attribute__((no_sanitize("thread")))
+int NoTSAN3(int *a) { return *a; }
+
// WITHOUT: TSANOk{{.*}}) [[NOATTR]]
// BL: TSANOk{{.*}}) [[NOATTR]]
// TSAN: TSANOk{{.*}}) [[WITH:#[0-9]+]]
Index: test/CodeGenCXX/cfi-vcall.cpp
===================================================================
--- test/CodeGenCXX/cfi-vcall.cpp
+++ test/CodeGenCXX/cfi-vcall.cpp
@@ -47,16 +47,32 @@
a->f();
}
-// CHECK: define internal void @_Z2dfPN12_GLOBAL__N_11DE
-void df(D *d) {
+// CHECK: define internal void @_Z3df1PN12_GLOBAL__N_11DE
+void df1(D *d) {
// CHECK: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"[{{.*}}cfi-vcall.cpp]N12_GLOBAL__N_11DE")
d->f();
}
+// CHECK: define internal void @_Z3df2PN12_GLOBAL__N_11DE
+__attribute__((no_sanitize("cfi")))
+void df2(D *d) {
+ // CHECK-NOT: call i1 @llvm.bitset.test
+ d->f();
+}
+
+// CHECK: define internal void @_Z3df3PN12_GLOBAL__N_11DE
+__attribute__((no_sanitize("address", "cfi-vcall")))
+void df3(D *d) {
+ // CHECK-NOT: call i1 @llvm.bitset.test
+ d->f();
+}
+
D d;
void foo() {
- df(&d);
+ df1(&d);
+ df2(&d);
+ df3(&d);
}
// CHECK-DAG: !{!"1A", [3 x i8*]* @_ZTV1A, i64 16}
Index: test/Sema/attr-no-sanitize.c
===================================================================
--- /dev/null
+++ test/Sema/attr-no-sanitize.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: not %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s
+
+int f1() __attribute__((no_sanitize)); // expected-error{{'no_sanitize' attribute takes at least 1 argument}}
+
+int f2() __attribute__((no_sanitize(1))); // expected-error{{'no_sanitize' attribute requires a string}}
+
+// CHECK-LABEL: FunctionDecl {{.*}} f3
+// CHECK: NoSanitizeAttr {{.*}} 1
+int f3() __attribute__((no_sanitize("address")));
+
+// CHECK-LABEL: FunctionDecl {{.*}} f4
+// CHECK: NoSanitizeAttr {{.*}} 4
+int f4() __attribute__((no_sanitize("thread")));
+
+// CHECK-LABEL: FunctionDecl {{.*}} f5
+// CHECK: NoSanitizeAttr {{.*}} 5
+int f5() __attribute__((no_sanitize("address", "thread")));
+
+// CHECK-LABEL: FunctionDecl {{.*}} f6
+// CHECK: NoSanitizeAttr {{.*}} 0
+int f6() __attribute__((no_sanitize("unknown")));
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -282,7 +282,8 @@
} else if (type == "bool") {
OS << " if (SA->get" << getUpperName() << "()) OS << \" "
<< getUpperName() << "\";\n";
- } else if (type == "int" || type == "unsigned") {
+ } else if (type == "int" || type == "unsigned" ||
+ type == "SanitizerMask") {
OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
} else {
llvm_unreachable("Unknown SimpleArgument type!");
@@ -1036,6 +1037,8 @@
Arg, Attr, "int", Arg.getValueAsInt("Default"));
else if (ArgName == "IntArgument")
Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "int");
+ else if (ArgName == "SanitizerMaskArgument")
+ Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "SanitizerMask");
else if (ArgName == "StringArgument")
Ptr = llvm::make_unique<StringArgument>(Arg, Attr);
else if (ArgName == "TypeArgument")
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits