[clang] 0cb6c41 - Revert "Diagnose problematic uses of constructor/destructor attribute (#67673)"

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 11 05:31:48 PDT 2023


Author: Aaron Ballman
Date: 2023-10-11T08:31:13-04:00
New Revision: 0cb6c413b1883a18341a428bb9179fa31cd6e4e3

URL: https://github.com/llvm/llvm-project/commit/0cb6c413b1883a18341a428bb9179fa31cd6e4e3
DIFF: https://github.com/llvm/llvm-project/commit/0cb6c413b1883a18341a428bb9179fa31cd6e4e3.diff

LOG: Revert "Diagnose problematic uses of constructor/destructor attribute (#67673)"

This reverts commit a633a3761fcbd0799426cbf5fbd7794961080e43.

Still breaking compiler-rt bots:
https://lab.llvm.org/buildbot/#/builders/109/builds/75360

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/AttrDocs.td
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/test/CodeGen/PowerPC/aix-destructor-attribute.c
    clang/test/CodeGenCXX/aix-destructor-attribute.cpp
    clang/test/Sema/constructor-attribute.c
    compiler-rt/CMakeLists.txt
    compiler-rt/cmake/config-ix.cmake
    compiler-rt/test/profile/Posix/gcov-destructor.c
    compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp

Removed: 
    clang/test/Sema/constructor-attribute-diag-group.c


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 530dbe55fcb1362..2d918967e7f0b02 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -217,11 +217,6 @@ Attribute Changes in Clang
   automatic diagnostic to use parameters of types that the format style
   supports but that are never the result of default argument promotion, such as
   ``float``. (`#59824: <https://github.com/llvm/llvm-project/issues/59824>`_)
-- The ``constructor`` and ``destructor`` attributes now diagnose when:
-  - the priority is not between 101 and 65535, inclusive,
-  - the function it is applied to accepts arguments or has a non-void return
-    type, or
-  - the function it is applied to is a non-static member function (C++).
 
 Improvements to Clang's diagnostics
 -----------------------------------

diff  --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index eb4ccc6fb9389d4..8d928dcc146b254 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7255,14 +7255,8 @@ after returning from ``main()`` or when the ``exit()`` function has been
 called. Note, ``quick_exit()``, ``_Exit()``, and ``abort()`` prevent a function
 marked ``destructor`` from being called.
 
-In general, the constructor or destructor function must use the C calling
-convention, cannot accept any arguments, and its return type should be
-``void``, ``int``, or ``unsigned int``. The latter two types are supported for
-historical reasons. On targets with a GNU environment (one which uses glibc),
-the signature of the function can also be the same as that of ``main()``.
-
-In C++ language modes, the function cannot be marked ``consteval``, nor can it
-be a non-static member function.
+The constructor or destructor function should not accept any arguments and its
+return type should be ``void``.
 
 The attributes accept an optional argument used to specify the priority order
 in which to execute constructor and destructor functions. The priority is

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index e017ca45aeeeb67..0b09c002191848a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -105,10 +105,6 @@ def EnumConversion : DiagGroup<"enum-conversion",
                                [EnumEnumConversion,
                                 EnumFloatConversion,
                                 EnumCompareConditional]>;
-def InvalidPriority : DiagGroup<"priority-ctor-dtor">;
-// For compatibility with GCC.
-def : DiagGroup<"prio-ctor-dtor", [InvalidPriority]>;
-
 def ObjCSignedCharBoolImplicitIntConversion :
   DiagGroup<"objc-signed-char-bool-implicit-int-conversion">;
 def ImplicitIntConversion : DiagGroup<"implicit-int-conversion",

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cce4601770a7ecc..c1a6e3831127e56 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2870,8 +2870,6 @@ def warn_cxx11_compat_constexpr_body_multiple_return : Warning<
   InGroup<CXXPre14Compat>, DefaultIgnore;
 def note_constexpr_body_previous_return : Note<
   "previous return statement is here">;
