serge-sans-paille updated this revision to Diff 545060.
serge-sans-paille added a comment.

Take reviewers comment into account.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156337/new/

https://reviews.llvm.org/D156337

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/attr-uninitialized.c
  clang/test/SemaCXX/constant-expression-cxx14.cpp
  clang/test/SemaCXX/constant-expression-cxx2a.cpp

Index: clang/test/SemaCXX/constant-expression-cxx2a.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1362,6 +1362,9 @@
   static_assert(&zti == &typeid(Y));
 }
 
+struct __attribute__((uninitialized)) j { int v; constexpr j() {}};
+static_assert(j().v == 0, ""); // expected-error {{constant expression}} expected-note {{read of uninitialized object is not allowed in a constant expression}}
+
 namespace PR45133 {
   struct A { long x; };
 
Index: clang/test/SemaCXX/constant-expression-cxx14.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -849,6 +849,13 @@
     ({ if (true) {} }); // expected-note {{not supported}}
     return 0;
   }
+
+  // Make sure the uninitialized attribute does not silent constant expression
+  // warnings.
+  constexpr int i() {
+    return ({ __attribute__((uninitialized)) int n; n; }); // expected-note {{read of uninitialized object}}
+  }
+  static_assert(i() == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
 }
 
 namespace VirtualFromBase {
Index: clang/test/Sema/attr-uninitialized.c
===================================================================
--- clang/test/Sema/attr-uninitialized.c
+++ clang/test/Sema/attr-uninitialized.c
@@ -18,4 +18,4 @@
 
 struct TheWordIsOut {
   __attribute((uninitialized)) int youre_doin_wrong; // expected-warning {{'uninitialized' attribute only applies to local variables}}
-} __attribute((uninitialized));                      // expected-warning {{'uninitialized' attribute only applies to local variables}}
+} __attribute((uninitialized));
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -188,7 +188,7 @@
 // CHECK-NEXT: TargetVersion (SubjectMatchRule_function)
 // CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member)
 // CHECK-NEXT: TrivialABI (SubjectMatchRule_record)
-// CHECK-NEXT: Uninitialized (SubjectMatchRule_variable_is_local)
+// CHECK-NEXT: Uninitialized (SubjectMatchRule_variable_is_local, SubjectMatchRule_record)
 // CHECK-NEXT: UnsafeBufferUsage (SubjectMatchRule_function)
 // CHECK-NEXT: UseHandle (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: VecReturn (SubjectMatchRule_record)
Index: clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp
===================================================================
--- clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp
+++ clang/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp
@@ -38,4 +38,24 @@
 }
 #pragma clang attribute pop
 
+struct [[clang::uninitialized]] uninitialized_record {
+  int i;
+};
+
+// UNINIT-LABEL:  test_record_attribute_uninitialized(
+// UNINIT:      alloca
+// UNINIT-NEXT: call void
+// ZERO-LABEL:    test_record_attribute_uninitialized(
+// ZERO:      alloca
+// ZERO-NOT:  !annotation
+// ZERO-NEXT: call void
+// PATTERN-LABEL: test_record_attribute_uninitialized(
+// PATTERN:      alloca
+// PATTERN-NOT:  !annotation
+// PATTERN-NEXT: call void
+void test_record_attribute_uninitialized() {
+  uninitialized_record some;
+  used(some);
+}
+
 } // extern "C"
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -8438,8 +8438,10 @@
 }
 
 static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic &&
-         "uninitialized is only valid on automatic duration variables");
+  assert((isa<RecordDecl>(D) ||
+          (cast<VarDecl>(D)->getStorageDuration() == SD_Automatic)) &&
+         "uninitialized is only valid on automatic duration variables and "
+         "record type");
   D->addAttr(::new (S.Context) UninitializedAttr(S.Context, AL));
 }
 
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -1902,13 +1902,17 @@
   const Address Loc =
       locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr;
 
-  // Note: constexpr already initializes everything correctly.
-  LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
-      (D.isConstexpr()
-           ? LangOptions::TrivialAutoVarInitKind::Uninitialized
-           : (D.getAttr<UninitializedAttr>()
-                  ? LangOptions::TrivialAutoVarInitKind::Uninitialized
-                  : getContext().getLangOpts().getTrivialAutoVarInit()));
+  LangOptions::TrivialAutoVarInitKind trivialAutoVarInit;
+  if (D.isConstexpr()) {
+    // Note: constexpr already initializes everything correctly.
+    trivialAutoVarInit = LangOptions::TrivialAutoVarInitKind::Uninitialized;
+  } else if (D.hasAttr<UninitializedAttr>())
+    trivialAutoVarInit = LangOptions::TrivialAutoVarInitKind::Uninitialized;
+  else if (const auto *RecordTy = D.getType()->getAsRecordDecl();
+           RecordTy && RecordTy->hasAttr<UnusedAttr>())
+    trivialAutoVarInit = LangOptions::TrivialAutoVarInitKind::Uninitialized;
+  else
+    trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit();
 
   auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) {
     if (trivialAutoVarInit ==
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -5782,8 +5782,10 @@
 The command-line parameter ``-ftrivial-auto-var-init=*`` can be used to
 initialize trivial automatic stack variables. By default, trivial automatic
 stack variables are uninitialized. This attribute is used to override the
-command-line parameter, forcing variables to remain uninitialized. It has no
-semantic meaning in that using uninitialized values is undefined behavior,
+command-line parameter, forcing variables to remain uninitialized.
+When set on a struct or class, all stack variables of this type are affected.
+
+It has no semantic meaning in that using uninitialized values is undefined behavior,
 it rather documents the programmer's intent.
   }];
 }
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3960,7 +3960,7 @@
 
 def Uninitialized : InheritableAttr {
   let Spellings = [Clang<"uninitialized", 0>];
-  let Subjects = SubjectList<[LocalVar]>;
+  let Subjects = SubjectList<[LocalVar, Record]>;
   let PragmaAttributeSupport = 1;
   let Documentation = [UninitializedDocs];
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to