https://github.com/hanickadot updated 
https://github.com/llvm/llvm-project/pull/136436

From f37eb75b71d2aa6433bc528b7b4532138ae4e62a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= <hani...@hanicka.net>
Date: Sun, 20 Apr 2025 00:24:46 +0200
Subject: [PATCH 1/2] [clang] add -fimplicit-constexpr flag (with same
 behaviour as GCC)

---
 clang/include/clang/AST/Decl.h                |   3 +
 .../include/clang/Basic/DiagnosticASTKinds.td |   2 +
 clang/include/clang/Basic/Features.def        |   1 +
 clang/include/clang/Basic/LangOptions.def     |   1 +
 clang/include/clang/Driver/Options.td         |   6 +
 clang/lib/AST/Decl.cpp                        |  21 ++++
 clang/lib/AST/ExprConstant.cpp                |  24 +++-
 clang/lib/Driver/ToolChains/Clang.cpp         |   3 +
 clang/lib/Frontend/InitPreprocessor.cpp       |   3 +
 clang/lib/Sema/SemaExpr.cpp                   |   6 +-
 clang/test/Sema/implicit-constexpr-basic.cpp  | 112 ++++++++++++++++++
 .../test/Sema/implicit-constexpr-features.cpp |  81 +++++++++++++
 .../test/Sema/implicit-constexpr-members.cpp  |  83 +++++++++++++
 13 files changed, 339 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/Sema/implicit-constexpr-basic.cpp
 create mode 100644 clang/test/Sema/implicit-constexpr-features.cpp
 create mode 100644 clang/test/Sema/implicit-constexpr-members.cpp

diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 3faf63e395a08..be37cb115b24b 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -2418,6 +2418,9 @@ class FunctionDecl : public DeclaratorDecl,
   bool isConstexpr() const {
     return getConstexprKind() != ConstexprSpecKind::Unspecified;
   }
+  /// Support for `-fimplicit-constexpr`
+  bool isConstexprOrImplicitlyCanBe(const LangOptions &LangOpts,
+                                    bool MustBeInlined = true) const;
   void setConstexprKind(ConstexprSpecKind CSK) {
     FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(CSK);
   }
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index f73963752bb67..57d58a735db85 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -32,6 +32,8 @@ def note_constexpr_lshift_discards : Note<"signed left shift 
discards bits">;
 def note_constexpr_invalid_function : Note<
   "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot "
   "be used in a constant expression">;
+def note_constexpr_implicit_constexpr_must_be_inlined
+    : Note<"non-inline function %0 is not implicitly constexpr">;
 def note_constexpr_invalid_inhctor : Note<
   "constructor inherited from base class %0 cannot be used in a "
   "constant expression; derived class cannot be implicitly initialized">;
diff --git a/clang/include/clang/Basic/Features.def 
b/clang/include/clang/Basic/Features.def
index 14bff8a68846d..2fe9ed3419ee9 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -316,6 +316,7 @@ EXTENSION(matrix_types, LangOpts.MatrixTypes)
 EXTENSION(matrix_types_scalar_division, true)
 EXTENSION(cxx_attributes_on_using_declarations, LangOpts.CPlusPlus11)
 EXTENSION(datasizeof, LangOpts.CPlusPlus)
+EXTENSION(cxx_implicit_constexpr, LangOpts.ImplicitConstexpr)
 
 FEATURE(cxx_abi_relative_vtable, LangOpts.CPlusPlus && 
LangOpts.RelativeCXXABIVTables)
 
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 930c1c06d1a76..97a271b200976 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -413,6 +413,7 @@ BENIGN_LANGOPT(ArrowDepth, 32, 256,
                "maximum number of operator->s to follow")
 BENIGN_LANGOPT(InstantiationDepth, 32, 1024,
                "maximum template instantiation depth")
+COMPATIBLE_LANGOPT(ImplicitConstexpr, 1, 0, "make functions implicitly 
'constexpr'")
 BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
                "maximum constexpr call depth")
 BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 919c1c643d080..877235147a044 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1991,6 +1991,12 @@ defm constant_cfstrings : 
