r237463 - Implement no_sanitize attribute.

Peter Collingbourne peter at pcc.me.uk
Fri May 15 11:33:32 PDT 2015


Author: pcc
Date: Fri May 15 13:33:32 2015
New Revision: 237463

URL: http://llvm.org/viewvc/llvm-project?rev=237463&view=rev
Log:
Implement no_sanitize attribute.

Differential Revision: http://reviews.llvm.org/D9631

Added:
    cfe/trunk/test/CodeGenObjC/no-sanitize.m
    cfe/trunk/test/SemaCXX/attr-no-sanitize.cpp
Modified:
    cfe/trunk/docs/UsersManual.rst
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/CodeGen/address-safety-attr.cpp
    cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp
    cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/docs/UsersManual.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.rst?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/docs/UsersManual.rst (original)
+++ cfe/trunk/docs/UsersManual.rst Fri May 15 13:33:32 2015
@@ -930,6 +930,8 @@ number of cases where the compilation en
 and the precompiled header cannot be generated after headers have been
 installed.
 
+.. _controlling-code-generation:
+
 Controlling Code Generation
 ---------------------------
 

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Fri May 15 13:33:32 2015
@@ -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"

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri May 15 13:33:32 2015
@@ -144,6 +144,7 @@ class TypeArgument<string name, bit opt
 class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
 class VariadicUnsignedArgument<string name> : Argument<name, 1>;
 class VariadicExprArgument<string name> : Argument<name, 1>;
+class VariadicStringArgument<string name> : Argument<name, 1>;
 
 // A version of the form major.minor[.subminor].
 class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
@@ -1386,26 +1387,35 @@ def X86ForceAlignArgPointer : Inheritabl
   let Documentation = [Undocumented];
 }
 
-// Attribute to disable AddressSanitizer (or equivalent) checks.
-def NoSanitizeAddress : InheritableAttr {
-  let Spellings = [GCC<"no_address_safety_analysis">,
-                   GCC<"no_sanitize_address">];
-  let Subjects = SubjectList<[Function], ErrorDiag>;
-  let Documentation = [NoSanitizeAddressDocs];
-}
-
-// Attribute to disable ThreadSanitizer checks.
-def NoSanitizeThread : InheritableAttr {
-  let Spellings = [GNU<"no_sanitize_thread">];
-  let Subjects = SubjectList<[Function], ErrorDiag>;
-  let Documentation = [NoSanitizeThreadDocs];
+def NoSanitize : InheritableAttr {
+  let Spellings = [GNU<"no_sanitize">, CXX11<"clang", "no_sanitize">];
+  let Args = [VariadicStringArgument<"Sanitizers">];
+  let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
+  let Documentation = [NoSanitizeDocs];
+  let AdditionalMembers = [{
+    SanitizerMask getMask() const {
+      SanitizerMask Mask = 0;
+      for (auto SanitizerName : sanitizers()) {
+        SanitizerMask ParsedMask =
+            parseSanitizerValue(SanitizerName, /*AllowGroups=*/true);
+        Mask |= expandSanitizerGroups(ParsedMask);
+      }
+      return Mask;
+    }
+  }];
 }
 
-// Attribute to disable MemorySanitizer checks.
-def NoSanitizeMemory : InheritableAttr {
-  let Spellings = [GNU<"no_sanitize_memory">];
+// Attributes to disable a specific sanitizer. No new sanitizers should be added
+// to this list; the no_sanitize attribute should be extended instead.
+def NoSanitizeSpecific : InheritableAttr {
+  let Spellings = [GCC<"no_address_safety_analysis">,
+                   GCC<"no_sanitize_address">,
+                   GCC<"no_sanitize_thread">,
+                   GNU<"no_sanitize_memory">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
-  let Documentation = [NoSanitizeMemoryDocs];
+  let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs,
+                       NoSanitizeMemoryDocs];
+  let ASTNode = 0;
 }
 
 // C/C++ Thread safety attributes (e.g. for deadlock, data race checking)

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Fri May 15 13:33:32 2015
@@ -920,6 +920,22 @@ This attribute accepts a single paramete
   }];
 }
 