-def err_ctordtor_attr_consteval : Error<
-  "%0 attribute cannot be applied to a 'consteval' function">;
 
 // C++20 function try blocks in constexpr
 def ext_constexpr_function_try_block_cxx20 : ExtWarn<
@@ -3184,13 +3182,6 @@ def err_alignas_underaligned : Error<
   "requested alignment is less than minimum alignment of %1 for type %0">;
 def warn_aligned_attr_underaligned : Warning<err_alignas_underaligned.Summary>,
   InGroup<IgnoredAttributes>;
-def err_ctor_dtor_attr_on_non_void_func : Error<
-  "%0 attribute can only be applied to a function which accepts no arguments "
-  "and has a 'void' or 'int' return type">;
-def err_ctor_dtor_member_func : Error<
-  "%0 attribute cannot be applied to a member function">;
-def err_ctor_dtor_calling_conv : Error<
-  "%0 attribute must be applied to a function with the C calling convention">;
 def err_attribute_sizeless_type : Error<
   "%0 attribute cannot be applied to sizeless type %1">;
 def err_attribute_argument_n_type : Error<
@@ -3204,9 +3195,6 @@ def err_attribute_argument_out_of_range : Error<
 def err_init_priority_object_attr : Error<
   "can only use 'init_priority' attribute on file-scope definitions "
   "of objects of class type">;
-def warn_priority_out_of_range : Warning<
-  err_attribute_argument_out_of_range.Summary>,
-  InGroup<InvalidPriority>, DefaultError;
 def err_attribute_argument_out_of_bounds : Error<
   "%0 attribute parameter %1 is out of bounds">;
 def err_attribute_only_once_per_parameter : Error<

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 964fcd6c6b15f5d..ed0b4d29b056397 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2352,126 +2352,26 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL));
 }
 
-static void diagnoseInvalidPriority(Sema &S, uint32_t Priority,
-                                    const ParsedAttr &A,
-                                    SourceLocation PriorityLoc) {
-  constexpr uint32_t ReservedPriorityLower = 101, ReservedPriorityUpper = 65535;
-
-  // Only perform the priority check if the attribute is outside of a system
-  // header. Values <= 100 are reserved for the implementation, and libc++
-  // benefits from being able to specify values in that range. Values > 65535
-  // are reserved for historical reasons.
-  if ((Priority < ReservedPriorityLower || Priority > ReservedPriorityUpper) &&
-      !S.getSourceManager().isInSystemHeader(A.getLoc())) {
-    S.Diag(A.getLoc(), diag::warn_priority_out_of_range)
-        << PriorityLoc << A << ReservedPriorityLower << ReservedPriorityUpper;
-  }
-}
-
-static bool FunctionParamsAreMainLike(ASTContext &Context,
-                                      const FunctionDecl *FD) {
-  assert(FD->hasPrototype() && "expected the function to have a prototype");
-  const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
-  QualType CharPP =
-      Context.getPointerType(Context.getPointerType(Context.CharTy));
-  QualType Expected[] = {Context.IntTy, CharPP, CharPP, CharPP};
-  for (unsigned I = 0;
-       I < sizeof(Expected) / sizeof(QualType) && I < FPT->getNumParams();
-       ++I) {
-    QualType AT = FPT->getParamType(I);
-
-    if (!Context.hasSameUnqualifiedType(AT, Expected[I])) {
-      if (Expected[I] == CharPP) {
-        // As an extension, the following forms are okay:
-        //   char const **
-        //   char const * const *
-        //   char * const *
-
-        QualifierCollector Qs;
-        const PointerType *PT;
-        if ((PT = Qs.strip(AT)->getAs<PointerType>()) &&
-            (PT = Qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
-            Context.hasSameType(QualType(Qs.strip(PT->getPointeeType()), 0),
-                                Context.CharTy)) {
-          Qs.removeConst();
-          if (!Qs.empty())
-            return false;
-          continue; // Accepted as an extension.
-        }
-      }
-      return false;
-    }
-  }
-  return true;
-}
-
-template <typename CtorDtorAttr>
-static void handleCtorDtorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  uint32_t Priority = CtorDtorAttr::DefaultPriority;
+static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  uint32_t priority = ConstructorAttr::DefaultPriority;
   if (S.getLangOpts().HLSL && AL.getNumArgs()) {
     S.Diag(AL.getLoc(), diag::err_hlsl_init_priority_unsupported);
     return;
   }
+  if (AL.getNumArgs() &&
+      !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
+    return;
 
-  // If we're given an argument for the priority, check that it's valid.
-  if (AL.getNumArgs()) {
-    if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Priority))
-      return;
-
-    // Diagnose an invalid priority, but continue to process the attribute.
-    diagnoseInvalidPriority(S, Priority, AL, AL.getArgAsExpr(0)->getExprLoc());
-  }
+  D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority));
+}
 
