]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Add -fimplicit-constexpr
authorJason Merrill <jason@redhat.com>
Wed, 13 Oct 2021 15:47:25 +0000 (11:47 -0400)
committerJason Merrill <jason@redhat.com>
Mon, 15 Nov 2021 23:50:07 +0000 (18:50 -0500)
With each successive C++ standard the restrictions on the use of the
constexpr keyword for functions get weaker and weaker; it recently occurred
to me that it is heading toward the same fate as the C register keyword,
which was once useful for optimization but became obsolete.  Similarly, it
seems to me that we should be able to just treat inlines as constexpr
functions and not make people add the extra keyword everywhere.

There were a lot of testcase changes needed; many disabling errors about
non-constexpr functions that are now constexpr, and many disabling implicit
constexpr so that the tests can check the same thing as before, whether
that's mangling or whatever.

gcc/c-family/ChangeLog:

* c.opt: Add -fimplicit-constexpr.
* c-cppbuiltin.c: Define __cpp_implicit_constexpr.
* c-opts.c (c_common_post_options): Disable below C++14.

gcc/cp/ChangeLog:

* cp-tree.h (struct lang_decl_fn): Add implicit_constexpr.
(decl_implicit_constexpr_p): New.
* class.c (type_maybe_constexpr_destructor): Use
TYPE_HAS_TRIVIAL_DESTRUCTOR and maybe_constexpr_fn.
(finalize_literal_type_property): Simplify.
* constexpr.c (is_valid_constexpr_fn): Check for dtor.
(maybe_save_constexpr_fundef): Try to set DECL_DECLARED_CONSTEXPR_P
on inlines.
(cxx_eval_call_expression): Use maybe_constexpr_fn.
(maybe_constexpr_fn): Handle flag_implicit_constexpr.
(var_in_maybe_constexpr_fn): Use maybe_constexpr_fn.
(potential_constant_expression_1): Likewise.
(decl_implicit_constexpr_p): New.
* decl.c (validate_constexpr_redeclaration): Allow change with
-fimplicit-constexpr.
(grok_special_member_properties): Use maybe_constexpr_fn.
* error.c (dump_function_decl): Don't print 'constexpr'
if it's implicit.
* Make-lang.in (check-c++-all): Update.

libstdc++-v3/ChangeLog:

* testsuite/20_util/to_address/1_neg.cc: Adjust error.
* testsuite/26_numerics/random/concept.cc: Adjust asserts.

gcc/testsuite/ChangeLog:

* lib/g++-dg.exp: Handle "impcx".
* lib/target-supports.exp
(check_effective_target_implicit_constexpr): New.
* g++.dg/abi/abi-tag16.C:
* g++.dg/abi/abi-tag18a.C:
* g++.dg/abi/guard4.C:
* g++.dg/abi/lambda-defarg1.C:
* g++.dg/abi/mangle26.C:
* g++.dg/cpp0x/constexpr-diag3.C:
* g++.dg/cpp0x/constexpr-ex1.C:
* g++.dg/cpp0x/constexpr-ice5.C:
* g++.dg/cpp0x/constexpr-incomplete2.C:
* g++.dg/cpp0x/constexpr-memfn1.C:
* g++.dg/cpp0x/constexpr-neg3.C:
* g++.dg/cpp0x/constexpr-specialization.C:
* g++.dg/cpp0x/inh-ctor19.C:
* g++.dg/cpp0x/inh-ctor30.C:
* g++.dg/cpp0x/lambda/lambda-mangle3.C:
* g++.dg/cpp0x/lambda/lambda-mangle5.C:
* g++.dg/cpp1y/auto-fn12.C:
* g++.dg/cpp1y/constexpr-loop5.C:
* g++.dg/cpp1z/constexpr-lambda7.C:
* g++.dg/cpp2a/constexpr-dtor3.C:
* g++.dg/cpp2a/constexpr-new13.C:
* g++.dg/cpp2a/constinit11.C:
* g++.dg/cpp2a/constinit12.C:
* g++.dg/cpp2a/constinit14.C:
* g++.dg/cpp2a/constinit15.C:
* g++.dg/cpp2a/spaceship-constexpr1.C:
* g++.dg/cpp2a/spaceship-eq3.C:
* g++.dg/cpp2a/udlit-class-nttp-neg2.C:
* g++.dg/debug/dwarf2/auto1.C:
* g++.dg/debug/dwarf2/cdtor-1.C:
* g++.dg/debug/dwarf2/lambda1.C:
* g++.dg/debug/dwarf2/pr54508.C:
* g++.dg/debug/dwarf2/pubnames-2.C:
* g++.dg/debug/dwarf2/pubnames-3.C:
* g++.dg/ext/is_literal_type3.C:
* g++.dg/ext/visibility/template7.C:
* g++.dg/gcov/gcov-12.C:
* g++.dg/gcov/gcov-2.C:
* g++.dg/ipa/devirt-35.C:
* g++.dg/ipa/devirt-36.C:
* g++.dg/ipa/devirt-37.C:
* g++.dg/ipa/devirt-44.C:
* g++.dg/ipa/imm-devirt-1.C:
* g++.dg/lookup/builtin5.C:
* g++.dg/lto/inline-crossmodule-1_0.C:
* g++.dg/modules/enum-1_a.C:
* g++.dg/modules/fn-inline-1_c.C:
* g++.dg/modules/pmf-1_b.C:
* g++.dg/modules/used-1_c.C:
* g++.dg/tls/thread_local11.C:
* g++.dg/tls/thread_local11a.C:
* g++.dg/tm/pr46653.C:
* g++.dg/ubsan/pr70035.C:
* g++.old-deja/g++.other/delete6.C:
* g++.dg/modules/pmf-1_a.H:
Adjust for implicit constexpr.

68 files changed:
gcc/c-family/c-cppbuiltin.c
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/cp/Make-lang.in
gcc/cp/class.c
gcc/cp/constexpr.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/error.c
gcc/testsuite/g++.dg/abi/abi-tag16.C
gcc/testsuite/g++.dg/abi/abi-tag18a.C
gcc/testsuite/g++.dg/abi/guard4.C
gcc/testsuite/g++.dg/abi/lambda-defarg1.C
gcc/testsuite/g++.dg/abi/mangle26.C
gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-neg3.C
gcc/testsuite/g++.dg/cpp0x/constexpr-specialization.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle3.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C
gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
gcc/testsuite/g++.dg/cpp1y/constexpr-loop5.C
gcc/testsuite/g++.dg/cpp1z/constexpr-lambda7.C
gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C
gcc/testsuite/g++.dg/cpp2a/constinit11.C
gcc/testsuite/g++.dg/cpp2a/constinit12.C
gcc/testsuite/g++.dg/cpp2a/constinit14.C
gcc/testsuite/g++.dg/cpp2a/constinit15.C
gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C
gcc/testsuite/g++.dg/debug/dwarf2/pr54508.C
gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C
gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C
gcc/testsuite/g++.dg/ext/is_literal_type3.C
gcc/testsuite/g++.dg/ext/visibility/template7.C
gcc/testsuite/g++.dg/gcov/gcov-12.C
gcc/testsuite/g++.dg/gcov/gcov-2.C
gcc/testsuite/g++.dg/ipa/devirt-35.C
gcc/testsuite/g++.dg/ipa/devirt-36.C
gcc/testsuite/g++.dg/ipa/devirt-37.C
gcc/testsuite/g++.dg/ipa/devirt-44.C
gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
gcc/testsuite/g++.dg/lookup/builtin5.C
gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
gcc/testsuite/g++.dg/modules/enum-1_a.C
gcc/testsuite/g++.dg/modules/fn-inline-1_c.C
gcc/testsuite/g++.dg/modules/pmf-1_a.H
gcc/testsuite/g++.dg/modules/pmf-1_b.C
gcc/testsuite/g++.dg/modules/used-1_c.C
gcc/testsuite/g++.dg/tls/thread_local11.C
gcc/testsuite/g++.dg/tls/thread_local11a.C
gcc/testsuite/g++.dg/tm/pr46653.C
gcc/testsuite/g++.dg/ubsan/pr70035.C
gcc/testsuite/g++.old-deja/g++.other/delete6.C
gcc/testsuite/lib/g++-dg.exp
gcc/testsuite/lib/target-supports.exp
libstdc++-v3/testsuite/20_util/to_address/1_neg.cc
libstdc++-v3/testsuite/26_numerics/random/concept.cc