+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.
+
+See :ref:`Controlling Code Generation <controlling-code-generation>` for a
+full list of supported sanitizer flags.
+  }];
+}
+
 def NoSanitizeAddressDocs : Documentation {
   let Category = DocCatFunction;
   // This function has multiple distinct spellings, and so it requires a custom
@@ -936,6 +952,7 @@ not be applied to that function.
 
 def NoSanitizeThreadDocs : Documentation {
   let Category = DocCatFunction;
+  let Heading = "no_sanitize_thread";
   let Content = [{
 .. _langext-thread_sanitizer:
 
@@ -948,6 +965,7 @@ tool to avoid false positives and provid
 
 def NoSanitizeMemoryDocs : Documentation {
   let Category = DocCatFunction;
+  let Heading = "no_sanitize_memory";
   let Content = [{
 .. _langext-memory_sanitizer:
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri May 15 13:33:32 2015
@@ -401,6 +401,7 @@ def UnknownAttributes : DiagGroup<"unkno
 def IgnoredAttributes : DiagGroup<"ignored-attributes">;
 def Attributes : DiagGroup<"attributes", [UnknownAttributes,
                                           IgnoredAttributes]>;
+def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;
 def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
                                         [CXX98CompatUnnamedTypeTemplateArgs]>;
 def UnsupportedFriend : DiagGroup<"unsupported-friend">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri May 15 13:33:32 2015
@@ -2519,6 +2519,10 @@ def warn_param_typestate_mismatch : Warn
   "argument not in expected state; expected '%0', observed '%1'">,
   InGroup<Consumed>, DefaultIgnore;
 
+// no_sanitize attribute
+def warn_unknown_sanitizer_ignored : Warning<
+  "unknown sanitizer '%0' ignored">, InGroup<UnknownSanitizers>;
+
 def warn_impcast_vector_scalar : Warning<
   "implicit conversion turns vector to scalar: %0 to %1">,
   InGroup<Conversion>, DefaultIgnore;

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri May 15 13:33:32 2015
@@ -608,6 +608,20 @@ void CodeGenFunction::StartFunction(Glob
   if (CGM.isInSanitizerBlacklist(Fn, Loc))
     SanOpts.clear();
 
+  if (D) {
+    // Apply the no_sanitize* attributes to SanOpts.
+    for (auto Attr : D->specific_attrs<NoSanitizeAttr>())
+      SanOpts.Mask &= ~Attr->getMask();
+  }
+
+  // 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.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri May 15 13:33:32 2015
@@ -752,23 +752,6 @@ void CodeGenModule::SetLLVMFunctionAttri
   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));

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri May 15 13:33:32 2015
@@ -4354,6 +4354,45 @@ static void handleDeprecatedAttr(Sema &S
   handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
 }
 
+static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+    return;
+
+  std::vector<std::string> Sanitizers;
+
+  for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+    StringRef SanitizerName;
+    SourceLocation LiteralLoc;
+
+    if (!S.checkStringLiteralArgumentAttr(Attr, I, SanitizerName, &LiteralLoc))
+      return;
+
+    if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0)
+      S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
+
+    Sanitizers.push_back(SanitizerName);
+  }
+
+  D->addAttr(::new (S.Context) NoSanitizeAttr(
+      Attr.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
+      Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
+                                         const AttributeList &Attr) {
+  std::string SanitizerName =
+      llvm::StringSwitch<const char *>(Attr.getName()->getName())
+          .Case("no_address_safety_analysis", "address")
+          .Case("no_sanitize_address", "address")
+          .Case("no_sanitize_thread", "thread")
+          .Case("no_sanitize_memory", "memory")
+          .Default("");
+  assert(!SanitizerName.empty());
+  D->addAttr(::new (S.Context)
+                 NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1,
+                                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,18 +4861,15 @@ static void ProcessDeclAttribute(Sema &S
   case AttributeList::AT_ScopedLockable:
     handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
     break;
-  case AttributeList::AT_NoSanitizeAddress:
-    handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr);
+  case AttributeList::AT_NoSanitize:
+    handleNoSanitizeAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_NoSanitizeSpecific:
+    handleNoSanitizeSpecificAttr(S, D, Attr);
     break;
   case AttributeList::AT_NoThreadSafetyAnalysis:
     handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
     break;
-  case AttributeList::AT_NoSanitizeThread:
-    handleSimpleAttribute<NoSanitizeThreadAttr>(S, D, Attr);
-    break;
-  case AttributeList::AT_NoSanitizeMemory:
-    handleSimpleAttribute<NoSanitizeMemoryAttr>(S, D, Attr);
-    break;
   case AttributeList::AT_GuardedBy:
     handleGuardedByAttr(S, D, Attr);
     break;

Modified: cfe/trunk/test/CodeGen/address-safety-attr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/address-safety-attr.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/address-safety-attr.cpp (original)
+++ cfe/trunk/test/CodeGen/address-safety-attr.cpp Fri May 15 13:33:32 2015
@@ -3,14 +3,14 @@ int DefinedInDifferentFile(int *a);
 // RUN: echo "struct S { S(){} ~S(){} };" >> %t.extra-source.cpp
 // RUN: echo "S glob_array[5];" >> %t.extra-source.cpp
 
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp | FileCheck -check-prefix=WITHOUT %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address | FileCheck -check-prefix=ASAN %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address | FileCheck -check-prefix=ASAN %s
 
 // RUN: echo "fun:*BlacklistedFunction*" > %t.func.blacklist
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
 
 // RUN: echo "src:%s" > %t.file.blacklist
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
 
 // FIXME: %t.file.blacklist is like "src:x:\path\to\clang\test\CodeGen\address-safety-attr.cpp"
 // REQUIRES: shell
@@ -52,6 +52,36 @@ __attribute__((no_sanitize_address))
 int NoAddressSafety2(int *a);
 int NoAddressSafety2(int *a) { return *a; }
 
+// WITHOUT:  NoAddressSafety3{{.*}}) [[NOATTR]]
+// BLFILE:  NoAddressSafety3{{.*}}) [[NOATTR]]
+// BLFUNC:  NoAddressSafety3{{.*}}) [[NOATTR]]
+// ASAN:  NoAddressSafety3{{.*}}) [[NOATTR]]
+[[gnu::no_sanitize_address]]
+int NoAddressSafety3(int *a) { return *a; }
+
+// WITHOUT:  NoAddressSafety4{{.*}}) [[NOATTR]]
+// BLFILE:  NoAddressSafety4{{.*}}) [[NOATTR]]
+// BLFUNC:  NoAddressSafety4{{.*}}) [[NOATTR]]
+// ASAN:  NoAddressSafety4{{.*}}) [[NOATTR]]
+[[gnu::no_sanitize_address]]
+int NoAddressSafety4(int *a);
+int NoAddressSafety4(int *a) { return *a; }
+
+// WITHOUT:  NoAddressSafety5{{.*}}) [[NOATTR]]
+// BLFILE:  NoAddressSafety5{{.*}}) [[NOATTR]]
+// BLFUNC:  NoAddressSafety5{{.*}}) [[NOATTR]]
+// ASAN:  NoAddressSafety5{{.*}}) [[NOATTR]]
+__attribute__((no_sanitize("address")))
+int NoAddressSafety5(int *a) { return *a; }
+
+// WITHOUT:  NoAddressSafety6{{.*}}) [[NOATTR]]
+// BLFILE:  NoAddressSafety6{{.*}}) [[NOATTR]]
+// BLFUNC:  NoAddressSafety6{{.*}}) [[NOATTR]]
+// ASAN:  NoAddressSafety6{{.*}}) [[NOATTR]]
+__attribute__((no_sanitize("address")))
+int NoAddressSafety6(int *a);
+int NoAddressSafety6(int *a) { return *a; }
+
 // WITHOUT:  AddressSafetyOk{{.*}}) [[NOATTR]]
 // BLFILE:  AddressSafetyOk{{.*}}) [[NOATTR]]
 // BLFUNC: AddressSafetyOk{{.*}}) [[WITH]]
@@ -86,16 +116,25 @@ int GENERATE_NAME(Function)(int *a) { re
 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;

Modified: cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp (original)
+++ cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp Fri May 15 13:33:32 2015
@@ -22,6 +22,12 @@ __attribute__((no_sanitize_thread))
 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]+]]

Modified: cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cfi-vcall.cpp Fri May 15 13:33:32 2015
@@ -47,16 +47,32 @@ void af(A *a) {
   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"))) __attribute__((no_sanitize("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}

Added: cfe/trunk/test/CodeGenObjC/no-sanitize.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/no-sanitize.m?rev=237463&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/no-sanitize.m (added)
+++ cfe/trunk/test/CodeGenObjC/no-sanitize.m Fri May 15 13:33:32 2015
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -emit-llvm -fsanitize=address -o - | FileCheck %s
+
+ at interface I0 @end
+ at implementation I0
+// CHECK-NOT: sanitize_address
+- (void) im0: (int) a0 __attribute__((no_sanitize("address"))) {
+}
+ at end

Added: cfe/trunk/test/SemaCXX/attr-no-sanitize.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-no-sanitize.cpp?rev=237463&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-no-sanitize.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-no-sanitize.cpp Fri May 15 13:33:32 2015
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: not %clang_cc1 -std=c++11 -ast-dump %s 2>&1 | FileCheck --check-prefix=DUMP %s
+// RUN: not %clang_cc1 -std=c++11 -ast-print %s 2>&1 | FileCheck --check-prefix=PRINT %s
+
+int v1 __attribute__((no_sanitize("address"))); // expected-error{{'no_sanitize' attribute only applies to functions and methods}}
+
+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}}
+
+// DUMP-LABEL: FunctionDecl {{.*}} f3
+// DUMP: NoSanitizeAttr {{.*}} address
+// PRINT: int f3() __attribute__((no_sanitize("address")))
+int f3() __attribute__((no_sanitize("address")));
+
+// DUMP-LABEL: FunctionDecl {{.*}} f4
+// DUMP: NoSanitizeAttr {{.*}} thread
+// PRINT: int f4() {{\[\[}}clang::no_sanitize("thread")]]
+[[clang::no_sanitize("thread")]] int f4();
+
+// DUMP-LABEL: FunctionDecl {{.*}} f5
+// DUMP: NoSanitizeAttr {{.*}} address thread
+// PRINT: int f5() __attribute__((no_sanitize("address", "thread")))
+int f5() __attribute__((no_sanitize("address", "thread")));
+
+// DUMP-LABEL: FunctionDecl {{.*}} f6
+// DUMP: NoSanitizeAttr {{.*}} unknown
+// PRINT: int f6() __attribute__((no_sanitize("unknown")))
+int f6() __attribute__((no_sanitize("unknown"))); // expected-warning{{unknown sanitizer 'unknown' ignored}}

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=237463&r1=237462&r2=237463&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri May 15 13:33:32 2015
@@ -82,6 +82,7 @@ static std::string ReadPCHRecord(StringR
     .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
     .Case("Expr *", "ReadExpr(F)")
     .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
+    .Case("std::string", "ReadString(Record, Idx)")
     .Default("Record[Idx++]");
 }
 
@@ -95,6 +96,7 @@ static std::string WritePCHRecord(String
     .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
     .Case("IdentifierInfo *", 
           "AddIdentifierRef(" + std::string(name) + ", Record);\n")
+    .Case("std::string", "AddString(" + std::string(name) + ", Record);\n")
     .Default("Record.push_back(" + std::string(name) + ");\n");
 }
 
@@ -983,6 +985,16 @@ namespace {
     }
   };
 
+  class VariadicStringArgument : public VariadicArgument {
+  public:
+    VariadicStringArgument(const Record &Arg, StringRef Attr)
+      : VariadicArgument(Arg, Attr, "std::string")
+    {}
+    void writeValueImpl(raw_ostream &OS) const override {
+      OS << "    OS << \"\\\"\" << Val << \"\\\"\";\n";
+    }
+  };
+
   class TypeArgument : public SimpleArgument {
   public:
     TypeArgument(const Record &Arg, StringRef Attr)
@@ -1044,6 +1056,8 @@ createArgument(const Record &Arg, String
     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "unsigned");
   else if (ArgName == "VariadicUnsignedArgument")
     Ptr = llvm::make_unique<VariadicArgument>(Arg, Attr, "unsigned");
+  else if (ArgName == "VariadicStringArgument")
+    Ptr = llvm::make_unique<VariadicStringArgument>(Arg, Attr);
   else if (ArgName == "VariadicEnumArgument")
     Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr);
   else if (ArgName == "VariadicExprArgument")





More information about the cfe-commits mailing list