BoolFOption<"constant-cfstrings",
           "Disable creation of CodeFoundation-type constant strings">,
   PosFlag<SetFalse>>;
 def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, 
Group<f_Group>;
+def fimplicit_constexpr
+    : Joined<["-"], "fimplicit-constexpr">,
+      Group<f_Group>,
+      Visibility<[ClangOption, CC1Option]>,
+      HelpText<"All function declarations will be implicitly constexpr.">,
+      MarshallingInfoFlag<LangOpts<"ImplicitConstexpr">>;
 def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum depth of recursive constexpr function calls">,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ad1cb01592e9b..1a595dfc3daeb 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3242,6 +3242,27 @@ bool FunctionDecl::isDefined(const FunctionDecl 
*&Definition,
   return false;
 }
 
+bool FunctionDecl::isConstexprOrImplicitlyCanBe(const LangOptions &LangOpts,
+                                                bool MustBeInlined) const {
+  if (isConstexpr())
+    return true;
+
+  if (!LangOpts.ImplicitConstexpr)
+    return false;
+
+  // Constexpr function in C++11 couldn't contain anything other then return
+  // expression. It wouldn't make sense to allow it (GCC doesn't do it 
neither).
+  if (!LangOpts.CPlusPlus14)
+    return false;
+
+  // Free functions must be inlined, but sometimes we want to skip this check.
+  // And in order to keep logic on one place, the check is here.
+  if (MustBeInlined)
+    return isInlined();
+
+  return true;
+}
+
 Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
   if (!hasBody(Definition))
     return nullptr;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b14ff21a8ebc2..6cfb67ad1d719 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5968,8 +5968,9 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
   // Can we evaluate this function call?
   if (Definition && Body &&
-      (Definition->isConstexpr() || (Info.CurrentCall->CanEvalMSConstexpr &&
-                                        
Definition->hasAttr<MSConstexprAttr>())))
+      (Definition->isConstexprOrImplicitlyCanBe(Info.Ctx.getLangOpts()) ||
+       (Info.CurrentCall->CanEvalMSConstexpr &&
+        Definition->hasAttr<MSConstexprAttr>())))
     return true;
 
   if (Info.getLangOpts().CPlusPlus11) {
@@ -5987,12 +5988,25 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
     // FIXME: If DiagDecl is an implicitly-declared special member function
     // or an inheriting constructor, we should be much more explicit about why
     // it's not constexpr.
-    if (CD && CD->isInheritingConstructor())
+    if (CD && CD->isInheritingConstructor()) {
       Info.FFDiag(CallLoc, diag::note_constexpr_invalid_inhctor, 1)
         << CD->getInheritedConstructor().getConstructor()->getParent();
-    else
+
+    } else if (Definition && !DiagDecl->isInlined() &&
+               Info.Ctx.getLangOpts().ImplicitConstexpr) {
+      Info.FFDiag(CallLoc,
+                  diag::note_constexpr_implicit_constexpr_must_be_inlined)
+          << DiagDecl;
+
+    } else {
+      // Using implicit constexpr check here, so we see a missing body as main
+      // problem and not missing constexpr with -fimplicit-constexpr.
       Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1)
-        << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
+          << DiagDecl->isConstexprOrImplicitlyCanBe(Info.Ctx.getLangOpts(),
+                                                    false)
+          << (bool)CD << DiagDecl;
+    }
+
     Info.Note(DiagDecl->getLocation(), diag::note_declared_at);
   } else {
     Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr);
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index f2f5231933c88..e33d0b72ed04d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6612,6 +6612,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ);
 
