kuhar added a subscriber: aaron.ballman.
kuhar updated this revision to Diff 29896.
kuhar added a comment.

Thanks for review.
Aaron - fixed things you pointed out, except not dropping attribute - I'm not 
entirely convinced, because attributes are being dropped on error in the entire 
file...

Richard:
ad. 1. This should be fixed now - I only report error when variables are 
initialized with some 'constant expression', so that dynamic initializers are 
allowed.
ad. 2.

> I think it's less reasonable to do this in C++>


Could you explain why?
ad. 3. I didn't know what to do with member pointers, so I left them unchecked. 
Is there a better way to determine non-zeroness of variable? Or maybe I should 
add it somewhere, so it can be target-specific (CXXABI.h?)?
ad. 4. Are there some existing mechanisms to do so, or could explain how it 
should be done? I've only found a function for validating section names 
(`isValidSectionSpecifier` in TargetInfo.h).
I would really appreciate your further help on this.


Repository:
  rL LLVM

http://reviews.llvm.org/D11221

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/Sema/attr-section-bss.c

Index: test/Sema/attr-section-bss.c
===================================================================
--- /dev/null
+++ test/Sema/attr-section-bss.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+__attribute__((section(".bss.Name"))) int a = 3 * 5; // expected-error {{variables placed in BSS section must be zero-initialized, but 'a' is initialized with a non-zero value}}
+__attribute__((section(".bss.Name"))) int correct_a = 0 * 5;
+
+__attribute__((section(".bss.Name"))) float x = 3 * 0.997; // expected-error {{variables placed in BSS section must be zero-initialized, but 'x' is initialized with a non-zero value}}
+__attribute__((section(".bss.Name"))) float correct_x = 0.0 * 0.997;
+
+__attribute__((section(".bss.Sth"))) void foo() {} // expected-error {{functions cannot be placed in BSS section}}
+
+__attribute__((section(".bss.Name"))) int arr[] = {0, 2, 0}; // expected-error {{variables placed in BSS section must be zero-initialized, but 'arr' is initialized with a non-zero value}}
+__attribute__((section(".bss.Name"))) int correct_arr[] = {0, 0, 0};
+
+typedef struct {
+  float a;
+  int b;
+  double arr[3];
+} TestStruct;
+
+__attribute__((section(".bss"))) TestStruct str = {0.0, 0, {0.0, 1.0, 0.0}}; // expected-error {{variables placed in BSS section must be zero-initialized, but 'str' is initialized with a non-zero value}}}
+__attribute__((section(".bss"))) TestStruct correct_str = {0.0, 0, {0.0, 0.0, 0.0}};
+
+typedef struct {} EmptyStruct;
+__attribute__((section(".bss.Name"))) EmptyStruct estr = {};
+
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -2396,6 +2396,12 @@
   SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
   if (NewAttr)
     D->addAttr(NewAttr);
+
+  if (isa<FunctionDecl>(D) && Str.startswith(".bss")) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_section_bss_function)
+       << NewAttr->getRange();
+    D->dropAttr<SectionAttr>();
+  }
 }
 
 // Check for things we'd like to warn about, no errors or validation for now.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5302,6 +5302,99 @@
   return false;
 }
 
+static bool isValueNonZero(const APValue &Value) {
+  switch (Value.getKind()) {
+  case APValue::Uninitialized:
+    return false;
+  case APValue::Int:
+    return Value.getInt() != 0;
+  case APValue::Float:
+    return Value.getFloat().isNonZero();
+  case APValue::ComplexInt: {
+    bool isRealNonZero = Value.getComplexIntReal() != 0;
+    bool isImagNonZero = Value.getComplexIntImag() != 0;
+    return isRealNonZero || isImagNonZero;
+  }
+  case APValue::ComplexFloat: {
+    bool isRealNonZero = Value.getComplexFloatReal().isNonZero();
+    bool isImagNonZero = Value.getComplexFloatImag().isNonZero();
+    return isRealNonZero || isImagNonZero;
+  }
+  case APValue::Vector: {
+    for (unsigned i = 0, e = Value.getVectorLength(); i < e; ++i) {
+      if (isValueNonZero(Value.getVectorElt(i)))
+        return true;
+    }
+    return false;
+  }
+  case APValue::Array: {
+    for (unsigned i = 0, e = Value.getArrayInitializedElts(); i < e; ++i) {
+      if (isValueNonZero(Value.getArrayInitializedElt(i)))
+        return true;
+    }
+    return false;
+  }
+  case APValue::Struct: {
+    for (unsigned i = 0, e = Value.getStructNumBases(); i < e; ++i) {
+      if (isValueNonZero(Value.getStructBase(i)))
+        return true;
+    }
+    for (unsigned i = 0, e = Value.getStructNumFields(); i < e; ++i) {
+      if (isValueNonZero(Value.getStructField(i)))
+        return true;
+    }
+    return false;
+  }
+  case APValue::Union:
+    return isValueNonZero(Value.getUnionValue());
+
+  // For other kinds we cannot tell and assume non-zero.
+  case APValue::LValue:
+    return false;
+  case APValue::MemberPointer:
+    return false;
+  case APValue::AddrLabelDiff:
+    return false;
+  }
+
+  llvm_unreachable("unhandled APValue kind");
+}
+
+static bool isExpressionNonZero(const Expr *E, Sema &S, const VarDecl &VD) {
+  APValue Result;
+  SmallVector<PartialDiagnosticAt, 2> Notes;
+  if (E->EvaluateAsInitializer(Result, S.Context, &VD, Notes))
+    return isValueNonZero(Result);
+
+  if (const auto *InitList = dyn_cast<InitListExpr>(E)) {
+    for (Stmt *Statement : *InitList) {
+      if (const auto *InitElt = dyn_cast<Expr>(Statement)) {
+          if (isExpressionNonZero(InitElt, S, VD))
+            return true;
+      } else
+        return false;
+    }
+    return false;
+  }
+  return false; // Expr E is neither evaluable initializer nor initializer list.
+}
+
+static void checkAttributeSectionBSS(Sema &S, VarDecl &VD) {
+  if (const auto *SA = VD.getAttr<SectionAttr>()) {
+    if (SA->getName().startswith(".bss")) {
+      if (const Expr *InitExpr = VD.getInit()) {
+        if (isExpressionNonZero(InitExpr, S, VD)) {
+          S.Diag(SA->getLocation(),
+                 diag::err_attribute_section_bss_nonzero)
+              << &VD << SA->getRange() << InitExpr->getSourceRange();
+          
+          VD.dropAttr<SectionAttr>();
+        }
+      }
+    }
+  }
+}
+
 static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
   // Ensure that an auto decl is deduced otherwise the checks below might cache
   // the wrong linkage.
@@ -5330,6 +5423,7 @@
         S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD;
         VD->dropAttr<AliasAttr>();
       }
+      checkAttributeSectionBSS(S, *VD);
     }
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2176,6 +2176,11 @@
   "argument to 'section' attribute is not valid for this target: %0">;
 def warn_mismatched_section : Warning<
   "section does not match previous declaration">, InGroup<Section>;
+def err_attribute_section_bss_nonzero : Error<
+  "variables placed in BSS section must be zero-initialized, but "
+  "%0 is initialized with a non-zero value">;
+def err_attribute_section_bss_function : Error<
+  "functions cannot be placed in BSS section">;
 
 def err_anonymous_property: Error<
   "anonymous property is not supported">;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to