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