+  if (types::isCXX(InputType))
+    Args.AddLastArg(CmdArgs, options::OPT_fimplicit_constexpr);
+
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
   if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 1f297f228fc1b..f0fdf81272fb3 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -779,6 +779,9 @@ static void InitializeCPlusPlusFeatureTestMacros(const 
LangOptions &LangOpts,
 
   // TODO: Final number?
   Builder.defineMacro("__cpp_type_aware_allocators", "202500L");
+
+  if (LangOpts.ImplicitConstexpr) // same value as GCC
+    Builder.defineMacro("__cpp_implicit_constexpr", "20211111");
 }
 
 /// InitializeOpenCLFeatureTestMacros - Define OpenCL macros based on target
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 01a021443c94f..82c2c61363e3b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18384,16 +18384,18 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, 
FunctionDecl *Func,
         }
 
         if (FirstInstantiation || TSK != TSK_ImplicitInstantiation ||
-            Func->isConstexpr()) {
+            Func->isConstexprOrImplicitlyCanBe(getLangOpts())) {
           if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
               cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
               CodeSynthesisContexts.size())
             PendingLocalImplicitInstantiations.push_back(
                 std::make_pair(Func, PointOfInstantiation));
-          else if (Func->isConstexpr())
+          else if (Func->isConstexprOrImplicitlyCanBe(getLangOpts()))
             // Do not defer instantiations of constexpr functions, to avoid the
             // expression evaluator needing to call back into Sema if it sees a
             // call to such a function.