index 60e9e05206289fe7ef2d7cf7096eb0581f28197d..eb34d5af004554396f301c53785fa80a672208d3 100644 (file)
@@ -1111,6 +1111,8 @@ c_cpp_builtins (cpp_reader *pfile)
       if (cxx_dialect >= cxx11 && strcmp (thread_model, "single") != 0)
        cpp_define (pfile, "__STDCPP_THREADS__=1");
 #endif
+      if (flag_implicit_constexpr)
+       cpp_define (pfile, "__cpp_implicit_constexpr=20211111L");
     }
   /* Note that we define this for C as well, so that we know if
      __attribute__((cleanup)) will interface with EH.  */
index 0225cba7a4bfbc0b67dc87738a8cdadeff0f8855..62f58295c119cd2ac8453c51c2fbbd1c824d364b 100644 (file)
@@ -1052,6 +1052,9 @@ c_common_post_options (const char **pfilename)
       && flag_strong_eval_order == -1)
     flag_strong_eval_order = (cxx_dialect >= cxx17 ? 2 : 1);
 
+  if (flag_implicit_constexpr && cxx_dialect < cxx14)
+    flag_implicit_constexpr = false;
+
   /* Global sized deallocation is new in C++14.  */
   if (flag_sized_deallocation == -1)
     flag_sized_deallocation = (cxx_dialect >= cxx14);
index 06457ac739e4ed7deeb49b2a208dc1c84cdae360..8a4cd634f77e71dec62c1023150270f61e38e0cf 100644 (file)
@@ -1712,6 +1712,10 @@ fimplement-inlines
 C++ ObjC++ Var(flag_implement_inlines) Init(1)
 Export functions even if they can be inlined.
 
+fimplicit-constexpr
+C++ ObjC++ Var(flag_implicit_constexpr)
+Make inline functions constexpr by default.
+
 fimplicit-inline-templates
 C++ ObjC++ Var(flag_implicit_inline_templates) Init(1)
 Emit implicit instantiations of inline templates.
index 84694249b873244eb598bfb6e7de7b64f2292561..de1fc0249e67d9a2af51fa39335768a598a078a8 100644 (file)
@@ -221,7 +221,7 @@ check-c++17:
 
 # Run the testsuite in all standard conformance levels.
 check-c++-all:
-       $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,2a,concepts" check-g++
+       $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,20,23,impcx" check-g++
 
 # Run the testsuite with garbage collection at every opportunity.
 check-g++-strict-gc:
index bf92300a1789c8e9187e0a855d31ba4f9358f23c..c30a44f039b2428063eba8fbba83459d94995894 100644 (file)
@@ -5547,10 +5547,16 @@ type_has_constexpr_destructor (tree t)
 static bool
 type_maybe_constexpr_destructor (tree t)
 {
+  /* Until C++20, only trivial destruction is constexpr.  */
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (t))
+    return true;
+  if (cxx_dialect < cxx20)
+    return false;
   if (CLASS_TYPE_P (t) && CLASSTYPE_LAZY_DESTRUCTOR (t))
     /* Assume it's constexpr.  */
     return true;
-  return type_has_constexpr_destructor (t);
+  tree fn = CLASSTYPE_DESTRUCTOR (t);
+  return (fn && maybe_constexpr_fn (fn));
 }
 
 /* Returns true iff class TYPE has a virtual destructor.  */
@@ -5823,8 +5829,7 @@ finalize_literal_type_property (tree t)
   if (cxx_dialect < cxx11)
     CLASSTYPE_LITERAL_P (t) = false;
   else if (CLASSTYPE_LITERAL_P (t)
-          && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
-          && (cxx_dialect < cxx20 || !type_maybe_constexpr_destructor (t)))
+          && !type_maybe_constexpr_destructor (t))
     CLASSTYPE_LITERAL_P (t) = false;
   else if (CLASSTYPE_LITERAL_P (t) && LAMBDA_TYPE_P (t))
     CLASSTYPE_LITERAL_P (t) = (cxx_dialect >= cxx17);
index c92db5d413c2d4d350f4c4f0ca24f82d52268dc0..69d9d3daeca7e651eb1c6469da944a75ae4c566c 100644 (file)
@@ -37,6 +37,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "cgraph.h"
 #include "opts.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)                                             \
@@ -220,6 +222,17 @@ is_valid_constexpr_fn (tree fun, bool complain)
        inform (DECL_SOURCE_LOCATION (fun),
                "lambdas are implicitly %<constexpr%> only in C++17 and later");
     }
