https://github.com/llukito updated https://github.com/llvm/llvm-project/pull/179233
>From 6ab49ef74a8de1b59aadad09681cbe62c159e1f7 Mon Sep 17 00:00:00 2001 From: Luka Aladashvili <[email protected]> Date: Mon, 2 Feb 2026 17:38:34 +0400 Subject: [PATCH 1/2] [clang][diagnostics] Refactor constexpr diagnostics to use enum_select Replaces %select{function|constructor} with %enum_select to improve clarity and type safety. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 807440c107897..4d55ef460c928 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -23,9 +23,9 @@ defm typename_outside_of_template : CXX11Compat<"'typename' outside of a templat // C++14 compatibility with C++11 and earlier. defm constexpr_type_definition : CXX14Compat< - "type definition in a constexpr %select{function|constructor}0 is">; + "type definition in a constexpr %enum_select<Function, Constructor>0 is">; defm constexpr_local_var : CXX14Compat< - "variable declaration in a constexpr %select{function|constructor}0 is">; + "variable declaration in a constexpr %enum_select<Function, Constructor>0 is">; defm constexpr_body_multiple_return : CXX14Compat< "multiple return statements in constexpr function is">; defm variable_template : CXX14Compat<"variable templates are">; @@ -38,9 +38,9 @@ defm inline_variable : CXX17Compat<"inline variables are">; defm decomp_decl_spec : CXX20Compat<"structured binding declaration declared '%0' is">; defm constexpr_local_var_no_init : CXX20Compat< - "uninitialized variable in a constexpr %select{function|constructor}0 is">; + "uninitialized variable in a constexpr %enum_select<Function, Constructor>0 is">; defm constexpr_function_try_block : CXX20Compat< - "function try block in constexpr %select{function|constructor}0 is">; + "function try block in constexpr %enum_select<Function, Constructor>0 is">; defm constexpr_union_ctor_no_init : CXX20Compat< "constexpr union constructor that does not initialize any member is">; defm constexpr_ctor_missing_init : CXX20Compat< @@ -56,7 +56,7 @@ defm implicit_typename // C++23 compatibility with C++20 and earlier. defm constexpr_static_var : CXX23Compat< "definition of a %select{static|thread_local}1 variable " - "in a constexpr %select{function|constructor}0 " + "in a constexpr %enum_select<Function, Constructor>0 " "is">; // C++26 compatibility with C++23 and earlier. @@ -65,7 +65,7 @@ defm decomp_decl_cond : CXX26Compat<"structured binding declaration in a conditi // Compatibility warnings duplicated across multiple language versions. foreach std = [14, 20, 23] in { defm cxx#std#_constexpr_body_invalid_stmt : CXXCompat< - "use of this statement in a constexpr %select{function|constructor}0 is", std>; + "use of this statement in a constexpr %enum_select<Function, Constructor>0 is", std>; } def note_previous_decl : Note<"%0 declared here">; >From 71e1f6b3df0179dcebec2fc5fa1771fb7ae4be9c Mon Sep 17 00:00:00 2001 From: Luka Aladashvili <[email protected]> Date: Mon, 2 Feb 2026 18:33:57 +0400 Subject: [PATCH 2/2] Fix constexpr indentation and logic --- clang/lib/Sema/SemaDeclCXX.cpp | 35 ++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 5837ecd6b9163..3b20a254c4a60 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2073,33 +2073,39 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, // thread storage duration or [before C++2a] for which no // initialization is performed. const auto *VD = cast<VarDecl>(DclIt); + + // Define the enum UP HERE so it is visible to all the checks below + enum { Function, Constructor }; + if (VD->isThisDeclarationADefinition()) { if (VD->isStaticLocal()) { if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.DiagCompat(VD->getLocation(), diag_compat::constexpr_static_var) - << isa<CXXConstructorDecl>(Dcl) + << (isa<CXXConstructorDecl>(Dcl) ? Constructor : Function) << (VD->getTLSKind() == VarDecl::TLS_Dynamic); } else if (!SemaRef.getLangOpts().CPlusPlus23) { return false; } } + if (SemaRef.LangOpts.CPlusPlus23) { CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(), diag::warn_cxx20_compat_constexpr_var, - isa<CXXConstructorDecl>(Dcl)); + isa<CXXConstructorDecl>(Dcl) ? Constructor + : Function); } else if (CheckLiteralType( SemaRef, Kind, VD->getLocation(), VD->getType(), diag::err_constexpr_local_var_non_literal_type, - isa<CXXConstructorDecl>(Dcl))) { + isa<CXXConstructorDecl>(Dcl) ? Constructor : Function)) { return false; } - if (!VD->getType()->isDependentType() && - !VD->hasInit() && !VD->isCXXForRangeDecl()) { + if (!VD->getType()->isDependentType() && !VD->hasInit() && + !VD->isCXXForRangeDecl()) { if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.DiagCompat(VD->getLocation(), diag_compat::constexpr_local_var_no_init) - << isa<CXXConstructorDecl>(Dcl); + << (isa<CXXConstructorDecl>(Dcl) ? Constructor : Function); } else if (!SemaRef.getLangOpts().CPlusPlus20) { return false; } @@ -2108,7 +2114,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, } if (Kind == Sema::CheckConstexprKind::Diagnose) { SemaRef.DiagCompat(VD->getLocation(), diag_compat::constexpr_local_var) - << isa<CXXConstructorDecl>(Dcl); + << (isa<CXXConstructorDecl>(Dcl) ? Constructor : Function); } else if (!SemaRef.getLangOpts().CPlusPlus14) { return false; } @@ -2382,6 +2388,10 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, // // This restriction is lifted in C++2a, as long as inner statements also // apply the general constexpr rules. + + // <--- START FIX + enum { Function, Constructor }; // Defined locally for this block + switch (Kind) { case Sema::CheckConstexprKind::CheckValid: if (!SemaRef.getLangOpts().CPlusPlus20) @@ -2391,11 +2401,12 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, case Sema::CheckConstexprKind::Diagnose: SemaRef.DiagCompat(Body->getBeginLoc(), diag_compat::constexpr_function_try_block) - << isa<CXXConstructorDecl>(Dcl); + << (isa<CXXConstructorDecl>(Dcl) ? Constructor : Function); break; } + // <--- END FIX } - + // - its function-body shall be [...] a compound-statement that contains only // [... list of cases ...] // @@ -2502,10 +2513,14 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, break; } } else if (ReturnStmts.size() > 1) { + // Define the enum locally again because the previous one is out of scope + enum { Function, Constructor }; + switch (Kind) { case Sema::CheckConstexprKind::Diagnose: SemaRef.DiagCompat(ReturnStmts.back(), - diag_compat::constexpr_body_multiple_return); + diag_compat::constexpr_body_multiple_return) + << (isa<CXXConstructorDecl>(Dcl) ? Constructor : Function); for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I) SemaRef.Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