+            // (When -fimplicit-instantiation is enabled, all functions are
+            // implicitly constexpr)
             InstantiateFunctionDefinition(PointOfInstantiation, Func);
           else {
             Func->setInstantiationIsPending(true);
diff --git a/clang/test/Sema/implicit-constexpr-basic.cpp 
b/clang/test/Sema/implicit-constexpr-basic.cpp
new file mode 100644
index 0000000000000..9f17a344125dc
--- /dev/null
+++ b/clang/test/Sema/implicit-constexpr-basic.cpp
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 
-verify=ALL_NORMAL,NORMAL14,BOTH14,ALL_PRE20,ALLNORMAL,NORMAL_PRE20,ALL 
-std=c++14 %s -fcolor-diagnostics
+// RUN: %clang_cc1 
-verify=IMPLICIT14,IMPLICIT_PRE20,BOTH14,ALL_PRE20,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++14 %s -fcolor-diagnostics
+
+// RUN: %clang_cc1 
-verify=ALL_NORMAL,NORMAL17,BOTH17,ALL_PRE20,ALLNORMAL,NORMAL_PRE20,ALL 
-std=c++17 %s -fcolor-diagnostics
+// RUN: %clang_cc1 
-verify=IMPLICIT17,IMPLICIT_PRE20,BOTH17,ALL_PRE20,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++17 %s -fcolor-diagnostics
+
+// RUN: %clang_cc1 -verify=ALL_NORMAL,NORMAL20,BOTH20,ALLNORMAL,ALL -std=c++20 
%s -fcolor-diagnostics
+// RUN: %clang_cc1 -verify=IMPLICIT20,BOTH20,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++20 %s -fcolor-diagnostics
+
+// RUN: %clang_cc1 -verify=ALL_NORMAL,NORMAL23,BOTH23,ALLNORMAL,ALL -std=c++23 
%s -fcolor-diagnostics
+// RUN: %clang_cc1 -verify=IMPLICIT23,BOTH23,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++23 %s -fcolor-diagnostics
+
+
+
+
+// =============================================
+// 1) simple uninlined function
+
+bool noinline_fnc() { 
+// ALL-note@-1 {{declared here}}
+       return true;
+}
+
+constexpr bool result_noinline_fnc = noinline_fnc();
+// ALL-error@-1 {{constexpr variable 'result_noinline_fnc' must be initialized 
by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'noinline_fnc' cannot be used in 
a constant expression}}
+// ALLIMPLICIT-note@-3 {{non-inline function 'noinline_fnc' is not implicitly 
constexpr}}
+
+
+// =============================================
+// 2) simple inlined function
+
+inline bool inline_fnc() { 
+// ALLNORMAL-note@-1 {{declared here}}
+       return true;
+}
+
+constexpr bool result_inline_fnc = inline_fnc();
+// ALLNORMAL-error@-1 {{constexpr variable 'result_inline_fnc' must be 
initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'inline_fnc' cannot be used in a 
constant expression}}
+
+
+// =============================================
+// 3) undefined uninlined function
+
+bool noinline_undefined_fnc();
+// ALL-note@-1 {{declared here}}
+
+constexpr bool result_noinline_undefined_fnc = noinline_undefined_fnc();
+// ALL-error@-1 {{constexpr variable 'result_noinline_undefined_fnc' must be 
initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'noinline_undefined_fnc' cannot 
be used in a constant expression}}
+// ALLIMPLICIT-note@-3 {{undefined function 'noinline_undefined_fnc' cannot be 
used in a constant expression}}
+
+
+// =============================================
+// 4) undefined inline function
+
+inline bool inline_undefined_fnc();
+// ALL-note@-1 {{declared here}}
+
+constexpr bool result_inline_undefined_fnc = inline_undefined_fnc();
+// ALL-error@-1 {{constexpr variable 'result_inline_undefined_fnc' must be 
initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'inline_undefined_fnc' cannot be 
used in a constant expression}}
+// ALLIMPLICIT-note@-3 {{undefined function 'inline_undefined_fnc' cannot be 
used in a constant expression}}
+
+// =============================================
+// 5) lambda function
+
+auto lambda = [](int x) { return x > 0; };
+// NORMAL14-note@-1 {{declared here}}
+
+constexpr bool result_lambda = lambda(10);
+// NORMAL14-error@-1 {{constexpr variable 'result_lambda' must be initialized 
by a constant expression}}
+// NORMAL14-note@-2 {{non-constexpr function 'operator()' cannot be used in a 
constant expression}}
+
+
+// =============================================
+// 6) virtual functions
+
+struct type {
+  virtual bool dispatch() const noexcept {
+    return false;
+  }
+};
+
+struct child_of_type: type {
+  bool dispatch() const noexcept override {
+// NORMAL20-note@-1 {{declared here}}
+// NORMAL23-note@-2 {{declared here}}
+    return true;
+  }
+};
+
+constexpr bool result_virtual = static_cast<const type 
&>(child_of_type{}).dispatch();
+// ALL_NORMAL-error@-1 {{constexpr variable 'result_virtual' must be 
initialized by a constant expression}}
+// NORMAL_PRE20-note@-2 {{cannot evaluate call to virtual function in a 
constant expression in C++ standards before C++20}}
+// IMPLICIT_PRE20-error@-3 {{constexpr variable 'result_virtual' must be 
initialized by a constant expression}}
+// IMPLICIT_PRE20-note@-4 {{cannot evaluate call to virtual function in a 
constant expression in C++ standards before C++20}}
+// NORMAL20-note@-5 {{non-constexpr function 'dispatch' cannot be used in a 
constant expression}}
+// NORMAL20-note@-6 {{declared here}}
+// NORMAL23-note@-7 {{non-constexpr function 'dispatch' cannot be used in a 
constant expression}}
+// NORMAL23-note@-8 {{declared here}}
+
+
+#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
+static_assert(result_virtual == true, "virtual should work");
+// ALL_NORMAL-error@-1 {{static assertion expression is not an integral 
constant expression}}
+// ALL_NORMAL-note@-2 {{initializer of 'result_virtual' is not a constant 
expression}}
+// IMPLICIT_PRE20-note@-3 {{initializer of 'result_virtual' is not a constant 
expression}}
+#endif
+
+
diff --git a/clang/test/Sema/implicit-constexpr-features.cpp 
b/clang/test/Sema/implicit-constexpr-features.cpp
new file mode 100644
index 0000000000000..ab8a50ecdb147
--- /dev/null
+++ b/clang/test/Sema/implicit-constexpr-features.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -verify=NORMAL14,NORMAL_ALL -std=c++14 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=
+// RUN: %clang_cc1 -verify=NORMAL17,NORMAL_ALL -std=c++17 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=
+// RUN: %clang_cc1 -verify=NORMAL20,NORMAL_ALL -std=c++20 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=
+// RUN: %clang_cc1 -verify=NORMAL23,NORMAL_ALL -std=c++23 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=
+// RUN: %clang_cc1 -verify=NORMAL26,NORMAL_ALL -std=c++26 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=
+
+// RUN: %clang_cc1 -verify=IMPLICIT14,IMPLICIT_ALL -std=c++14 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR= -fimplicit-constexpr
+// RUN: %clang_cc1 -verify=IMPLICIT17,IMPLICIT_ALL -std=c++17 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR= -fimplicit-constexpr
+// RUN: %clang_cc1 -verify=IMPLICIT20,IMPLICIT_ALL -std=c++20 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR= -fimplicit-constexpr
+// RUN: %clang_cc1 -verify=IMPLICIT23,IMPLICIT_ALL -std=c++23 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR= -fimplicit-constexpr
+// RUN: %clang_cc1 -verify=IMPLICIT26,IMPLICIT_ALL -std=c++26 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR= -fimplicit-constexpr
+
+// RUN: %clang_cc1 
-verify=CONSTEXPR14,CONSTEXPR_BEFORE23,CONSTEXPR_BEFORE20,CONSTEXPR_ALL 
-std=c++14 %s -fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=constexpr
+// RUN: %clang_cc1 
-verify=CONSTEXPR17,CONSTEXPR_BEFORE23,CONSTEXPR_BEFORE20,CONSTEXPR_ALL 
-std=c++17 %s -fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=constexpr
+// RUN: %clang_cc1 -verify=CONSTEXPR20,CONSTEXPR_BEFORE23,CONSTEXPR_ALL 
-std=c++20 %s -fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=constexpr
+// RUN: %clang_cc1 -verify=CONSTEXPR23,CONSTEXPR_ALL -std=c++23 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=constexpr
+// RUN: %clang_cc1 -verify=CONSTEXPR26,CONSTEXPR_ALL -std=c++26 %s 
-fcolor-diagnostics -fcxx-exceptions -DCONSTEXPR=constexpr
+
+// Objective is to make sure features like allocation / throwing won't fail 
code by just adding implicit constexpr
+// in an unevaluated code.
+
+// NORMAL_ALL-no-diagnostics
+// IMPLICIT_ALL-no-diagnostics
+// CONSTEXPR23-no-diagnostics
+// CONSTEXPR26-no-diagnostics
+
+CONSTEXPR inline bool function_with_goto(int v) {
+  if (v == 0) {
+    return true;
+  }
+  
+  goto label;
+  // CONSTEXPR_BEFORE23-warning@-1 {{use of this statement in a constexpr 
function is a C++23 extension}}
+  
+  label:
+  return false;
+}
+
+CONSTEXPR inline bool function_with_label(int v) {
+  label:
+  // CONSTEXPR_BEFORE23-warning@-1 {{use of this statement in a constexpr 
function is a C++23 extension}}
+  if (v > 0) {
+    return true;
+  }
+  v++;
+  goto label;
+}
+
+CONSTEXPR inline bool function_with_try_catch(int v) {
+  try {
+    // CONSTEXPR_BEFORE20-warning@-1 {{use of this statement in a constexpr 
function is a C++20 extension}}
+    return v;
+  } catch (int) {
+    return -v;
+  }
+}
+
+CONSTEXPR inline bool function_with_inline_asm(int v) {
+  if (v > 0) {
+    asm("");
+    // CONSTEXPR_BEFORE20-warning@-1 {{use of this statement in a constexpr 
function is a C++20 extension}}
+  } 
+  
+  return v;
+}
+
+struct easy_type {
+  // CONSTEXPR_BEFORE20-note@-1 {{declared here}}
+  int * x;
+};
+
+CONSTEXPR inline bool function_with_no_initializer_variable(int v) {
+  // CONSTEXPR_BEFORE20-error@-1 {{constexpr function never produces a 
constant expression}}
+  easy_type easy;
+  // CONSTEXPR_BEFORE20-note@-1 {{non-constexpr constructor 'easy_type' cannot 
be used in a constant expression}}
+  return v;
+}
+
+
+
+
diff --git a/clang/test/Sema/implicit-constexpr-members.cpp 
b/clang/test/Sema/implicit-constexpr-members.cpp
new file mode 100644
index 0000000000000..c68df52677dff
--- /dev/null
+++ b/clang/test/Sema/implicit-constexpr-members.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -verify=NORMAL14,BOTH14,ALLNORMAL,ALL -std=c++14 %s 
-fcolor-diagnostics
+// RUN: %clang_cc1 -verify=IMPLICIT14,BOTH14,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++14 %s -fcolor-diagnostics
+
+// RUN: %clang_cc1 -verify=NORMAL17,BOTH20,ALLNORMAL,ALL -std=c++17 %s 
-fcolor-diagnostics
+// RUN: %clang_cc1 -verify=IMPLICIT17,BOTH20,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++17 %s -fcolor-diagnostics
+
+// RUN: %clang_cc1 -verify=NORMAL20,BOTH20,ALLNORMAL,ALL -std=c++20 %s 
-fcolor-diagnostics
+// RUN: %clang_cc1 -verify=IMPLICIT20,BOTH20,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++20 %s -fcolor-diagnostics
+
+// RUN: %clang_cc1 -verify=NORMAL23,BOTH23,ALLNORMAL,ALL -std=c++23 %s 
-fcolor-diagnostics
+// RUN: %clang_cc1 -verify=IMPLICIT23,BOTH23,ALLIMPLICIT,ALL 
-fimplicit-constexpr -std=c++23 %s -fcolor-diagnostics
+
+
+// =============================================
+// 1) simple member function
+
+struct simple_type {
+  bool test() const {
+    // ALLNORMAL-note@-1 {{declared here}}
+    return true;
+  }
+};
+
+constexpr bool result_simple_type = simple_type{}.test();
+// ALLNORMAL-error@-1 {{constexpr variable 'result_simple_type' must be 
initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'test' cannot be used in a 
constant expression}}
+
+#ifdef __cpp_implicit_constexpr
+static_assert(result_simple_type == true, "simple member function must work");
+#endif
+
+
+// =============================================
+// 2) simple member function inside a template
+
+template <typename T> struct template_type {
+  bool test() const {
+    // ALLNORMAL-note@-1 {{declared here}}
+    return true;
+  }
+};
+
+constexpr bool result_template_type = template_type<int>{}.test();
+// ALLNORMAL-error@-1 {{constexpr variable 'result_template_type' must be 
initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'test' cannot be used in a 
constant expression}}
+
+
+// =============================================
+// 3) template member function inside a template
+
+template <typename T> struct template_template_type {
+  template <typename Y> bool test() const {
+    // ALLNORMAL-note@-1 {{declared here}}
+    return true;
+  }
+};
+
+constexpr bool result_template_template_type = 
template_template_type<int>{}.template test<long>();
+// ALLNORMAL-error@-1 {{constexpr variable 'result_template_template_type' 
must be initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'test<long>' cannot be used in a 
constant expression}}
+
+
+#if defined(__cpp_explicit_this_parameter) && __cpp_explicit_this_parameter >= 
202110L
+
+// =============================================
+// 3) explicit "this" function
+
+struct explicit_this {
+  template <typename Self> bool test(this const Self & self) const {
+    // ALLNORMAL-note@-1 {{declared here}}
+    return self.ok;
+  }
+};
+
+struct child: explicit_this {
+  static constexpr bool ok = true;
+};
+
+constexpr bool result_explicit_this = child{}.test();
+// ALLNORMAL-error@-1 {{constexpr variable 'result_explicit_this' must be 
initialized by a constant expression}}
+// ALLNORMAL-note@-2 {{non-constexpr function 'test' cannot be used in a 
constant expression}}
+
+#endif

From a486edc7562ba44e67a50eee3217c39fd9405d90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= <hani...@hanicka.net>
Date: Sun, 20 Apr 2025 00:33:05 +0200
Subject: [PATCH 2/2] [clang] `-fimplicit-constexpr` release notes.

---
 clang/docs/ReleaseNotes.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f5cd1fbeabcfe..be8a7e164e529 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -211,6 +211,8 @@ New Compiler Flags
   The feature has `existed 
<https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program>`_)
   for a while and this is just a user facing option.
 
+- New option ``-fimplicit-constexpr`` which implicitly makes all inlined and 
defined functions ``constexpr``.
+
 Deprecated Compiler Flags
 -------------------------
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to