-  // Ensure the function we're attaching to is something that is sensible to
-  // automatically call before or after main(); it should accept no arguments.
-  // In theory, a void return type is the only truly safe return type (consider
-  // that calling conventions may place returned values in a hidden pointer
-  // argument passed to the function that will not be present when called
-  // automatically). However, there is a significant amount of existing code
-  // which uses an int return type. So we will accept void, int, and
-  // unsigned int return types. Any other return type, or a non-void parameter
-  // list is treated as an error because it's a form of type system
-  // incompatibility. The function also cannot be a member function. We allow
-  // K&R C functions because that's a 
diff icult edge case where it depends on
-  // how the function is defined as to whether it does or does not expect
-  // arguments.
-  //
-  // However! glibc on ELF will pass the same arguments to a constructor
-  // function as are given to main(), so we will allow `int, char *[]` and
-  // `int, char *[], char *[]` (or qualified versions thereof), but only if
-  // the target is explicitly for glibc.
-  const auto *FD = cast<FunctionDecl>(D);
-  QualType RetTy = FD->getReturnType();
-  bool IsGlibC = S.Context.getTargetInfo().getTriple().isGNUEnvironment();
-  if (!(RetTy->isVoidType() ||
-        RetTy->isSpecificBuiltinType(BuiltinType::UInt) ||
-        RetTy->isSpecificBuiltinType(BuiltinType::Int)) ||
-      FD->isVariadic() ||
-      (FD->hasPrototype() &&
-       ((!IsGlibC && FD->getNumParams() != 0) ||
-        (IsGlibC && !FunctionParamsAreMainLike(S.Context, FD))))) {
-    S.Diag(AL.getLoc(), diag::err_ctor_dtor_attr_on_non_void_func)
-        << AL << FD->getSourceRange();
-    return;
-  }
-  if (FD->getType()->castAs<FunctionType>()->getCallConv() !=
-      CallingConv::CC_C) {
-    S.Diag(AL.getLoc(), diag::err_ctor_dtor_calling_conv)
-        << AL << FD->getSourceRange();
-    return;
-  }
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD); MD && MD->isInstance()) {
-    S.Diag(AL.getLoc(), diag::err_ctor_dtor_member_func)
-        << AL << FD->getSourceRange();
-    return;
-  }
-  if (FD->isConsteval()) {
-    S.Diag(AL.getLoc(), diag::err_ctordtor_attr_consteval)
-        << AL << FD->getSourceRange();
+static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  uint32_t priority = DestructorAttr::DefaultPriority;
+  if (AL.getNumArgs() &&
+      !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
     return;
-  }
 
-  D->addAttr(CtorDtorAttr::Create(S.Context, Priority, AL));
+  D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority));
 }
 
 template <typename AttrTy>
@@ -3988,9 +3888,16 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     return;
   }
 