+  else if (DECL_DESTRUCTOR_P (fun))
+    {
+      if (cxx_dialect < cxx20)
+       {
+         ret = false;
+         if (complain)
+           error_at (DECL_SOURCE_LOCATION (fun),
+                     "%<constexpr%> destructors only available"
+                     " with %<-std=c++20%> or %<-std=gnu++20%>");
+       }
+    }
   else if (!DECL_CONSTRUCTOR_P (fun))
     {
       tree rettype = TREE_TYPE (TREE_TYPE (fun));
@@ -865,12 +878,31 @@ void
 maybe_save_constexpr_fundef (tree fun)
 {
   if (processing_template_decl
-      || !DECL_DECLARED_CONSTEXPR_P (fun)
       || cp_function_chain->invalid_constexpr
       || (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun)))
     return;
 
-  bool complain = !DECL_GENERATED_P (fun);
+  /* With -fimplicit-constexpr, try to make inlines constexpr.  We'll
+     actually set DECL_DECLARED_CONSTEXPR_P below if the checks pass.  */
+  bool implicit = false;
+  if (flag_implicit_constexpr)
+    {
+      if (DECL_DELETING_DESTRUCTOR_P (fun)
+         && decl_implicit_constexpr_p (DECL_CLONED_FUNCTION (fun)))
+       /* Don't inherit implicit constexpr from the non-deleting
+          destructor.  */
+       DECL_DECLARED_CONSTEXPR_P (fun) = false;
+
+      if (!DECL_DECLARED_CONSTEXPR_P (fun)
+         && DECL_DECLARED_INLINE_P (fun)
+         && !lookup_attribute ("noinline", DECL_ATTRIBUTES (fun)))
+       implicit = true;
+    }
+
+  if (!DECL_DECLARED_CONSTEXPR_P (fun) && !implicit)
+    return;
+
+  bool complain = !DECL_GENERATED_P (fun) && !implicit;
 
   if (!is_valid_constexpr_fn (fun, complain))
     return;
@@ -878,7 +910,7 @@ maybe_save_constexpr_fundef (tree fun)
   tree massaged = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
   if (massaged == NULL_TREE || massaged == error_mark_node)
     {
-      if (!DECL_CONSTRUCTOR_P (fun))
+      if (!DECL_CONSTRUCTOR_P (fun) && complain)
        error ("body of %<constexpr%> function %qD not a return-statement",
               fun);
       return;
@@ -907,6 +939,21 @@ maybe_save_constexpr_fundef (tree fun)
   if (!potential && complain)
     return;
 
+  if (implicit)
+    {
+      if (potential)
+       {
+         DECL_DECLARED_CONSTEXPR_P (fun) = true;
+         DECL_LANG_SPECIFIC (fun)->u.fn.implicit_constexpr = true;
+         if (DECL_CONSTRUCTOR_P (fun))
+           TYPE_HAS_CONSTEXPR_CTOR (DECL_CONTEXT (fun)) = true;
+       }
+      else
+       /* Don't bother keeping the pre-generic body of unsuitable functions
+          not explicitly declared constexpr.  */
+       return;
+    }
+
   constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE};
   bool clear_ctx = false;
   if (DECL_RESULT (fun) && DECL_CONTEXT (DECL_RESULT (fun)) == NULL_TREE)
@@ -2404,7 +2451,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
                                           lval, non_constant_p, overflow_p);
   if (DECL_THUNK_P (fun))
     return cxx_eval_thunk_call (ctx, t, fun, lval, non_constant_p, overflow_p);
-  if (!DECL_DECLARED_CONSTEXPR_P (fun))
+  if (!maybe_constexpr_fn (fun))
     {
       if (TREE_CODE (t) == CALL_EXPR
          && cxx_replaceable_global_alloc_fn (fun)
@@ -5229,7 +5276,9 @@ bool
 maybe_constexpr_fn (tree t)
 {
   return (DECL_DECLARED_CONSTEXPR_P (t)
-         || (cxx_dialect >= cxx17 && LAMBDA_FUNCTION_P (t)));
+         || (cxx_dialect >= cxx17 && LAMBDA_FUNCTION_P (t))
+         || (flag_implicit_constexpr
+             && DECL_DECLARED_INLINE_P (STRIP_TEMPLATE (t))));
 }
 
 /* True if T was declared in a function that might be constexpr: either a
@@ -5238,11 +5287,8 @@ maybe_constexpr_fn (tree t)
 bool
 var_in_maybe_constexpr_fn (tree t)
 {
-  if (cxx_dialect >= cxx17
-      && DECL_FUNCTION_SCOPE_P (t)
-      && LAMBDA_FUNCTION_P (DECL_CONTEXT (t)))
-    return true;
-  return var_in_constexpr_fn (t);
+  return (DECL_FUNCTION_SCOPE_P (t)
+         && maybe_constexpr_fn (DECL_CONTEXT (t)));
 }
 
 /* We're assigning INIT to TARGET.  In do_build_copy_constructor and
@@ -8219,7 +8265,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
              {
                if (builtin_valid_in_constant_expr_p (fun))
                  return true;
-               if (!DECL_DECLARED_CONSTEXPR_P (fun)
+               if (!maybe_constexpr_fn (fun)
                    /* Allow any built-in function; if the expansion
                       isn't constant, we'll deal with that then.  */
                    && !fndecl_built_in_p (fun)
@@ -9257,6 +9303,23 @@ is_nondependent_static_init_expression (tree t)
          && !instantiation_dependent_expression_p (t));
 }
 
+/* True iff FN is an implicitly constexpr function.  */
+
+bool
+decl_implicit_constexpr_p (tree fn)
+{
+  if (!(flag_implicit_constexpr
+       && TREE_CODE (fn) == FUNCTION_DECL
+       && DECL_DECLARED_CONSTEXPR_P (fn)))
+    return false;
+
+  if (DECL_CLONED_FUNCTION_P (fn))
+    fn = DECL_CLONED_FUNCTION (fn);
+
+  return (DECL_LANG_SPECIFIC (fn)
+         && DECL_LANG_SPECIFIC (fn)->u.fn.implicit_constexpr);
+}
+
 /* Finalize constexpr processing after parsing.  */
 
 void
