]> granicus.if.org Git - clang/commitdiff
The following patch adds __attribute__((no_address_safety_analysis)) which will allow...
authorKostya Serebryany <kcc@google.com>
Tue, 24 Jan 2012 19:25:38 +0000 (19:25 +0000)
committerKostya Serebryany <kcc@google.com>
Tue, 24 Jan 2012 19:25:38 +0000 (19:25 +0000)
address safety analysis (such as e.g. AddressSanitizer or SAFECode) for a specific function.

When building with AddressSanitizer, add AddressSafety function attribute to every generated function
except for those that have __attribute__((no_address_safety_analysis)).

With this patch we will be able to
1. disable AddressSanitizer for a particular function
2. disable AddressSanitizer-hostile optimizations (such as some cases of load widening) when AddressSanitizer is on.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148842 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LanguageExtensions.html
include/clang/Basic/Attr.td
include/clang/Sema/AttributeList.h
lib/CodeGen/CodeGenModule.cpp
lib/Sema/AttributeList.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/address-safety-attr.cpp [new file with mode: 0644]

index 7b832bab927b2e0cdc2fa57932876f3b6847aa5a..7693d24154084336d8144d1b166835eff9b73f62 100644 (file)
@@ -1453,6 +1453,10 @@ balance in some way.</p>
 to check if the code is being built with <a
   href="AddressSanitizer.html">AddressSanitizer</a>.
 </p>
+<p>Use <tt>__attribute__((no_address_safety_analysis))</tt> on a function
+declaration to specify that address safety instrumentation (e.g.
+AddressSanitizer) should not be applied to that function.
+</p>
 
 <!-- ======================================================================= -->
 <h2 id="threadsafety">Thread-Safety Annotation Checking</h2>
index 292c9a396f58f88fd9e4bb2cec4592887499f6ac..a7680bbb52fd05d777ed5751ba06441641b8c3e8 100644 (file)
@@ -576,6 +576,10 @@ def X86ForceAlignArgPointer : InheritableAttr {
   let Spellings = [];
 }
 
+// AddressSafety attribute (e.g. for AddressSanitizer)
+def NoAddressSafetyAnalysis : InheritableAttr {
+  let Spellings = ["no_address_safety_analysis"];
+}
 
 // C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
 
index a54c1828aefb53138ed664c5cb3c32c10a21e815..545350f9ef90fa64c8d3c7124473a52a52ab16fc 100644 (file)
@@ -218,6 +218,7 @@ public:
     AT_naked,
     AT_neon_polyvector_type,    // Clang-specific.
     AT_neon_vector_type,        // Clang-specific.
+    AT_no_address_safety_analysis,
     AT_no_instrument_function,
     AT_no_thread_safety_analysis,
     AT_nocommon,
index c54b904abcb0ebcbbb20381bf231439221baa445..67059016f7de497969e16ea014efb9e1facd94e5 100644 (file)
@@ -1019,6 +1019,14 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
   if (ExtraAttrs != llvm::Attribute::None)
     F->addFnAttr(ExtraAttrs);
 
+  if (Features.AddressSanitizer) {
+    // When AddressSanitizer is enabled, set AddressSafety attribute
+    // unless __attribute__((no_address_safety_analysis)) is used.
+    const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl());
+    if (!FD || !FD->hasAttr<NoAddressSafetyAnalysisAttr>())
+      F->addFnAttr(llvm::Attribute::AddressSafety);
+  }
+
   // This is the first use or definition of a mangled name.  If there is a
   // deferred decl with this name, remember that we need to emit it at the end
   // of the file.
index c184676b9e5a72bc18a9bb841e06c1b95ea678b0..a3791dedf73b664cc1c32e9f73289bdb93ec6df4 100644 (file)
@@ -218,6 +218,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
     .Case("pt_guarded_var", AT_pt_guarded_var)
     .Case("scoped_lockable", AT_scoped_lockable)
     .Case("lockable", AT_lockable)
+    .Case("no_address_safety_analysis", AT_no_address_safety_analysis)
     .Case("no_thread_safety_analysis", AT_no_thread_safety_analysis)
     .Case("guarded_by", AT_guarded_by)
     .Case("pt_guarded_by", AT_pt_guarded_by)
index e06d637eeb7ec10cc1480d3b052b883a94343ebc..b15ad0ddd156613926a53264a77487a7c1559c6d 100644 (file)
@@ -444,6 +444,23 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
                                                           S.Context));
 }
 
+static void handleNoAddressSafetyAttr(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::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(),
+                                                          S.Context));
+}
+
 static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr,
                                    bool before) {
   assert(!Attr.isInvalid());
@@ -3678,6 +3695,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
   case AttributeList::AT_scoped_lockable:
     handleLockableAttr(S, D, Attr, /*scoped = */true);
     break;
+  case AttributeList::AT_no_address_safety_analysis:
+    handleNoAddressSafetyAttr(S, D, Attr);
+    break;
   case AttributeList::AT_no_thread_safety_analysis:
     handleNoThreadSafetyAttr(S, D, Attr);
     break;
diff --git a/test/CodeGen/address-safety-attr.cpp b/test/CodeGen/address-safety-attr.cpp
new file mode 100644 (file)
index 0000000..9d0fb95
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - %s -faddress-sanitizer | FileCheck -check-prefix ASAN %s
+
+// The address_safety attribute should be attached to functions
+// when AddressSanitizer is enabled, unless no_address_safety_analysis attribute
+// is present.
+
+// CHECK-NOT:  NoAddressSafety1{{.*}} address_safety
+// ASAN-NOT:  NoAddressSafety1{{.*}} address_safety
+__attribute__((no_address_safety_analysis))
+int NoAddressSafety1(int *a) { return *a; }
+
+// CHECK-NOT:  NoAddressSafety2{{.*}} address_safety
+// ASAN-NOT:  NoAddressSafety2{{.*}} address_safety
+__attribute__((no_address_safety_analysis))
+int NoAddressSafety2(int *a);
+int NoAddressSafety2(int *a) { return *a; }
+
+// CHECK-NOT:  AddressSafetyOk{{.*}} address_safety
+// ASAN: AddressSafetyOk{{.*}} address_safety
+int AddressSafetyOk(int *a) { return *a; }
+
+// CHECK-NOT:  TemplateNoAddressSafety{{.*}} address_safety
+// ASAN-NOT: TemplateNoAddressSafety{{.*}} address_safety
+template<int i>
+__attribute__((no_address_safety_analysis))
+int TemplateNoAddressSafety() { return i; }
+
+// CHECK-NOT:  TemplateAddressSafetyOk{{.*}} address_safety
+// ASAN: TemplateAddressSafetyOk{{.*}} address_safety
+template<int i>
+int TemplateAddressSafetyOk() { return i; }
+
+int force_instance = TemplateAddressSafetyOk<42>()
+                   + TemplateNoAddressSafety<42>();