https://github.com/hanickadot updated https://github.com/llvm/llvm-project/pull/136436
From b8865c8f7eddfd7bfaba1b0f5399ea03c6780070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= <hani...@hanicka.net> Date: Sat, 19 Apr 2025 16:52:33 +0200 Subject: [PATCH] [clang] add -fimplicit-constexpr flag --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/Options.td | 6 +++ clang/include/clang/Sema/Sema.h | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 2 + clang/lib/Sema/SemaDecl.cpp | 10 +++++ clang/test/Sema/implicit-constexpr.cpp | 51 +++++++++++++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 clang/test/Sema/implicit-constexpr.cpp diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 930c1c06d1a76..97527f7a0d1f3 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") +LANGOPT(ImplicitConstexpr, 1, 0, "evaluate everything as it is a constexpr enabled") 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/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 96d81e618494a..603a44bbba910 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2826,6 +2826,7 @@ class Sema final : public SemaBase { bool buildCoroutineParameterMoves(SourceLocation Loc); VarDecl *buildCoroutinePromise(SourceLocation Loc); void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); + void AnalyseCoroutineBody(const CoroutineBodyStmt *); // As a clang extension, enforces that a non-coroutine function must be marked // with [[clang::coro_wrapper]] if it returns a type marked with diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f2f5231933c88..27baf602e2703 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6612,6 +6612,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ); Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ); + 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/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 46933c5c43168..1d4328db4dc41 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10163,6 +10163,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); + + // Clang's option -fimplicit-constexpr will make functions without constexpr + // or consteval specifier implicitly constexpr (compatibility with GCC.) + if (ConstexprKind == ConstexprSpecKind::Unspecified && + getLangOpts().ImplicitConstexpr) { + + NewFD->setConstexprKind(ConstexprSpecKind::Constexpr); + ConstexprKind = ConstexprSpecKind::Constexpr; + } + if (ConstexprKind != ConstexprSpecKind::Unspecified) { // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors // are implicitly inline. diff --git a/clang/test/Sema/implicit-constexpr.cpp b/clang/test/Sema/implicit-constexpr.cpp new file mode 100644 index 0000000000000..4b1314c342361 --- /dev/null +++ b/clang/test/Sema/implicit-constexpr.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -verify=normal,both -std=c++23 %s +// RUN: %clang_cc1 -verify=implicit,both -fimplicit-constexpr -std=c++23 %s + +bool function_test() { // normal-note+ {{declared here}} + return true; +} + +// const variables should work as before +const auto cvar = function_test(); + +constexpr auto constexpr_var = function_test(); // normal-error {{constexpr variable 'constexpr_var' must be initialized by a constant expression}} +// normal-note@-1 {{non-constexpr function 'function_test' cannot be used in a constant expression}} + +static_assert(function_test()); // normal-error {{static assertion expression is not an integral constant expression}} +// normal-note@-1 {{non-constexpr function 'function_test' cannot be used in a constant expression}} + + +struct full_nonconstexpr_type { + full_nonconstexpr_type() { } // normal-note {{declared here}} + ~full_nonconstexpr_type() { } +}; + +constexpr bool constructor_destructor_test() { + full_nonconstexpr_type var{}; // normal-note {{non-constexpr constructor 'full_nonconstexpr_type' cannot be used in a constant expression}} + return true; +} + +static_assert(constructor_destructor_test()); // normal-error {{static assertion expression is not an integral constant expression}} +// normal-note@-1 {{in call to 'constructor_destructor_test()'}} + + +struct only_destructor_type { + constexpr only_destructor_type() { } + ~only_destructor_type() { } // normal-note {{declared here}} +}; + +constexpr bool destructor_test() { + only_destructor_type var{}; // normal-note {{non-constexpr function '~only_destructor_type' cannot be used in a constant expression}} + return true; +} + +static_assert(destructor_test()); // normal-error {{static assertion expression is not an integral constant expression}} +// normal-note@-1 {{in call to 'destructor_test()'}} + + +bool undefined_test(); // both-note {{declared here}} + +static_assert(undefined_test()); // both-error {{static assertion expression is not an integral constant expression}} +// normal-note@-1 {{non-constexpr function 'undefined_test' cannot be used in a constant expressio}} +// implicit-note@-2 {{undefined function 'undefined_test' cannot be used in a constant expression}} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits