Skip to content

Commit

Permalink
[Clang] Static member initializers are not immediate escalating context.
Browse files Browse the repository at this point in the history
Per CWG2760, default members initializers should be consider
part the body of consstructors, which mean they are evaluated
in an immediate escalating context.

However, this does not apply to static members.

This patch produces some extraneous diagnostics, unfortunately
we do not have a good way to report an error back to the
initializer and this is a preexisting issue

Fixes llvm#65985
  • Loading branch information
cor3ntin committed Sep 13, 2023
1 parent 69b056d commit a3390c4
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ Bug Fixes to C++ Support
a non-template inner-class between the function and the class template.
(`#65810 <https://github.com/llvm/llvm-project/issues/65810>`_)

- Fix a crash when calling a non-constant immediate function
in the initializer of a static data member.
(`#65985 <https://github.com/llvm/llvm-project/issues/65985>_`).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed an import failure of recursive friend class template.
Expand Down
12 changes: 10 additions & 2 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3230,13 +3230,21 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
assert(Tok.isOneOf(tok::equal, tok::l_brace) &&
"Data member initializer not starting with '=' or '{'");

bool IsFieldInitialization = isa_and_present<FieldDecl>(D);

EnterExpressionEvaluationContext Context(
Actions,
isa_and_present<FieldDecl>(D)
IsFieldInitialization
? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed
: Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
D);
Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext = true;

// CWG2760
// Default member initializers used to initialize a base or member subobject
// [...] are considered to be part of the function body
Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
IsFieldInitialization;

if (TryConsumeToken(tok::equal, EqualLoc)) {
if (Tok.is(tok::kw_delete)) {
// In principle, an initializer of '= delete p;' is legal, but it will
Expand Down
23 changes: 23 additions & 0 deletions clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,26 @@ struct S {
S s(0); // expected-note {{in the default initializer of 'j'}}

}

namespace GH65985 {

int consteval operator""_foo(unsigned long long V) {
return 0;
}
int consteval operator""_bar(unsigned long long V); // expected-note 3{{here}}

struct C {
static const int a = 1_foo;
static constexpr int b = 1_foo;
static const int c = 1_bar; // expected-error {{call to consteval function 'GH65985::operator""_bar' is not a constant expression}} \
// expected-note {{undefined function 'operator""_bar' cannot be used in a constant expression}} \
// expected-error {{in-class initializer for static data member is not a constant expression}}

// FIXME: remove duplicate diagnostics
static constexpr int d = 1_bar; // expected-error {{call to consteval function 'GH65985::operator""_bar' is not a constant expression}} \
// expected-note {{undefined function 'operator""_bar' cannot be used in a constant expression}} \
// expected-error {{constexpr variable 'd' must be initialized by a constant expression}} \
// expected-note {{undefined function 'operator""_bar' cannot be used in a constant expression}}
};

}

0 comments on commit a3390c4

Please sign in to comment.