-  // Diagnose an invalid priority, but continue to process the attribute.
-  diagnoseInvalidPriority(S, prioritynum, AL, E->getExprLoc());
-
+  // Only perform the priority check if the attribute is outside of a system
+  // header. Values <= 100 are reserved for the implementation, and libc++
+  // benefits from being able to specify values in that range.
+  if ((prioritynum < 101 || prioritynum > 65535) &&
+      !S.getSourceManager().isInSystemHeader(AL.getLoc())) {
+    S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
+        << E->getSourceRange() << AL << 101 << 65535;
+    AL.setInvalid();
+    return;
+  }
   D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum));
 }
 
@@ -9052,13 +8959,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
     handlePassObjectSizeAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Constructor:
-    handleCtorDtorAttr<ConstructorAttr>(S, D, AL);
+      handleConstructorAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Deprecated:
     handleDeprecatedAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Destructor:
-    handleCtorDtorAttr<DestructorAttr>(S, D, AL);
+      handleDestructorAttr(S, D, AL);
     break;
   case ParsedAttr::AT_EnableIf:
     handleEnableIfAttr(S, D, AL);

diff  --git a/clang/test/CodeGen/PowerPC/aix-destructor-attribute.c b/clang/test/CodeGen/PowerPC/aix-destructor-attribute.c
index f0d83d161be50bd..cfb1fd7b0171a41 100644
--- a/clang/test/CodeGen/PowerPC/aix-destructor-attribute.c
+++ b/clang/test/CodeGen/PowerPC/aix-destructor-attribute.c
@@ -12,8 +12,9 @@
 // RUN:     -fno-use-cxa-atexit -fregister-global-dtors-with-atexit < %s | \
 // RUN:   FileCheck --check-prefix=REGISTER %s
 
-int bar(void) __attribute__((destructor(101)));
+int bar(void) __attribute__((destructor(100)));
 int bar2(void) __attribute__((destructor(65535)));