index f387b5036d27f7efd8eef0f7cc845b33618b035f..acc98c9c452a1aa063c8326fe7d9bddaf63910cf 100644 (file)
@@ -2868,8 +2868,9 @@ struct GTY(()) lang_decl_fn {
   unsigned immediate_fn_p : 1;
   unsigned maybe_deleted : 1;
   unsigned coroutine_p : 1;
+  unsigned implicit_constexpr : 1;
 
-  unsigned spare : 10;
+  unsigned spare : 9;
 
   /* 32-bits padding on 64-bit host.  */
 
@@ -8315,6 +8316,7 @@ extern vec<tree> cx_error_context               (void);
 extern tree fold_sizeof_expr                   (tree);
 extern void clear_cv_and_fold_caches           (void);
 extern tree unshare_constructor                        (tree CXX_MEM_STAT_INFO);
+extern bool decl_implicit_constexpr_p          (tree);
 
 /* An RAII sentinel used to restrict constexpr evaluation so that it
    doesn't do anything that causes extra DECL_UID generation.  */
index eed478199ea5833c45c29490d8a6c34b27a4612b..2ddf0e4a5247e78fdc90d44ea6f86d7ac6099102 100644 (file)
@@ -1290,6 +1290,12 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl)
     }
   if (TREE_CODE (old_decl) == FUNCTION_DECL)
     {
+      /* With -fimplicit-constexpr, ignore changes in the constexpr
+        keyword.  */
+      if (flag_implicit_constexpr
+         && (DECL_IMMEDIATE_FUNCTION_P (new_decl)
+             == DECL_IMMEDIATE_FUNCTION_P (old_decl)))
+       return true;
       if (fndecl_built_in_p (old_decl))
        {
          /* Hide a built-in declaration.  */
@@ -14863,7 +14869,7 @@ grok_special_member_properties (tree decl)
       if (is_list_ctor (decl))
        TYPE_HAS_LIST_CTOR (class_type) = 1;
 
-      if (DECL_DECLARED_CONSTEXPR_P (decl)
+      if (maybe_constexpr_fn (decl)
          && !ctor && !move_fn_p (decl))
        TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1;
     }
index 012a4ecddf44661f12d8df1d5e474614b5de3d39..872479369ab226ee97c1bf4990a9c6972a84c5d2 100644 (file)
@@ -1686,7 +1686,8 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
   exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
 
   /* Likewise for the constexpr specifier, in case t is a specialization.  */
-  constexpr_p = DECL_DECLARED_CONSTEXPR_P (t);
+  constexpr_p = (DECL_DECLARED_CONSTEXPR_P (t)
+                && !decl_implicit_constexpr_p (t));
 
   /* Pretty print template instantiations only.  */
   if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)
index d4fa142762a8cef0e57c0cad4828b22fcd8ed40d..3027d7906f51fb02a889b3f5ab95a4e8946bbdb4 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-options -Wabi=9 }
+// { dg-options "-Wabi=9 -fno-implicit-constexpr" }
 // { dg-final { scan-assembler "_ZGVZN1N1FEvE4NameB5cxx11" } }
 namespace std {
   __extension__ inline namespace __cxx11 __attribute__((abi_tag("cxx11"))) {
index 95e192ae6f4a0a1b715ce20f5160783f03b72566..c6fb1607a418c1c8eb526365b33a42b19d09bacf 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-skip-if "PR 70349" { hppa*-*-hpux* && { ! lp64 } } }
-// { dg-options -fabi-version=9 }
+// { dg-options "-fabi-version=9 -fno-implicit-constexpr" }
 // { dg-final { scan-assembler "_Z1fB7__test1v" } }
 // { dg-final { scan-assembler "_ZZ1fB7__test1vEN1T1gB7__test2Ev" } }
 // { dg-final { scan-assembler "_ZZZ1fB7__test1vEN1T1gEvE1x" } }
index 537c90524f3c55bf39faeb8b1a648d64b364c584..71e6744e3810d5c5ced91c7eb11c9bac3afc579d 100644 (file)
@@ -3,9 +3,10 @@
 
 namespace x {
   struct s {
-    s() {}
+    s();
     static int a;
   };
+  s::s() {}
   // { dg-final { scan-assembler {.weak[^\n]*_ZGVN1x1bE} } }
   struct s __attribute__((weak)) b = s();
 }
index 8c53858124069645d5b054315f5c47391ef27326..79e4fa64ac57245c6a483550ec683c40a3ac994d 100644 (file)
@@ -1,5 +1,6 @@
 // PR c++/91241
 // { dg-do compile { target c++11 } }
+// { dg-additional-options -fkeep-inline-functions }
 
 struct A {
   int *b(const int & = []() -> int { return 0; }(),
index 5d1609596b909ba28bdc0203865a58e6743ec6dc..2041d778b9a63638d34a72e63dc5ed6c821b7bed 100644 (file)
@@ -1,7 +1,7 @@
 // Test of std mangling
 
 // { dg-do compile }
-// { dg-options "-fno-inline" }
+// { dg-options "-fno-inline -fno-implicit-constexpr" }
 
 namespace std {
   struct A {
index 1c43569615c5f5fb81603e8604549a1d77756370..c167bb1d8bc1bb8787385de4b0a33b413ca40fe9 100644 (file)
@@ -13,7 +13,7 @@ int main()
 
 // --------------------
 
-struct complex                         // { dg-message "no .constexpr. constructor" }
+struct complex                         // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } }
 {
   complex(double r, double i) : re(r), im(i) { }
   constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } }
@@ -24,23 +24,23 @@ private:
   double im;
 };
 
-constexpr complex co1(0, 1);      // { dg-error "19:the type .const complex. of .constexpr. variable .co1. is not literal" }
-constexpr double dd2 = co1.real(); // { dg-error "|in .constexpr. expansion of " }
+constexpr complex co1(0, 1);      // { dg-error "19:the type .const complex. of .constexpr. variable .co1. is not literal" "" { target { ! implicit_constexpr } } }
+constexpr double dd2 = co1.real(); // { dg-error "|in .constexpr. expansion of " "" { target { ! implicit_constexpr } } }
 
 // --------------------
 
-struct base                   // { dg-message "no .constexpr. constructor" }
+struct base                   // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } }
 {
   int _M_i;
   base() : _M_i(5) { }
 };
 
-struct derived : public base   // { dg-message "base class" }
+struct derived : public base   // { dg-message "base class" "" { target { ! implicit_constexpr } } }
 {
-  constexpr derived(): base() { } // { dg-error "non-.constexpr. function" }
+  constexpr derived(): base() { } // { dg-error "non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 };
 
-constexpr derived obj;         // { dg-error "not literal" }
+constexpr derived obj;         // { dg-error "not literal" "" { target { ! implicit_constexpr } } }
 
 // --------------------
 
index e5e58bddab0b2fa8a37cd0395cb853a957250518..1d5c58b4090b1f1c55d647e8ea7b2c6f4101684b 100644 (file)
@@ -87,7 +87,7 @@ struct resource {
   }
 };
 constexpr resource f(resource d)
-{ return d; }                  // { dg-error "non-.constexpr." }
-constexpr resource d = f(9);   // { dg-message ".constexpr." }
+{ return d; }                  // { dg-error "non-.constexpr." "" { target { ! implicit_constexpr } } }
+constexpr resource d = f(9);   // { dg-message ".constexpr." "" { target { ! implicit_constexpr } } }
 
 // 4.4 floating-point constant expressions
index 51b328e2598098f6d330e96751674920426ec8fb..e934421c2f4880b82ce1bb90da3e97293c0954d6 100644 (file)
@@ -9,5 +9,5 @@ struct A
 struct B
 {
   A a[1];
-  constexpr B() : a() {} // { dg-error "non-constant|non-.constexpr." }
+  constexpr B() : a() {} // { dg-error "non-constant|non-.constexpr." "" { target { ! implicit_constexpr } } }
 };
index a04f1d51d22c7666312fd1d87497cf6dea74879b..c018eded1de1fe9b59336a451d3421952581414c 100644 (file)
@@ -28,4 +28,4 @@ struct D
   C<D> c;
 };
 
-constexpr D d {};              // { dg-error "non-.constexpr. function" }
+constexpr D d {};              // { dg-error "non-.constexpr. function" "" { target { ! implicit_constexpr } } }
index d58e2ec6b15f840ab142e65e315c4a2449b3b9f8..37255282ded7bddb3e5f48f41328955f7934038f 100644 (file)
@@ -13,6 +13,6 @@ constexpr X X::g(X x) { return x; }
 struct Y
 {
   Y() { }
-  constexpr Y f(Y y) { return y; }  // { dg-error "constexpr" }
-  static constexpr Y g(Y y) { return y; } // { dg-error "constexpr" }
+  constexpr Y f(Y y) { return y; }  // { dg-error "constexpr" "" { target { ! implicit_constexpr } } }
+  static constexpr Y g(Y y) { return y; } // { dg-error "constexpr" "" { target { ! implicit_constexpr } } }
 };
index 55bb838a2bfb5033c5e21b0ebfa7cb8dea132c8a..89559d7605882908ee5629bde65f13af2febc1c3 100644 (file)
@@ -9,7 +9,7 @@ struct A
 template<typename> struct B
 {
   A a;
-  constexpr int bar() { return a.foo(); } // { dg-error "foo" }
+  constexpr int bar() { return a.foo(); } // { dg-error "foo" "" { target { ! implicit_constexpr } } }
 };
 
-constexpr int i = B<void>().bar(); // { dg-error "bar" }
+constexpr int i = B<void>().bar(); // { dg-error "bar" "" { target { ! implicit_constexpr } } }
index 64d8f4ec2666d1e5cbe86897940d7ae02128c440..acda6e0bcbfd42f6791d370ddd3cf3b6f40fd767 100644 (file)
@@ -3,10 +3,10 @@
 
 template<typename T> constexpr int foo(T);
 template<> int foo(int);
-template<> int foo(int);            // { dg-message "previous declaration 'int foo" }
-template<> constexpr int foo(int);  // { dg-error "redeclaration 'constexpr int foo" }
+template<> int foo(int);            // { dg-message "previous declaration 'int foo" "" { target { ! implicit_constexpr } } }
+template<> constexpr int foo(int);  // { dg-error "redeclaration 'constexpr int foo" "" { target { ! implicit_constexpr } } }
 
 template<typename T> int bar(T);
 template<> constexpr int bar(int);
-template<> constexpr int bar(int);  // { dg-message "previous declaration 'constexpr int bar" }
-template<> int bar(int);            // { dg-error "redeclaration 'int bar" }
+template<> constexpr int bar(int);  // { dg-message "previous declaration 'constexpr int bar" "" { target { ! implicit_constexpr } } }
+template<> int bar(int);            // { dg-error "redeclaration 'int bar" "" { target { ! implicit_constexpr } } }
index 7e2d58b422efc245652eb0b7c97ee52fb701d5da..3476f9607ac004f4c426bebe2d2ca4620ec59be4 100644 (file)
@@ -11,4 +11,4 @@ struct B : A
   using A::A;
 };
 
-constexpr B b;  // { dg-error "literal" }
+constexpr B b;  // { dg-error "literal" "" { target { ! implicit_constexpr } } }
index 04c58636d8d5a53d8eda42d49cb53af289a7f726..c978f0c376164df662409358ec49fe555a9753c8 100644 (file)
@@ -1,6 +1,7 @@
 // PR c++/81860
 // { dg-do compile { target c++11 } }
 // { dg-final { scan-assembler "_ZN1AIjEC\[12\]Ev" } }
+// { dg-additional-options -fno-implicit-constexpr }
 
 template <typename T>
 struct A
index 5f17a21cac484e208e67a6d87d0d31fedd675af6..2120d8c72fe9d0543e70f1a4d836096444a5eb08 100644 (file)
@@ -1,6 +1,7 @@
 // PR c++/51818
 // { dg-do compile { target c++11 } }
 // { dg-final { scan-assembler "_ZN1AC1IN3foo3barMUlvE_EEET_" } }
+// { dg-additional-options -fno-implicit-constexpr }
 
 struct A
 {
index dd95894755c97611be4fb01d21bc03f27ef2c346..23df3a2b41675b882c3155f2eac5326352309500 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
+// { dg-additional-options -fkeep-inline-functions }
 // { dg-final { scan-assembler "_ZZN1AIiEC4IiEET_S2_Ed_NKUlvE_clEv" } }
 
 template <class T> struct A
index 224f2789bcd8f98811c13f553ac9e3660b9a5671..98885799de989ce1d1fa5f158afeeb9205451100 100644 (file)
@@ -1,5 +1,6 @@
 // { dg-do compile { target c++14 } }
 // { dg-final { scan-assembler "_ZN1AIiEcvDaEv" } }
+// { dg-additional-options -fno-implicit-constexpr }
 
 template <class T>
 struct A {
index 02f372d98887ed7b100133238daea6427a197667..150aadfe6094b12d2c4e10cb61c553286e6701c9 100644 (file)
@@ -9,11 +9,11 @@ template<typename>
 constexpr int count()
 {
     auto item = thing {};
-    for(; (item.foo(), false);); // { dg-error "foo" }
+    for(; (item.foo(), false);); // { dg-error "foo" "" { target { ! implicit_constexpr } } }
     return 0;
 }
 
 int main()
 {
-    static_assert( count<int>() == 0, "" ); // { dg-error "" }
+    static_assert( count<int>() == 0, "" ); // { dg-error "" "" { target { ! implicit_constexpr } } }
 }
index 474ce88f81f3151b9711e2f67fbc2d1414934d5c..faac00ca9974f3ec3cec51c040c15cb091278aaf 100644 (file)
@@ -8,5 +8,5 @@ struct NonLiteral {
   int n;
 };
 
-static_assert( ID (NonLiteral{3}).n == 3); // { dg-error "non-literal" }
+static_assert( ID (NonLiteral{3}).n == 3); // { dg-error "non-literal" "" { target { ! implicit_constexpr } } }
 // { dg-prune-output "static assertion" }
index 69fe9e26654f83983d5ce9d47074ee5e440396d4..a68a6b4af8bc517e7dbc3444509109e01b869f02 100644 (file)
@@ -7,16 +7,16 @@ struct S
   constexpr ~S () {}
   int s;
 };
-struct T       // { dg-message "'T' is not literal because" }
-{              // { dg-message "'T' does not have 'constexpr' destructor" "" { target *-*-* } .-1 }
+struct T       // { dg-message "'T' is not literal because" "" { target { ! implicit_constexpr } } }
+{              // { dg-message "'T' does not have 'constexpr' destructor" "" { target { ! implicit_constexpr } } .-1 }
   constexpr T () : t (0) {}
-  ~T () {}     // { dg-message "defaulted destructor calls non-'constexpr' 'T::~T\\(\\)'" }
+  ~T () {}     // { dg-message "defaulted destructor calls non-'constexpr' 'T::~T\\(\\)'" "" { target { ! implicit_constexpr } } }
   int t;
 };
 struct U : public S
 {
   constexpr U () : u (0) {}
-  constexpr ~U () = default;   // { dg-error "explicitly defaulted function 'constexpr U::~U\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+  constexpr ~U () = default;   // { dg-error "explicitly defaulted function 'constexpr U::~U\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" "" { target { ! implicit_constexpr } } }
   int u;
   T t;
 };
@@ -100,11 +100,11 @@ struct W8
 struct X : public T
 {
   constexpr X () : x (0) {}
-  constexpr ~X () = default;   // { dg-error "explicitly defaulted function 'constexpr X::~X\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+  constexpr ~X () = default;   // { dg-error "explicitly defaulted function 'constexpr X::~X\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" "" { target { ! implicit_constexpr } } }
   int x;
 };
 constexpr S s;
-constexpr T t; // { dg-error "the type 'const T' of 'constexpr' variable 't' is not literal" }
+constexpr T t; // { dg-error "the type 'const T' of 'constexpr' variable 't' is not literal" "" { target { ! implicit_constexpr } } }
 constexpr W0 w1;
 constexpr W0 w2 = 12;
 constexpr W1 w3 = 5;   // { dg-message "in 'constexpr' expansion of" }
@@ -167,19 +167,19 @@ constexpr int x5 = f5 (); // { dg-message "in 'constexpr' expansion of" }
 void
 f6 ()
 {
-  constexpr T t2;      // { dg-error "the type 'const T' of 'constexpr' variable 't2' is not literal" }
+  constexpr T t2;      // { dg-error "the type 'const T' of 'constexpr' variable 't2' is not literal" "" { target { ! implicit_constexpr } } }
 }
 
 constexpr int
 f7 ()
 {
-  constexpr T t3;      // { dg-error "the type 'const T' of 'constexpr' variable 't3' is not literal" }
+  constexpr T t3;      // { dg-error "the type 'const T' of 'constexpr' variable 't3' is not literal" "" { target { ! implicit_constexpr } } }
   return 0;
 }
 
 constexpr int
 f8 ()
 {
-  T t4;                        // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target c++20_down } }
+  T t4;                        // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target { c++20_down && { ! implicit_constexpr } } } }
   return 0;
 }
index 6762c24a34271fcc5caf149f75c9518595eb9568..7eed50c7f4cfdbd1313d8b505df92fe54a3d69de 100644 (file)
@@ -9,7 +9,7 @@ struct A {
 
 struct B : A {
   constexpr B () : b (0) {}
-  virtual int foo () { return 0 + b * 4; }     // { dg-message "declared here" }
+  virtual int foo () { return 0 + b * 4; }     // { dg-message "declared here" "" { target { ! implicit_constexpr } } }
   int b;
 };
 
@@ -18,7 +18,7 @@ foo ()
 {
   A *a = new B ();
   a->a = 4;
-  int r = a->foo ();   // { dg-error "call to non-.constexpr. function" }
+  int r = a->foo ();   // { dg-error "call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
   delete a;
   return r;
 }
index e8b3bcb570b7dd0e3d6f5876b73de275ee357782..b090277181411dadb3f3f2904c512138e165a8a2 100644 (file)
@@ -39,9 +39,9 @@ constinit thread_local const int &r2 = gl;
 constinit const int &r3 // { dg-error "variable .r3. does not have a constant initializer" }
   = foo (); // { dg-error "call to non-.constexpr. function" }
 constinit const literal &r4 = 42;
-constinit const nonliteral &r5 // { dg-error "variable .r5. does not have a constant initializer" }
-  = 42; // { dg-error "call to non-.constexpr. function" }
-constinit const int &r6 = nonliteral(2).m; // { dg-error "variable .r6. does not have a constant initializer|call to non-.constexpr. function" }
+constinit const nonliteral &r5 // { dg-error "variable .r5. does not have a constant initializer" "" { target { ! implicit_constexpr } } }
+  = 42; // { dg-error "call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
+constinit const int &r6 = nonliteral(2).m; // { dg-error "variable .r6. does not have a constant initializer|call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 
 constinit pod p1;
 constinit pod p2 = { 42 };
@@ -64,8 +64,8 @@ constinit thread_local literal l11{};
 pod S::p;
 constinit pod S::pc(S::p); // { dg-error "variable .S::pc. does not have a constant initializer|not usable" }
 
-constinit const nonliteral S::n(42); // { dg-error "variable .S::n. does not have a constant initializer|call to non-.constexpr. function" }
-constinit int n1 = nonliteral{42}.m; // { dg-error "variable .n1. does not have a constant initializer|temporary of non-literal type" }
+constinit const nonliteral S::n(42); // { dg-error "variable .S::n. does not have a constant initializer|call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
+constinit int n1 = nonliteral{42}.m; // { dg-error "variable .n1. does not have a constant initializer|temporary of non-literal type" "" { target { ! implicit_constexpr } } }
 constinit int n2 = literal{42}.m;
 
 void
index cc6569b2277b241235372c485f220339e2e8d53d..faa1b430cee96b3266a002f3d2e9b8b27e8b9bcf 100644 (file)
@@ -8,7 +8,7 @@ struct S {
 template <class T>
 struct U {
   T m;
-  constexpr U(int i) : m(i) { } // { dg-error "call to non-.constexpr. function" }
+  constexpr U(int i) : m(i) { } // { dg-error "call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 };
 
-constinit U<S> u(42); // { dg-error "does not have a constant initializer|called in a constant expression" }
+constinit U<S> u(42); // { dg-error "does not have a constant initializer|called in a constant expression" "" { target { ! implicit_constexpr } } }
index 86a058b632cccccdb0f8ad1d65251f09307490ce..06c4cb46722f6f4049fd7a9e0aafaac7a6f462a6 100644 (file)
@@ -2,7 +2,7 @@
 // { dg-do compile { target c++20 } }
 
 struct Value {
-  Value() : v{new int{42}} {}
+  Value() : v{new int{42}} {}  // { dg-error "result of 'operator new'" "" { target implicit_constexpr } }
   int* v;
 };
 
index 29e8b51326d4b07424c1176e13b6689610c93a48..b6215587badb54343e965481ff9732a02f378794 100644 (file)
@@ -6,7 +6,7 @@ struct B {
 };
 
 struct A {
-    constinit static inline B b1{}; // { dg-error "does not have a constant initializer|call to non-.constexpr. function" }
+    constinit static inline B b1{}; // { dg-error "does not have a constant initializer|call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 };
 
 int main() {
index 6ccc7e8507bda90a2b02cde7e884c05f419ddad2..dff59271a1e67fdf6485c28fc2ed713fdb896bd5 100644 (file)
@@ -9,7 +9,7 @@ struct A
 struct B
 {
   A a;
-  bool operator==(const B&) const = default; // { dg-error "A::operator==" }
+  bool operator==(const B&) const = default; // { dg-error "A::operator==" "" { target { ! implicit_constexpr } } }
 };
 
-constexpr bool x = B() == B(); // { dg-error "non-.constexpr" }
+constexpr bool x = B() == B(); // { dg-error "non-.constexpr" "" { target { ! implicit_constexpr } } }
index d31faef095d0dac0cf9feb883fb5807fa4914f34..7a517a8016c4f1c15e3e343aaddbf64ddb507667 100644 (file)
@@ -12,5 +12,5 @@ struct D
 };
 
 constexpr D d{A()};
-static_assert (d == d);                // { dg-error "non-constant|constexpr" }
-static_assert (!(d != d));     // { dg-error "non-constant|constexpr" }
+static_assert (d == d);                // { dg-error "constant|constexpr" }
+static_assert (!(d != d));     // { dg-error "constant|constexpr" }
index 62cb86ae6954f1e6ef5152293d816d674818fa6d..ab7c012f5f47c481b95baa965a0b1ff40526026f 100644 (file)
@@ -9,5 +9,5 @@ struct non_literal_class {
   // auto operator<=> (const non_literal_fixed_string&) = default;
 };
 
-template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not structural" }
-int operator"" _udl();       // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" }
+template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not structural" "" { target { ! implicit_constexpr } } }
+int operator"" _udl();       // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" "" { target { ! implicit_constexpr } } }
index 5daf3cd5c879bd8befa6c4fdb3e0a7eadc48d808..3e5867d258c8fb4ec0979192215211600bbbeecd 100644 (file)
@@ -1,6 +1,6 @@
 // PR c++/53756
 // { dg-do compile { target c++14 } }
-// { dg-options "-gdwarf-2 -dA -fno-debug-types-section" }
+// { dg-options "-gdwarf-2 -dA -fno-debug-types-section -fno-inline" }
 // We're looking for something like
 
 // .uleb128 0x3    # (DIE (0x33) DW_TAG_subprogram)
index c0d3d2251870a57b6330eb085dbc08da32d1d6dd..b211c02c894095722eb92f0862717c85f8ec7030 100644 (file)
@@ -1,5 +1,5 @@
 // origin PR debug/49047
-// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings" }
+// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings -fno-implicit-constexpr" }
 // { dg-do compile }
 
 struct K
index bd3ce5dc807b99061b6fea721609b395d4e375db..b2566c7aa7a060a5b6733e61a0058d404569f9c1 100644 (file)
@@ -1,6 +1,6 @@
 // PR c++/43912
 // { dg-do compile { target c++11 } }
-// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings -gno-strict-dwarf" }
+// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings -gno-strict-dwarf -fno-inline" }
 
 // Check for the local alias variables that point to the members of the closure.
 // { dg-final { scan-assembler-times "DW_TAG_variable\[^.\]*\.ascii \"j.0\"" 4 { xfail { powerpc-ibm-aix* } } } }
index e7a6aa41c0d25a47ed742fed90a418e5d57c48c2..0a3721ee6b1bc302cb7e173836411b9b3d84b672 100644 (file)
@@ -1,6 +1,6 @@
 // PR debug/54508
 // { dg-do compile }
-// { dg-options "-gdwarf-2 -g2 -dA -fno-merge-debug-strings" }
+// { dg-options "-gdwarf-2 -g2 -dA -fno-merge-debug-strings -fno-inline" }
 
 // { dg-final { scan-assembler "\"cbase\\\\0\"\[ \t\]+\[#;/!|@\]+ +DW_AT_name" } }
 // { dg-final { scan-assembler "\"OPCODE\\\\0\"\[ \t\]+\[#;/!|@\]+ +DW_AT_name" } }
index af0f6f1b95cf284b0004ab7dd81c813dec51e1d0..1fb5004df4012fc61de85fb7ea1268778d6dedb8 100644 (file)
@@ -1,6 +1,6 @@
 // { dg-do compile { target c++11 } }
 // { dg-skip-if "" { powerpc-ibm-aix* } }
-// { dg-options "-gpubnames -gdwarf-4 -fno-debug-types-section -dA" }
+// { dg-options "-gpubnames -gdwarf-4 -fno-debug-types-section -dA -fno-inline" }
 // { dg-final { scan-assembler-times "\.section\[\t \]\[^\n\]*debug_pubnames" 1 } }
 // { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
 // { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
index 63b870bc8e7ba8d40fa24580c09e71f4537217c5..37e04fb6c972c603cb822dd620b2ea3c6b9e0e83 100644 (file)
@@ -1,6 +1,6 @@
 // { dg-do compile { target c++11 } }
 // { dg-skip-if "" { powerpc-ibm-aix* } }
-// { dg-options "-gpubnames -gdwarf-4 -fdebug-types-section -dA" }
+// { dg-options "-gpubnames -gdwarf-4 -fdebug-types-section -dA -fno-inline" }
 // { dg-final { scan-assembler-times "\.section\[\t \]\[^\n\]*debug_pubnames" 1 } }
 // { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
 // { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
index 22d8494a2b47a913caca3d1efc1c61d8ea6c321a..4fede879a42a13c6b54dffba6fc10fc5e6f5d2f3 100644 (file)
@@ -6,7 +6,11 @@ struct S {
   int n;
 };
 
+#if __cpp_implicit_constexpr
+static_assert(__is_literal_type(S), "");
+#else
 static_assert(!__is_literal_type(S), "");
+#endif
 
 #ifdef __cpp_constexpr_dynamic_alloc
 struct T {
index 5197fb1c960398cd347ba2aa8a9b252f6351d1b3..f1490fa3d32dd145109a261d8694311273de71f6 100644 (file)
@@ -1,6 +1,6 @@
 // PR c++/35688
 // { dg-require-visibility "" }
-// { dg-options "-fvisibility=hidden" }
+// { dg-options "-fvisibility=hidden -fno-inline" }
 
 // { dg-final { scan-hidden "_ZN1s6vectorI1AEC1Ev" } }
 // { dg-final { scan-hidden "_ZN1s3fooI1AEEvT_" } }
index c4708e40726b7ce813064c15d9df1d49e24beb15..9f2b29b4da501fe5cd35bd67145b6491a6cb447e 100644 (file)
@@ -1,5 +1,5 @@
 /* PR 51113 */
-/* { dg-options "-fprofile-arcs -ftest-coverage -fpic" } */
+/* { dg-options "-fprofile-arcs -ftest-coverage -fpic -fno-implicit-constexpr" } */
 /* { dg-do run { target native } } */
 /* { dg-additional-sources "gcovpart-12b.C" } */
 
index 2b4cdd844e95c7871ca02c9e2c3d4eb24c5ae41a..05db15de7cc5896dfb96739efd3dd8c0f8b51ec7 100644 (file)
@@ -1,6 +1,6 @@
 /* Verify line coverage counts for simple member functions. */
 
-/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-options "-fprofile-arcs -ftest-coverage -fno-implicit-constexpr" } */
 /* { dg-do run { target native } } */
 
 class C {
index 87f72b89984e8d9148a993871fa28972a12e1e56..ca9ccb7a1334d8f45addb881435aa9b3edddff11 100644 (file)
@@ -15,7 +15,6 @@ m(struct B *b)
                   //  test2 may change the type of A by placement new.
                   // C++ standard is bit imprecise about this.
 }
-/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
-/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1" { target { ! implicit_constexpr } } } } */
+/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt" { target { ! implicit_constexpr } } } } */
 /* { dg-final { scan-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
-
index 067a2bb8ca19336d156fbdaeb078269a0e6beee8..60b830186bb7553c8a1415fd71261158f0a611a8 100644 (file)
@@ -18,7 +18,7 @@ m(struct B *b)
                   //  test2 may change the type of A by placement new.
                   // C++ standard is bit imprecise about this.
 }
-/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
-/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1" { target { ! implicit_constexpr } } } } */
+/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt" { target { ! implicit_constexpr } } } } */
 /* { dg-final { scan-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
 
index b7f52a0a5e9d350b22d76a1cf8c85f24ac926d6f..df5ab901f82a7604b7cbde021ff71371f5421f43 100644 (file)
@@ -33,4 +33,4 @@ t()
 /* { dg-final { scan-tree-dump "No dynamic type change found."  "fre3"  } } */
 /* { dg-final { scan-tree-dump "Checking vtbl store:"  "fre3"  } } */
 /* { dg-final { scan-tree-dump "Function call may change dynamic type:extcall"  "fre3"  } } */
-/* { dg-final { scan-tree-dump "converting indirect call to function virtual void"  "fre3"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual void"  "fre3" { target { ! implicit_constexpr } } } } */
index 5de761412d0560b15bfaf01bad184ee70e5990ef..ed211e1173997eb10bf895d7bb0404ccf85b25ef 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining" } */
+/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining -fno-implicit-constexpr" } */
 struct A {
   virtual int foo () {return 1;}
   void wrapfoo () {foo();}
index 00ac61e7f3848152d3e342e88397453dcafb9f21..fa31cfbae5452929375a82ace2acaa8b65d03978 100644 (file)
@@ -60,7 +60,7 @@ int main (int argc, char *argv[])
 
 /* middleman_2 gets early inlined and the virtual call should get turned to
    a direct call.  */
-/* { dg-final { scan-tree-dump "Inlining int middleman_1" "einline"  } } */
-/* { dg-final { scan-tree-dump "Inlining int middleman_2" "einline"  } } */
+/* { dg-final { scan-tree-dump "Inlining int middleman_1" "einline" { target { ! implicit_constexpr } } } } */
+/* { dg-final { scan-tree-dump "Inlining int middleman_2" "einline" { target { ! implicit_constexpr } } } } */
 /* { dg-final { scan-tree-dump "B::foo \\(" "einline"  } } */
 /* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 2 "einline"  } } */
index 1bd67dce5ac608db67253d33e3d66177659162dd..652e3f58b67831c2dbe2556ceb01dbc294ea2593 100644 (file)
@@ -1,5 +1,5 @@
 // PR c++/37276
-
+// { dg-additional-options -fno-inline }
 // { dg-final { scan-assembler "_ZSt5atanhd" } }
 
 namespace std
index adbc43ea2534db913d3925de0aec9f87244c5ae3..0294dcc4bfb7000c6a3338f855f541d0760be27d 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-lto-do link }
-/* { dg-lto-options { "-O2 -fno-early-inlining -flto -fdump-ipa-inline-details" } } */
+/* { dg-lto-options { "-O2 -fno-early-inlining -fno-implicit-constexpr -flto -fdump-ipa-inline-details" } } */
 #include "inline-crossmodule-1.h"
 int a::key ()
 {
index 53e2ac88f2082c8501388a9b582a618085caa651..24cad2864648476d63a86a6e824d53062cbf9788 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-module-do run }
-// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid -fno-implicit-constexpr" }
 export module enUm;
 // { dg-module-cmi "enUm" }
 
index 55a7aaa26b46c225c90b656255dd0ffdc5fee663..2b8bbdcd1af96b30483be01c2de61d5e9c15f055 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts" }
+// { dg-additional-options "-fmodules-ts -fno-inline" }
 import bob;
 
 int main ()
index c597db1fe8abc899ca522fa94a283d63b4f41ab9..a7b3fc370ecdf80089f65a90e49954e8a1679a2c 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-additional-options -fmodule-header }
+// { dg-additional-options "-fmodule-header -fno-implicit-constexpr" }
 // { dg-module-cmi {} }
 
 #include "pmf-1.h"
index 0b086107045383bb2843a9edca9668cff948ffa2..cb2a35bbc3b1a998c056f3b9fb210d682bf0a871 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias -fno-implicit-constexpr" }
 
 #include "pmf-1.h"
 import "pmf-1_a.H";
index 0d1514e031cae0936cca8998d4513e13827e4f1e..b51a19fb8d754f5520a749a654bd38dffed05ff3 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-additional-options -fmodules-ts }
+// { dg-additional-options "-fmodules-ts -fno-inline" }
 
 import "used-1_b.H";
 
index 273ee03d70256a6cb0118041ee294b99060d5bcb..7e83a4537543a41efb7ea7ffb9194985f7687cd1 100644 (file)
@@ -2,7 +2,7 @@
 // { dg-do compile { target c++11 } }
 // { dg-add-options tls }
 // { dg-require-effective-target tls_runtime }
-// { dg-additional-options "-fdump-tree-gimple" }
+// { dg-additional-options "-fdump-tree-gimple -fno-implicit-constexpr" }
 // { dg-final { scan-tree-dump-times "_ZTW2s1" 2 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTW2s2" 2 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTW2s3" 2 "gimple" } }
index d8c4a6dc0ab85513a18fc49df1449023c6a4f437..a6283984eb79d58e9e8d55d199e2478af7bd1a02 100644 (file)
@@ -3,7 +3,7 @@
 // { dg-add-options tls }
 // { dg-require-alias "" }
 // { dg-require-effective-target tls_runtime }
-// { dg-additional-options "-fdump-tree-gimple" }
+// { dg-additional-options "-fdump-tree-gimple -fno-implicit-constexpr" }
 // { dg-final { scan-tree-dump-times "_ZTH2s1" 1 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTH2s2" 1 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTH2s3" 1 "gimple" } }
index f8f3a1d3117fa6b43408f22b95cf408216e7f56c..a4649eb5ffc941f15b80204f9afe37f7c135331c 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-fgnu-tm -O" }
+// { dg-options "-fgnu-tm -O -fno-implicit-constexpr" }
 
 class shared_count
 {
index a1d3dc2ec1698a9ab0667e18571989ec35f523eb..521dcb8d8c022cd9dc8d8c4d3bbba5e6cd4ac942 100644 (file)
@@ -1,7 +1,7 @@
 // PR c++/70035
 // { dg-do run }
 // { dg-shouldfail "ubsan" }
-// { dg-options "-fsanitize=vptr -fno-sanitize-recover=undefined" }
+// { dg-options "-fsanitize=vptr -fno-sanitize-recover=undefined -fno-implicit-constexpr" }
 
 struct A {
   A (int) {}
index 733a6e22cb9b9b2a14718931c7775c90021e417c..56cfa000e8d531562a6f576a75aa3ecea15942ba 100644 (file)
@@ -25,4 +25,4 @@ inline void A::operator delete(void*p)
 
 int main()
 {A *ap=new A;
-delete ap;}
+delete ap;}                    // { dg-prune-output "unallocated object 'i'" }
index c360770a7a20251f19d7d7003abb12dbba2d4676..fd06d278faafaf3d657842ca135c564e22cebefc 100644 (file)
@@ -57,7 +57,8 @@ proc g++-dg-runtest { testcases flags default-extra-flags } {
            set option_list { }
            foreach x $std_list {
                # Handle "concepts" as C++17 plus Concepts TS.
-               if { $x eq "concepts" } then { set x "17 -fconcepts" }
+               if { $x eq "concepts" } then { set x "17 -fconcepts"
+               } elseif { $x eq "impcx" } then { set x "23 -fimplicit-constexpr" }
                lappend option_list "${std_prefix}$x"
            }
        } else {
index 8cbda192fe0fae59ea208ee43696b4d22c43e61e..c928d99a14be1192b5f4154a833b9fef5c8cf0e7 100644 (file)
@@ -10232,6 +10232,10 @@ proc check_effective_target_concepts { } {
     return [check-flags { "" { } { -fconcepts } }]
 }
 
+proc check_effective_target_implicit_constexpr { } {
+    return [check-flags { "" { } { -fimplicit-constexpr } }]
+}
+
 # Return 1 if expensive testcases should be run.
 
 proc check_effective_target_run_expensive_tests { } {
index ff3a1fbcb5dd6ba70e3c5e547a9ae419212e8ae2..5030f89b345287a7d604778d6ebdac5512641321 100644 (file)
@@ -32,5 +32,5 @@ struct P
 void test01()
 {
   P p;
-  std::to_address(p); // { dg-error "required from here" }
+  std::to_address(p); // { dg-error "" }
 }
index 1adc0c11baaa6d32f05b6434e2eca0a11f4e8020..0a0cbbf7c4e1f624cc482d65fd5e87df9609bc5a 100644 (file)
@@ -227,7 +227,11 @@ struct N12
   static constexpr unsigned max() { return 1; }
 };
 
+#if __cpp_implicit_constexpr
+static_assert( std::uniform_random_bit_generator<N12> ); // LWG 3150
+#else
 static_assert( ! std::uniform_random_bit_generator<N12> ); // LWG 3150
+#endif
 
 struct N13
 {
@@ -236,7 +240,11 @@ struct N13
   static unsigned max() { return 1; } // not constexpr
 };
 
+#if __cpp_implicit_constexpr
+static_assert( std::uniform_random_bit_generator<N13> ); // LWG 3150
+#else
 static_assert( ! std::uniform_random_bit_generator<N13> ); // LWG 3150
+#endif
 
 struct N14
 {