Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
57 changes: 53 additions & 4 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ consteval int f1(int i) {
return i;
}

consteval constexpr int f2(int i) {
consteval constexpr int f2(int i) {
//expected-error@-1 {{cannot combine}}
return i;
}
Expand Down Expand Up @@ -195,7 +195,7 @@ auto ptr = ret1(0);
struct A {
consteval int f(int) {
// expected-note@-1+ {{declared here}}
return 0;
return 0;
}
};

Expand Down Expand Up @@ -239,7 +239,7 @@ constexpr int f_c(int i) {
int t = f(i);
// expected-error@-1 {{is not a constant expression}}
// expected-note@-2 {{function parameter}}
return f(0);
return f(0);
}

consteval int f_eval(int i) {
Expand Down Expand Up @@ -675,7 +675,7 @@ Bar<derp> a; // expected-note {{in instantiation of member function 'issue_55601

struct constantDerp {
// Can be used in a constant expression.
consteval constantDerp(int) {}
consteval constantDerp(int) {}
consteval operator int() const { return 5; }
};
Bar<constantDerp> b;
Expand Down Expand Up @@ -1126,4 +1126,53 @@ int test2() { return h{nullptr}; }
// expected-note@-2 {{subobject 'g' is not initialized}}


}

namespace GH65985 {

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

int consteval f() {
return 0;
}

int consteval g(); // expected-note {{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}}

static const int e = f();
static const int f = g(); // expected-error {{call to consteval function 'GH65985::g' is not a constant expression}} \
// expected-error {{in-class initializer for static data member is not a constant expression}} \
// expected-note {{undefined function 'g' cannot be used in a constant expression}}
};

}

namespace GH66562 {

namespace ns
{
consteval int foo(int x) { return 1; } // expected-note {{declared here}}
}

template <class A>
struct T {
static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}}
};

}