+int bar3(int) __attribute__((destructor(65535)));
 
 int bar(void) {
   return 1;
@@ -23,12 +24,16 @@ int bar2(void) {
   return 2;
 }
 
-// NO-REGISTER: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @bar, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @bar2, ptr null }]
+int bar3(int a) {
+  return a;
+}
+
+// NO-REGISTER: @llvm.global_dtors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 100, ptr @bar, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @bar2, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @bar3, ptr null }]
 
-// REGISTER: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @__GLOBAL_init_101, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_init_65535, ptr null }]
-// REGISTER: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @__GLOBAL_cleanup_101, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_cleanup_65535, ptr null }]
+// REGISTER: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 100, ptr @__GLOBAL_init_100, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_init_65535, ptr null }]
+// REGISTER: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 100, ptr @__GLOBAL_cleanup_100, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_cleanup_65535, ptr null }]
 
-// REGISTER: define internal void @__GLOBAL_init_101() [[ATTR:#[0-9]+]] {
+// REGISTER: define internal void @__GLOBAL_init_100() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
 // REGISTER:   %0 = call i32 @atexit(ptr @bar)
 // REGISTER:   ret void
@@ -37,10 +42,11 @@ int bar2(void) {
 // REGISTER: define internal void @__GLOBAL_init_65535() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
 // REGISTER:   %0 = call i32 @atexit(ptr @bar2)
+// REGISTER:   %1 = call i32 @atexit(ptr @bar3)
 // REGISTER:   ret void
 // REGISTER: }
 
-// REGISTER: define internal void @__GLOBAL_cleanup_101() [[ATTR:#[0-9]+]] {
+// REGISTER: define internal void @__GLOBAL_cleanup_100() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
 // REGISTER:   %0 = call i32 @unatexit(ptr @bar)
 // REGISTER:   %needs_destruct = icmp eq i32 %0, 0
@@ -56,11 +62,20 @@ int bar2(void) {
 
 // REGISTER: define internal void @__GLOBAL_cleanup_65535() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
-// REGISTER:   %0 = call i32 @unatexit(ptr @bar2)
+// REGISTER:   %0 = call i32 @unatexit(ptr @bar3)
 // REGISTER:   %needs_destruct = icmp eq i32 %0, 0
-// REGISTER:   br i1 %needs_destruct, label %destruct.call, label %destruct.end
+// REGISTER:   br i1 %needs_destruct, label %destruct.call, label %unatexit.call
 
 // REGISTER: destruct.call:
+// REGISTER:   call void @bar3()
+// REGISTER:   br label %unatexit.call
+
+// REGISTER: unatexit.call:
+// REGISTER:   %1 = call i32 @unatexit(ptr @bar2)
+// REGISTER:   %needs_destruct1 = icmp eq i32 %1, 0
+// REGISTER:   br i1 %needs_destruct1, label %destruct.call2, label %destruct.end
+
+// REGISTER: destruct.call2:
 // REGISTER:   call void @bar2()
 // REGISTER:   br label %destruct.end
 

diff  --git a/clang/test/CodeGenCXX/aix-destructor-attribute.cpp b/clang/test/CodeGenCXX/aix-destructor-attribute.cpp
index 2cdf147af8d07f1..5ebea7a997c9db1 100644
--- a/clang/test/CodeGenCXX/aix-destructor-attribute.cpp
+++ b/clang/test/CodeGenCXX/aix-destructor-attribute.cpp
@@ -17,8 +17,9 @@ struct test {
   ~test();
 } t;
 
-int bar() __attribute__((destructor(101)));
+int bar() __attribute__((destructor(100)));
 int bar2() __attribute__((destructor(65535)));
+int bar3(int) __attribute__((destructor(65535)));
 
 int bar() {
   return 1;
@@ -28,13 +29,17 @@ int bar2() {
   return 2;
 }
 
+int bar3(int a) {
+  return a;
+}
+
 // NO-REGISTER: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }]
-// NO-REGISTER: @llvm.global_dtors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @_Z3barv, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_Z4bar2v, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }]
+// NO-REGISTER: @llvm.global_dtors = appending global [4 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 100, ptr @_Z3barv, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_Z4bar2v, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_Z4bar3i, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }]
 
-// REGISTER: @llvm.global_ctors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }, { i32, ptr, ptr } { i32 101, ptr @__GLOBAL_init_101, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_init_65535, ptr null }]
-// REGISTER: @llvm.global_dtors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }, { i32, ptr, ptr } { i32 101, ptr @__GLOBAL_cleanup_101, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_cleanup_65535, ptr null }]
+// REGISTER: @llvm.global_ctors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I__, ptr null }, { i32, ptr, ptr } { i32 100, ptr @__GLOBAL_init_100, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_init_65535, ptr null }]
+// REGISTER: @llvm.global_dtors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__D_a, ptr null }, { i32, ptr, ptr } { i32 100, ptr @__GLOBAL_cleanup_100, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__GLOBAL_cleanup_65535, ptr null }]
 
-// REGISTER: define internal void @__GLOBAL_init_101() [[ATTR:#[0-9]+]] {
+// REGISTER: define internal void @__GLOBAL_init_100() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
 // REGISTER:   %0 = call i32 @atexit(ptr @_Z3barv)
 // REGISTER:   ret void
@@ -43,10 +48,11 @@ int bar2() {
 // REGISTER: define internal void @__GLOBAL_init_65535() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
 // REGISTER:   %0 = call i32 @atexit(ptr @_Z4bar2v)
+// REGISTER:   %1 = call i32 @atexit(ptr @_Z4bar3i)
 // REGISTER:   ret void
 // REGISTER: }
 
-// REGISTER: define internal void @__GLOBAL_cleanup_101() [[ATTR:#[0-9]+]] {
+// REGISTER: define internal void @__GLOBAL_cleanup_100() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
 // REGISTER:   %0 = call i32 @unatexit(ptr @_Z3barv)
 // REGISTER:   %needs_destruct = icmp eq i32 %0, 0
@@ -62,11 +68,20 @@ int bar2() {
 
 // REGISTER: define internal void @__GLOBAL_cleanup_65535() [[ATTR:#[0-9]+]] {
 // REGISTER: entry:
-// REGISTER:   %0 = call i32 @unatexit(ptr @_Z4bar2v)
+// REGISTER:   %0 = call i32 @unatexit(ptr @_Z4bar3i)
 // REGISTER:   %needs_destruct = icmp eq i32 %0, 0
-// REGISTER:   br i1 %needs_destruct, label %destruct.call, label %destruct.end
+// REGISTER:   br i1 %needs_destruct, label %destruct.call, label %unatexit.call
 
 // REGISTER: destruct.call:
+// REGISTER:   call void @_Z4bar3i()
+// REGISTER:   br label %unatexit.call
+
+// REGISTER: unatexit.call:
+// REGISTER:   %1 = call i32 @unatexit(ptr @_Z4bar2v)
+// REGISTER:   %needs_destruct1 = icmp eq i32 %1, 0
+// REGISTER:   br i1 %needs_destruct1, label %destruct.call2, label %destruct.end
+
+// REGISTER: destruct.call2:
 // REGISTER:   call void @_Z4bar2v()
 // REGISTER:   br label %destruct.end
 

diff  --git a/clang/test/Sema/constructor-attribute-diag-group.c b/clang/test/Sema/constructor-attribute-diag-group.c
deleted file mode 100644
index e1828d62d28b754..000000000000000
--- a/clang/test/Sema/constructor-attribute-diag-group.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=err %s
-// RUN: %clang_cc1 -fsyntax-only -verify=warn -Wno-error=priority-ctor-dtor %s
-// RUN: %clang_cc1 -fsyntax-only -verify=okay -Wno-priority-ctor-dtor %s
-// RUN: %clang_cc1 -fsyntax-only -verify=okay -Wno-prio-ctor-dtor %s
-// okay-no-diagnostics
-
-void f(void) __attribute__((constructor(1)));   // warn-warning {{'constructor' attribute requires integer constant between 101 and 65535 inclusive}} \
-                                                   err-error {{'constructor' attribute requires integer constant between 101 and 65535 inclusive}}
-void f(void) __attribute__((destructor(1)));    // warn-warning {{'destructor' attribute requires integer constant between 101 and 65535 inclusive}} \
-                                                   err-error {{'destructor' attribute requires integer constant between 101 and 65535 inclusive}}

diff  --git a/clang/test/Sema/constructor-attribute.c b/clang/test/Sema/constructor-attribute.c
index d29be13f68f89db..2317c7735bda586 100644
--- a/clang/test/Sema/constructor-attribute.c
+++ b/clang/test/Sema/constructor-attribute.c
@@ -1,75 +1,16 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-musl -fsyntax-only -verify=expected,nonglibc -Wno-strict-prototypes %s
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -Wno-strict-prototypes %s
-// RUN: %clang_cc1 -triple x86_64-pc-linux-musl -fsyntax-only -verify=expected,nonglibc -x c++ -std=c++20 %s
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -x c++ -std=c++20 %s
-
-int x1 __attribute__((constructor)); // expected-warning {{'constructor' attribute only applies to functions}}
-void f(void) __attribute__((constructor));
-void f(void) __attribute__((constructor(1)));   // expected-error {{'constructor' attribute requires integer constant between 101 and 65535 inclusive}}
-void f(void) __attribute__((constructor(1,2))); // expected-error {{'constructor' attribute takes no more than 1 argument}}
-void f(void) __attribute__((constructor(1.0))); // expected-error {{'constructor' attribute requires an integer constant}}
-void f(void) __attribute__((constructor(0x100000000))); // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
-void f(void) __attribute__((constructor(101)));
-
-int x2 __attribute__((destructor)); // expected-warning {{'destructor' attribute only applies to functions}}
-void f(void) __attribute__((destructor));
-void f(void) __attribute__((destructor(1)));   // expected-error {{'destructor' attribute requires integer constant between 101 and 65535 inclusive}}
-void f(void) __attribute__((destructor(1,2))); // expected-error {{'destructor' attribute takes no more than 1 argument}}
-void f(void) __attribute__((destructor(1.0))); // expected-error {{'destructor' attribute requires an integer constant}}
-void f(void) __attribute__((destructor(101)));
-
-void knr1() __attribute__((constructor));
-void knr2() __attribute__((destructor));
-
-// Require a void or (unsigned) int return type
-int g0(void) __attribute__((constructor));
-signed int g1(void) __attribute__((constructor));
-float g2(void) __attribute__((constructor)); // expected-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-int h0(void) __attribute__((destructor));
-unsigned int h1(void) __attribute__((destructor));
-float h2(void) __attribute__((destructor));  // expected-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-
-// In glibc environments, allow main-like signatures, but otherwise disallow
-// any parameters.
-void i1(int v) __attribute__((constructor)); // nonglibc-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void j1(int v) __attribute__((destructor));  // nonglibc-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void i2(int argc, char *argv[]) __attribute__((constructor)); // nonglibc-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void j2(int argc, char *argv[]) __attribute__((destructor));  // nonglibc-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void i3(int argc, char *const argv[], char *environ[]) __attribute__((constructor)); // nonglibc-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void j3(int argc, const char *argv[], char *environ[]) __attribute__((destructor));  // nonglibc-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void i4(int argc, float f) __attribute__((constructor)); // expected-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-void j4(int argc, float f) __attribute__((destructor));  // expected-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-
-// Disallow calling conventions other than the C calling convention
-__attribute__((regcall, constructor)) void k(void); // expected-error {{'constructor' attribute must be applied to a function with the C calling convention}}
-
-#ifdef __cplusplus
-// Disallow variadic functions.
-__attribute__((constructor)) void g1(...); // expected-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-__attribute__((destructor)) void g2(...);  // expected-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-
-struct S {
-  // Not allowed on a nonstatic member function, but is allowed on a static
-  // member function so long as it has no args/void return type.
-  void mem1() __attribute__((constructor)); // expected-error {{'constructor' attribute cannot be applied to a member function}}
-  void mem2() __attribute__((destructor));  // expected-error {{'destructor' attribute cannot be applied to a member function}}
-
-  static signed nonmem1() __attribute__((constructor));
-  static unsigned nonmem2() __attribute__((destructor));
-
-  static _BitInt(32) nonmem3() __attribute__((constructor)); // expected-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-  static char nonmem4() __attribute__((destructor));         // expected-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-
-  static void nonmem5(int) __attribute__((constructor)); // nonglibc-error {{'constructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-  static void nonmem6(int) __attribute__((destructor));  // nonglibc-error {{'destructor' attribute can only be applied to a function which accepts no arguments and has a 'void' or 'int' return type}}
-};
-
-consteval void consteval_func1() __attribute__((constructor)); // expected-error {{'constructor' attribute cannot be applied to a 'consteval' function}}
-consteval void consteval_func2() __attribute__((destructor));  // expected-error {{'destructor' attribute cannot be applied to a 'consteval' function}}
-#endif // __cplusplus
-
-# 1 "source.c" 1 3
-// Can use reserved priorities within a system header
-void f(void) __attribute__((constructor(1)));
-void f(void) __attribute__((destructor(1)));
-# 1 "source.c" 2
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-strict-prototypes %s
+
+int x __attribute__((constructor)); // expected-warning {{'constructor' attribute only applies to functions}}
+int f(void) __attribute__((constructor));
+int f(void) __attribute__((constructor(1)));
+int f(void) __attribute__((constructor(1,2))); // expected-error {{'constructor' attribute takes no more than 1 argument}}
+int f(void) __attribute__((constructor(1.0))); // expected-error {{'constructor' attribute requires an integer constant}}
+int f(void) __attribute__((constructor(0x100000000))); // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+
+int x __attribute__((destructor)); // expected-warning {{'destructor' attribute only applies to functions}}
+int f(void) __attribute__((destructor));
+int f(void) __attribute__((destructor(1)));
+int f(void) __attribute__((destructor(1,2))); // expected-error {{'destructor' attribute takes no more than 1 argument}}
+int f(void) __attribute__((destructor(1.0))); // expected-error {{'destructor' attribute requires an integer constant}}
+
+void knr() __attribute__((constructor));

diff  --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 2e4b2c7070bb91f..1a46f5b33480694 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -480,7 +480,6 @@ endif()
 append_list_if(COMPILER_RT_HAS_WGNU_FLAG -Wno-gnu SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG -Wno-c99-extensions SANITIZER_COMMON_CFLAGS)
-append_list_if(COMPILER_RT_HAS_WPRIO_CTOR_DTOR_FLAG -Wno-prio-ctor-dtor SANITIZER_COMMON_CFLAGS)
 # format-pedantic warns about passing T* for %p, which is not useful.
 append_list_if(COMPILER_RT_HAS_WD4146_FLAG /wd4146 SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS)

diff  --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 9ec08f8e99ea2fe..a8e078f1ebc9888 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -137,7 +137,7 @@ check_cxx_compiler_flag("-Werror -Wthread-safety-beta" COMPILER_RT_HAS_WTHREAD_S
 check_cxx_compiler_flag(-Wno-pedantic COMPILER_RT_HAS_WNO_PEDANTIC)
 check_cxx_compiler_flag(-Wno-format COMPILER_RT_HAS_WNO_FORMAT)
 check_cxx_compiler_flag(-Wno-format-pedantic COMPILER_RT_HAS_WNO_FORMAT_PEDANTIC)
-check_cxx_compiler_flag(-Wno-prio-ctor-dtor COMPILER_RT_HAS_WPRIO_CTOR_DTOR_FLAG)
+
 check_cxx_compiler_flag("/experimental:external /external:W0" COMPILER_RT_HAS_EXTERNAL_FLAG)
 
 check_cxx_compiler_flag(/W4 COMPILER_RT_HAS_W4_FLAG)

diff  --git a/compiler-rt/test/profile/Posix/gcov-destructor.c b/compiler-rt/test/profile/Posix/gcov-destructor.c
index ed4360636c1fcdb..bd1e0d2dde079b2 100644
--- a/compiler-rt/test/profile/Posix/gcov-destructor.c
+++ b/compiler-rt/test/profile/Posix/gcov-destructor.c
@@ -1,6 +1,6 @@
 /// Test that destructors and destructors whose priorities are greater than 100 are tracked.
 // RUN: mkdir -p %t.dir && cd %t.dir
-// RUN: %clang -Wno-prio-ctor-dtor --coverage %s -o %t -dumpdir ./
+// RUN: %clang --coverage %s -o %t -dumpdir ./
 // RUN: rm -f gcov-destructor.gcda && %run %t
 // RUN: llvm-cov gcov -t gcov-destructor.gcda | FileCheck %s
 // UNSUPPORTED: darwin

diff  --git a/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp b/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
index f89c14acca98de1..0ab65bd30d92cc8 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -fsanitize=undefined -Wno-prio-ctor-dtor -shared-libsan %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx -fsanitize=undefined -shared-libsan %s -o %t && %run %t 2>&1 | FileCheck %s
 
 // Ensure ubsan runtime/interceptors are lazily initialized if called early.
 


        


More information about the cfe-commits mailing list