[clang] Don't wrap immediate invocations in ConstantExprs within constexpr initializers (PR #89565)
Daniel M. Katz via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 26 11:41:28 PDT 2024
https://github.com/katzdm updated https://github.com/llvm/llvm-project/pull/89565
>From 218ffb6d5a03c96d46bfecdb4490277809f5b62e Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Tue, 16 Apr 2024 17:14:50 -0400
Subject: [PATCH 1/7] Fix bug with constexpr initialization.
---
clang/lib/Parse/ParseDecl.cpp | 12 ++++++++++-
clang/test/CXX/expr/expr.const/p6-2a.cpp | 7 +++----
clang/test/SemaCXX/builtin_vectorelements.cpp | 4 ++--
clang/test/SemaCXX/cxx2a-consteval.cpp | 20 ++++++++-----------
clang/unittests/Support/TimeProfilerTest.cpp | 1 -
5 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 05ad5ecbfaa0cf..d71dfaf20a793b 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2552,6 +2552,13 @@ Decl *Parser::ParseDeclarationAfterDeclarator(
return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
}
+static bool isConstexprVariable(const Decl *D) {
+ if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
+ return Var->isConstexpr();
+
+ return false;
+}
+
Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
// RAII type used to track whether we're inside an initializer.
@@ -2559,9 +2566,12 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Parser &P;
Declarator &D;
Decl *ThisDecl;
+ llvm::SaveAndRestore<bool> ConstantContext;
InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
- : P(P), D(D), ThisDecl(ThisDecl) {
+ : P(P), D(D), ThisDecl(ThisDecl),
+ ConstantContext(P.Actions.isConstantEvaluatedOverride,
+ isConstexprVariable(ThisDecl)) {
if (ThisDecl && P.getLangOpts().CPlusPlus) {
Scope *S = nullptr;
if (D.getCXXScopeSpec().isSet()) {
diff --git a/clang/test/CXX/expr/expr.const/p6-2a.cpp b/clang/test/CXX/expr/expr.const/p6-2a.cpp
index a937474d53b221..8b940b2ee9fb2a 100644
--- a/clang/test/CXX/expr/expr.const/p6-2a.cpp
+++ b/clang/test/CXX/expr/expr.const/p6-2a.cpp
@@ -43,12 +43,11 @@ struct Temporary {
constexpr Temporary t = {3}; // expected-error {{must have constant destruction}} expected-note {{created here}} expected-note {{in call}}
namespace P1073R3 {
-consteval int f() { return 42; } // expected-note 2 {{declared here}}
+consteval int f() { return 42; } // expected-note {{declared here}}
consteval auto g() { return f; }
consteval int h(int (*p)() = g()) { return p(); }
constexpr int r = h();
-constexpr auto e = g(); // expected-error {{call to consteval function 'P1073R3::g' is not a constant expression}} \
- expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \
- expected-note 2 {{pointer to a consteval declaration is not a constant expression}}
+constexpr auto e = g(); // expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \
+ expected-note {{pointer to a consteval declaration is not a constant expression}}
static_assert(r == 42);
} // namespace P1073R3
diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp
index 59ff09ac72e42d..12f2cbe57bd47d 100644
--- a/clang/test/SemaCXX/builtin_vectorelements.cpp
+++ b/clang/test/SemaCXX/builtin_vectorelements.cpp
@@ -42,11 +42,11 @@ void test_builtin_vectorelements() {
#include <arm_sve.h>
consteval int consteval_elements() { // expected-error {{consteval function never produces a constant expression}}
- return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
+ return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
}
void test_bad_constexpr() {
- constexpr int eval = consteval_elements(); // expected-error {{initialized by a constant expression}} // expected-error {{not a constant expression}} // expected-note {{in call}} // expected-note {{in call}}
+ constexpr int eval = consteval_elements(); // expected-error {{initialized by a constant expression}} // expected-note {{in call}}
constexpr int i32 = __builtin_vectorelements(svuint32_t); // expected-error {{initialized by a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
constexpr int i16p8 = __builtin_vectorelements(svuint16_t) + 16; // expected-error {{initialized by a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
constexpr int lambda = [] { return __builtin_vectorelements(svuint16_t); }(); // expected-error {{initialized by a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{in call}}
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index e198074372072d..22bef4774a108a 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -733,7 +733,7 @@ constexpr derp d;
struct test {
consteval int operator[](int i) const { return {}; }
consteval const derp * operator->() const { return &d; }
- consteval int f() const { return 12; } // expected-note 2{{declared here}}
+ consteval int f() const { return 12; } // expected-note {{declared here}}
};
constexpr test a;
@@ -746,8 +746,7 @@ constexpr int s = a.operator[](1);
constexpr int t = a[1];
constexpr int u = a.operator->()->b;
constexpr int v = a->b;
-// FIXME: I believe this case should work, but we currently reject.
-constexpr int w = (a.*&test::f)(); // expected-error {{cannot take address of consteval function 'f' outside of an immediate invocation}}
+constexpr int w = (a.*&test::f)();
constexpr int x = a.f();
// Show that we reject when not in an immediate context.
@@ -1052,17 +1051,15 @@ int f() {
namespace GH57682 {
void test() {
- constexpr auto l1 = []() consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \
- // expected-note 2{{declared here}}
+ constexpr auto l1 = []() consteval { // expected-note {{declared here}}
return 3;
};
constexpr int (*f1)(void) = l1; // expected-error {{constexpr variable 'f1' must be initialized by a constant expression}} \
// expected-note {{pointer to a consteval declaration is not a constant expression}}
- constexpr auto lstatic = []() static consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \
- // expected-note 2{{declared here}} \
- // expected-warning {{extension}}
+ constexpr auto lstatic = []() static consteval { // expected-note {{declared here}} \
+ // expected-warning {{extension}}
return 3;
};
constexpr int (*f2)(void) = lstatic; // expected-error {{constexpr variable 'f2' must be initialized by a constant expression}} \
@@ -1093,7 +1090,7 @@ struct tester {
consteval const char* make_name(const char* name) { return name;}
consteval const char* pad(int P) { return "thestring"; }
-int bad = 10; // expected-note 6{{declared here}}
+int bad = 10; // expected-note 5{{declared here}}
tester glob1(make_name("glob1"));
tester glob2(make_name("glob2"));
@@ -1102,9 +1099,8 @@ tester paddedglob(make_name(pad(bad))); // expected-error {{call to consteval fu
// expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
constexpr tester glob3 = { make_name("glob3") };
-constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
- // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \
- // expected-note 2{{read of non-const variable 'bad' is not allowed in a constant expression}}
+constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \
+ // expected-note 1{{read of non-const variable 'bad' is not allowed in a constant expression}}
auto V = make_name(pad(3));
auto V1 = make_name(pad(bad)); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp
index 97fdbb7232b135..9c1a955743f1ee 100644
--- a/clang/unittests/Support/TimeProfilerTest.cpp
+++ b/clang/unittests/Support/TimeProfilerTest.cpp
@@ -193,7 +193,6 @@ Frontend
| ParseDeclarationOrFunctionDefinition (test.cc:16:1)
| | ParseFunctionDefinition (slow_test)
| | | EvaluateAsInitializer (slow_value)
-| | | EvaluateAsConstantExpr (<test.cc:17:33, col:59>)
| | | EvaluateAsConstantExpr (<test.cc:18:11, col:37>)
| ParseDeclarationOrFunctionDefinition (test.cc:22:1)
| | EvaluateAsConstantExpr (<test.cc:23:31, col:57>)
>From 8cd385f005865eeb0ee66890303c2dbf8479775a Mon Sep 17 00:00:00 2001
From: "Daniel M. Katz" <katzdm at gmail.com>
Date: Mon, 22 Apr 2024 08:59:55 -0400
Subject: [PATCH 2/7] Use dyn_cast without checking for null
Co-authored-by: cor3ntin <corentinjabot at gmail.com>
---
clang/lib/Parse/ParseDecl.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index d71dfaf20a793b..1332ca114dbfc9 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2553,7 +2553,7 @@ Decl *Parser::ParseDeclarationAfterDeclarator(
}
static bool isConstexprVariable(const Decl *D) {
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
+ if (const VarDecl *Var = dyn_cast<VarDecl>(D))
return Var->isConstexpr();
return false;
>From 76ca0e07f170e3dd04b86c3a20b3f1f109759339 Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Mon, 22 Apr 2024 09:01:48 -0400
Subject: [PATCH 3/7] Add 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 5d4d152b2eb540..eb930a0e5a37b5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -593,6 +593,8 @@ Bug Fixes to C++ Support
- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)
- Fixed bug in which the body of a consteval lambda within a template was not parsed as within an
immediate function context.
+- Fix a bug in which valid constexpr variable initializers containing immediate function calls were
+ sometimes diagnosed as not constant expressions.
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
>From 502686358a726747d467d7940ba2cd0fc8585d1a Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Mon, 22 Apr 2024 12:38:11 -0400
Subject: [PATCH 4/7] Re-introduce null check. Use EvaluationContext instead of
override.
---
clang/lib/Parse/ParseDecl.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 1332ca114dbfc9..b7514d417a1128 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2553,7 +2553,7 @@ Decl *Parser::ParseDeclarationAfterDeclarator(
}
static bool isConstexprVariable(const Decl *D) {
- if (const VarDecl *Var = dyn_cast<VarDecl>(D))
+ if (const VarDecl *Var = dyn_cast_if_present<VarDecl>(D))
return Var->isConstexpr();
return false;
@@ -2566,12 +2566,13 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Parser &P;
Declarator &D;
Decl *ThisDecl;
- llvm::SaveAndRestore<bool> ConstantContext;
+ EnterExpressionEvaluationContext EC;
InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
: P(P), D(D), ThisDecl(ThisDecl),
- ConstantContext(P.Actions.isConstantEvaluatedOverride,
- isConstexprVariable(ThisDecl)) {
+ EC(P.Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated,
+ ThisDecl, Sema::ExpressionEvaluationContextRecord::EK_Other,
+ isConstexprVariable(ThisDecl)) {
if (ThisDecl && P.getLangOpts().CPlusPlus) {
Scope *S = nullptr;
if (D.getCXXScopeSpec().isSet()) {
>From 9f98e403e221d36f29e2d8dced274de349ebd0dd Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Mon, 22 Apr 2024 13:28:03 -0400
Subject: [PATCH 5/7] Adjust other tests newly failing from change.
---
clang/test/AST/Interp/intap.cpp | 3 +--
clang/test/CXX/expr/expr.const/p2-0x.cpp | 4 ++--
clang/test/Parser/pragma-fenv_access.c | 3 ---
clang/test/SemaCXX/constant-expression-cxx11.cpp | 2 +-
clang/test/SemaCXX/cxx2a-consteval.cpp | 14 ++++++++------
clang/test/SemaCXX/ext-int.cpp | 2 +-
6 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/Interp/intap.cpp
index d4440124856915..1b8ec2dfdab79e 100644
--- a/clang/test/AST/Interp/intap.cpp
+++ b/clang/test/AST/Interp/intap.cpp
@@ -9,8 +9,7 @@ using MaxBitInt = _BitInt(128);
constexpr _BitInt(2) A = 0;
constexpr _BitInt(2) B = A + 1;
-constexpr _BitInt(2) C = B + 1; // expected-warning {{from 2 to -2}} \
- // ref-warning {{from 2 to -2}}
+constexpr _BitInt(2) C = B + 1;
static_assert(C == -2, "");
static_assert(C - B == A, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{value -3 is outside the range of representable values}} \
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index e3cd057baba75f..86b9b066d6867f 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -244,8 +244,8 @@ namespace UndefinedBehavior {
constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }}
constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }}
constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }}
- constexpr signed char c1 = 100 * 2; // ok expected-warning{{changes value}}
- constexpr signed char c2 = '\x64' * '\2'; // also ok expected-warning{{changes value}}
+ constexpr signed char c1 = 100 * 2; // ok - no error from changing value because initializer is constexpr.
+ constexpr signed char c2 = '\x64' * '\2'; // also ok - no error from changing value because initializer is constexpr.
constexpr long long ll1 = 0x7fffffffffffffff; // ok
constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }}
constexpr long long ll3 = -ll1 - 1; // ok
diff --git a/clang/test/Parser/pragma-fenv_access.c b/clang/test/Parser/pragma-fenv_access.c
index 76256cff1b49b5..86d40bbab4be93 100644
--- a/clang/test/Parser/pragma-fenv_access.c
+++ b/clang/test/Parser/pragma-fenv_access.c
@@ -32,9 +32,6 @@ int main(void) {
CONST int not_too_big = 255;
CONST float fnot_too_big = not_too_big;
CONST int too_big = 0x7ffffff0;
-#if defined(CPP)
-//expected-warning at +2{{implicit conversion}}
-#endif
CONST float fbig = too_big; // inexact
#if !defined(CPP)
#define static_assert _Static_assert
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index efb391ba0922d8..815d2e1651d4ac 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1961,7 +1961,7 @@ namespace ConstexprConstructorRecovery {
namespace Lifetime {
void f() {
- constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} expected-warning {{not yet bound to a value}}
+ constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}}
constexpr int m = m; // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}}
}
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 22bef4774a108a..39be55810d2b24 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -1051,21 +1051,23 @@ int f() {
namespace GH57682 {
void test() {
- constexpr auto l1 = []() consteval { // expected-note {{declared here}}
+ constexpr auto l1 = []() consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \
+ // expected-note 2 {{declared here}}
return 3;
};
- constexpr int (*f1)(void) = l1; // expected-error {{constexpr variable 'f1' must be initialized by a constant expression}} \
- // expected-note {{pointer to a consteval declaration is not a constant expression}}
+ int (*f1)(void) = l1;
+
+ constexpr int (*f2)(void) = l1; // expected-error {{constexpr variable 'f2' must be initialized by a constant expression}} \
+ // expected-note {{pointer to a consteval declaration is not a constant expression}}
constexpr auto lstatic = []() static consteval { // expected-note {{declared here}} \
// expected-warning {{extension}}
return 3;
};
- constexpr int (*f2)(void) = lstatic; // expected-error {{constexpr variable 'f2' must be initialized by a constant expression}} \
+ constexpr int (*f3)(void) = lstatic; // expected-error {{constexpr variable 'f3' must be initialized by a constant expression}} \
// expected-note {{pointer to a consteval declaration is not a constant expression}}
-
-}
+ };
}
namespace GH60286 {
diff --git a/clang/test/SemaCXX/ext-int.cpp b/clang/test/SemaCXX/ext-int.cpp
index 000b871ccd3433..931842b7e3c53b 100644
--- a/clang/test/SemaCXX/ext-int.cpp
+++ b/clang/test/SemaCXX/ext-int.cpp
@@ -25,7 +25,7 @@ _BitInt(33) Declarations(_BitInt(48) &Param) { // Useable in params and returns.
unsigned _BitInt(1) l;
signed _BitInt(1) m; // expected-error{{signed _BitInt must have a bit size of at least 2}}
- constexpr _BitInt(6) n = 33; // expected-warning{{implicit conversion from 'int' to 'const _BitInt(6)' changes value from 33 to -31}}
+ constexpr _BitInt(6) n = 33;
constexpr _BitInt(7) o = 33;
// Check imposed max size.
>From ec17c7668650add013f321453007191740e144e6 Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Thu, 25 Apr 2024 11:40:35 -0400
Subject: [PATCH 6/7] Addressing feedback. Redesigning proposed solution.
---
clang/docs/ReleaseNotes.rst | 6 ++-
clang/include/clang/Sema/Sema.h | 4 +-
clang/lib/Parse/ParseDecl.cpp | 32 ++++---------
clang/lib/Sema/SemaChecking.cpp | 4 +-
clang/lib/Sema/SemaDeclCXX.cpp | 47 +++++++++----------
clang/lib/Sema/SemaExpr.cpp | 1 +
clang/test/AST/Interp/intap.cpp | 3 +-
clang/test/CXX/expr/expr.const/p2-0x.cpp | 4 +-
clang/test/CXX/expr/expr.const/p6-2a.cpp | 7 +--
clang/test/Parser/pragma-fenv_access.c | 3 ++
clang/test/SemaCXX/builtin_vectorelements.cpp | 4 +-
.../SemaCXX/constant-expression-cxx11.cpp | 2 +-
clang/test/SemaCXX/cxx2a-consteval.cpp | 44 ++++++++++-------
.../SemaCXX/cxx2b-consteval-propagate.cpp | 26 ++++++++++
clang/test/SemaCXX/enum-scoped.cpp | 1 +
clang/test/SemaCXX/ext-int.cpp | 2 +-
clang/unittests/Support/TimeProfilerTest.cpp | 1 +
17 files changed, 113 insertions(+), 78 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index eb930a0e5a37b5..1f388916a81163 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -593,8 +593,10 @@ Bug Fixes to C++ Support
- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)
- Fixed bug in which the body of a consteval lambda within a template was not parsed as within an
immediate function context.
-- Fix a bug in which valid constexpr variable initializers containing immediate function calls were
- sometimes diagnosed as not constant expressions.
+- Fix a C++23 bug in implementation of P2564R3 which evaluates immediate invocations in place
+ within initializers for variables that are usable in constant expressions or are constant
+ initialized, rather than evaluating them as a part of the larger manifestly constant evaluated
+ expression.
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1ca523ec88c2f9..28eee463ba2e71 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10201,7 +10201,9 @@ class Sema final : public SemaBase {
S.ExprEvalContexts.back().InImmediateFunctionContext =
FD->isImmediateFunction() ||
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
- .isConstantEvaluated();
+ .isConstantEvaluated() ||
+ S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
+ .isImmediateFunctionContext();
S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
} else
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index b7514d417a1128..b603d2695487a7 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2552,13 +2552,6 @@ Decl *Parser::ParseDeclarationAfterDeclarator(
return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
}
-static bool isConstexprVariable(const Decl *D) {
- if (const VarDecl *Var = dyn_cast_if_present<VarDecl>(D))
- return Var->isConstexpr();
-
- return false;
-}
-
Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
// RAII type used to track whether we're inside an initializer.
@@ -2566,29 +2559,30 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Parser &P;
Declarator &D;
Decl *ThisDecl;
- EnterExpressionEvaluationContext EC;
+ bool Entered;
InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
- : P(P), D(D), ThisDecl(ThisDecl),
- EC(P.Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated,
- ThisDecl, Sema::ExpressionEvaluationContextRecord::EK_Other,
- isConstexprVariable(ThisDecl)) {
+ : P(P), D(D), ThisDecl(ThisDecl), Entered(false) {
if (ThisDecl && P.getLangOpts().CPlusPlus) {
Scope *S = nullptr;
if (D.getCXXScopeSpec().isSet()) {
P.EnterScope(0);
S = P.getCurScope();
}
- P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
+ if (ThisDecl && !ThisDecl->isInvalidDecl()) {
+ P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
+ Entered = true;
+ }
}
}
- ~InitializerScopeRAII() { pop(); }
- void pop() {
+ ~InitializerScopeRAII() {
if (ThisDecl && P.getLangOpts().CPlusPlus) {
Scope *S = nullptr;
if (D.getCXXScopeSpec().isSet())
S = P.getCurScope();
- P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
+
+ if (Entered)
+ P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
if (S)
P.ExitScope();
}
@@ -2719,8 +2713,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
FRI->RangeExpr = Init;
}
- InitScope.pop();
-
if (Init.isInvalid()) {
SmallVector<tok::TokenKind, 2> StopTokens;
StopTokens.push_back(tok::comma);
@@ -2768,8 +2760,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
bool SawError = ParseExpressionList(Exprs, ExpressionStarts);
- InitScope.pop();
-
if (SawError) {
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceConstructorSignatureHelp(
@@ -2801,8 +2791,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
ExprResult Init(ParseBraceInitializer());
- InitScope.pop();
-
if (Init.isInvalid()) {
Actions.ActOnInitializerError(ThisDecl);
} else
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e33113ab9c4c1d..8d078c23e5bbbe 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16548,8 +16548,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
std::string PrettySourceValue = toString(Value, 10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
- S.DiagRuntimeBehavior(
- E->getExprLoc(), E,
+ S.Diag(
+ E->getExprLoc(),
S.PDiag(diag::warn_impcast_integer_precision_constant)
<< PrettySourceValue << PrettyTargetValue << E->getType() << T
<< E->getSourceRange() << SourceRange(CC));
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index abdbc9d8830c03..e3d0efe6876cf0 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18545,15 +18545,6 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
Diag(D->getLocation(), diag::err_illegal_initializer);
}
-/// Determine whether the given declaration is a global variable or
-/// static data member.
-static bool isNonlocalVariable(const Decl *D) {
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
- return Var->hasGlobalStorage();
-
- return false;
-}
-
/// Invoked when we are about to parse an initializer for the declaration
/// 'Dcl'.
///
@@ -18562,9 +18553,7 @@ static bool isNonlocalVariable(const Decl *D) {
/// class X. If the declaration had a scope specifier, a scope will have
/// been created and passed in for this purpose. Otherwise, S will be null.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
- // If there is no declaration, there was an error parsing it.
- if (!D || D->isInvalidDecl())
- return;
+ assert(D && !D->isInvalidDecl());
// We will always have a nested name specifier here, but this declaration
// might not be out of line if the specifier names the current namespace:
@@ -18573,25 +18562,35 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
if (S && D->isOutOfLine())
EnterDeclaratorContext(S, D->getDeclContext());
- // If we are parsing the initializer for a static data member, push a
- // new expression evaluation context that is associated with this static
- // data member.
- if (isNonlocalVariable(D))
- PushExpressionEvaluationContext(
- ExpressionEvaluationContext::PotentiallyEvaluated, D);
+ PushExpressionEvaluationContext(
+ ExpressionEvaluationContext::PotentiallyEvaluated, D);
}
/// Invoked after we are finished parsing an initializer for the declaration D.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
- // If there is no declaration, there was an error parsing it.
- if (!D || D->isInvalidDecl())
- return;
-
- if (isNonlocalVariable(D))
- PopExpressionEvaluationContext();
+ assert(D);
if (S && D->isOutOfLine())
ExitDeclaratorContext(S);
+
+ if (getLangOpts().CPlusPlus23) {
+ // An expression or conversion is 'manifestly constant-evaluated' if it is:
+ // [...]
+ // - the initializer of a variable that is usable in constant expressions or
+ // has constant initialization.
+ if (auto *VD = dyn_cast<VarDecl>(D);
+ VD && (VD->isUsableInConstantExpressions(Context) ||
+ VD->hasConstantInitialization())) {
+ // An expression or conversion is in an 'immediate function context' if it
+ // is potentially evaluated and either:
+ // [...]
+ // - it is a subexpression of a manifestly constant-evaluated expression or
+ // conversion.
+ ExprEvalContexts.back().InImmediateFunctionContext = true;
+ }
+ }
+
+ PopExpressionEvaluationContext();
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 50f92c496a539a..1758eebcebac73 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18011,6 +18011,7 @@ HandleImmediateInvocations(Sema &SemaRef,
Sema::ExpressionEvaluationContextRecord &Rec) {
if ((Rec.ImmediateInvocationCandidates.size() == 0 &&
Rec.ReferenceToConsteval.size() == 0) ||
+ Rec.isImmediateFunctionContext() ||
SemaRef.RebuildingImmediateInvocation)
return;
diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/Interp/intap.cpp
index 1b8ec2dfdab79e..d4440124856915 100644
--- a/clang/test/AST/Interp/intap.cpp
+++ b/clang/test/AST/Interp/intap.cpp
@@ -9,7 +9,8 @@ using MaxBitInt = _BitInt(128);
constexpr _BitInt(2) A = 0;
constexpr _BitInt(2) B = A + 1;
-constexpr _BitInt(2) C = B + 1;
+constexpr _BitInt(2) C = B + 1; // expected-warning {{from 2 to -2}} \
+ // ref-warning {{from 2 to -2}}
static_assert(C == -2, "");
static_assert(C - B == A, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{value -3 is outside the range of representable values}} \
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 86b9b066d6867f..e3cd057baba75f 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -244,8 +244,8 @@ namespace UndefinedBehavior {
constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }}
constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }}
constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }}
- constexpr signed char c1 = 100 * 2; // ok - no error from changing value because initializer is constexpr.
- constexpr signed char c2 = '\x64' * '\2'; // also ok - no error from changing value because initializer is constexpr.
+ constexpr signed char c1 = 100 * 2; // ok expected-warning{{changes value}}
+ constexpr signed char c2 = '\x64' * '\2'; // also ok expected-warning{{changes value}}
constexpr long long ll1 = 0x7fffffffffffffff; // ok
constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }}
constexpr long long ll3 = -ll1 - 1; // ok
diff --git a/clang/test/CXX/expr/expr.const/p6-2a.cpp b/clang/test/CXX/expr/expr.const/p6-2a.cpp
index 8b940b2ee9fb2a..a937474d53b221 100644
--- a/clang/test/CXX/expr/expr.const/p6-2a.cpp
+++ b/clang/test/CXX/expr/expr.const/p6-2a.cpp
@@ -43,11 +43,12 @@ struct Temporary {
constexpr Temporary t = {3}; // expected-error {{must have constant destruction}} expected-note {{created here}} expected-note {{in call}}
namespace P1073R3 {
-consteval int f() { return 42; } // expected-note {{declared here}}
+consteval int f() { return 42; } // expected-note 2 {{declared here}}
consteval auto g() { return f; }
consteval int h(int (*p)() = g()) { return p(); }
constexpr int r = h();
-constexpr auto e = g(); // expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \
- expected-note {{pointer to a consteval declaration is not a constant expression}}
+constexpr auto e = g(); // expected-error {{call to consteval function 'P1073R3::g' is not a constant expression}} \
+ expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \
+ expected-note 2 {{pointer to a consteval declaration is not a constant expression}}
static_assert(r == 42);
} // namespace P1073R3
diff --git a/clang/test/Parser/pragma-fenv_access.c b/clang/test/Parser/pragma-fenv_access.c
index 86d40bbab4be93..76256cff1b49b5 100644
--- a/clang/test/Parser/pragma-fenv_access.c
+++ b/clang/test/Parser/pragma-fenv_access.c
@@ -32,6 +32,9 @@ int main(void) {
CONST int not_too_big = 255;
CONST float fnot_too_big = not_too_big;
CONST int too_big = 0x7ffffff0;
+#if defined(CPP)
+//expected-warning at +2{{implicit conversion}}
+#endif
CONST float fbig = too_big; // inexact
#if !defined(CPP)
#define static_assert _Static_assert
diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp
index 12f2cbe57bd47d..59ff09ac72e42d 100644
--- a/clang/test/SemaCXX/builtin_vectorelements.cpp
+++ b/clang/test/SemaCXX/builtin_vectorelements.cpp
@@ -42,11 +42,11 @@ void test_builtin_vectorelements() {
#include <arm_sve.h>
consteval int consteval_elements() { // expected-error {{consteval function never produces a constant expression}}
- return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
+ return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
}
void test_bad_constexpr() {
- constexpr int eval = consteval_elements(); // expected-error {{initialized by a constant expression}} // expected-note {{in call}}
+ constexpr int eval = consteval_elements(); // expected-error {{initialized by a constant expression}} // expected-error {{not a constant expression}} // expected-note {{in call}} // expected-note {{in call}}
constexpr int i32 = __builtin_vectorelements(svuint32_t); // expected-error {{initialized by a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
constexpr int i16p8 = __builtin_vectorelements(svuint16_t) + 16; // expected-error {{initialized by a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
constexpr int lambda = [] { return __builtin_vectorelements(svuint16_t); }(); // expected-error {{initialized by a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{in call}}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 815d2e1651d4ac..efb391ba0922d8 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1961,7 +1961,7 @@ namespace ConstexprConstructorRecovery {
namespace Lifetime {
void f() {
- constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}}
+ constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} expected-warning {{not yet bound to a value}}
constexpr int m = m; // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}}
}
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 39be55810d2b24..622ec31c459ddf 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -733,7 +733,7 @@ constexpr derp d;
struct test {
consteval int operator[](int i) const { return {}; }
consteval const derp * operator->() const { return &d; }
- consteval int f() const { return 12; } // expected-note {{declared here}}
+ consteval int f() const { return 12; } // expected-note 2{{declared here}}
};
constexpr test a;
@@ -746,7 +746,8 @@ constexpr int s = a.operator[](1);
constexpr int t = a[1];
constexpr int u = a.operator->()->b;
constexpr int v = a->b;
-constexpr int w = (a.*&test::f)();
+// FIXME: I believe this case should work, but we currently reject.
+constexpr int w = (a.*&test::f)(); // expected-error {{cannot take address of consteval function 'f' outside of an immediate invocation}}
constexpr int x = a.f();
// Show that we reject when not in an immediate context.
@@ -1052,22 +1053,30 @@ int f() {
namespace GH57682 {
void test() {
constexpr auto l1 = []() consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \
- // expected-note 2 {{declared here}}
+ // expected-note 2{{declared here}}
return 3;
};
-
- int (*f1)(void) = l1;
-
- constexpr int (*f2)(void) = l1; // expected-error {{constexpr variable 'f2' must be initialized by a constant expression}} \
+ constexpr int (*f1)(void) = l1; // expected-error {{constexpr variable 'f1' must be initialized by a constant expression}} \
// expected-note {{pointer to a consteval declaration is not a constant expression}}
- constexpr auto lstatic = []() static consteval { // expected-note {{declared here}} \
- // expected-warning {{extension}}
+
+ constexpr auto lstatic = []() static consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \
+ // expected-note 2{{declared here}} \
+ // expected-warning {{extension}}
return 3;
};
- constexpr int (*f3)(void) = lstatic; // expected-error {{constexpr variable 'f3' must be initialized by a constant expression}} \
+ constexpr int (*f2)(void) = lstatic; // expected-error {{constexpr variable 'f2' must be initialized by a constant expression}} \
// expected-note {{pointer to a consteval declaration is not a constant expression}}
- };
+
+ int (*f3)(void) = []() consteval { return 3; }; // expected-error {{cannot take address of consteval call operator of '(lambda at}} \
+ // expected-note {{declared here}}
+}
+
+consteval void consteval_test() {
+ constexpr auto l1 = []() consteval { return 3; };
+
+ int (*f1)(void) = l1; // ok
+}
}
namespace GH60286 {
@@ -1092,17 +1101,18 @@ struct tester {
consteval const char* make_name(const char* name) { return name;}
consteval const char* pad(int P) { return "thestring"; }
-int bad = 10; // expected-note 5{{declared here}}
+int bad = 10; // expected-note 6{{declared here}}
tester glob1(make_name("glob1"));
tester glob2(make_name("glob2"));
constexpr tester cglob(make_name("cglob"));
-tester paddedglob(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+tester paddedglob(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \
// expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
constexpr tester glob3 = { make_name("glob3") };
-constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \
- // expected-note 1{{read of non-const variable 'bad' is not allowed in a constant expression}}
+constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \
+ // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \
+ // expected-note 2{{read of non-const variable 'bad' is not allowed in a constant expression}}
auto V = make_name(pad(3));
auto V1 = make_name(pad(bad)); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
@@ -1112,12 +1122,12 @@ auto V1 = make_name(pad(bad)); // expected-error {{call to consteval function 'G
void foo() {
static tester loc1(make_name("loc1"));
static constexpr tester loc2(make_name("loc2"));
- static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \
// expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
}
void bar() {
- static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::tester::tester' is not a constant expression}} \
// expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
}
}
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index 4a75392045d05a..37fa1f1bdf59db 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -394,3 +394,29 @@ static_assert(none_of(
));
}
+
+#if __cplusplus >= 202302L
+namespace lvalue_to_rvalue_init_from_heap {
+
+struct S {
+ int *value;
+ constexpr S(int v) : value(new int {v}) {} // expected-note 2 {{heap allocation performed here}}
+ constexpr ~S() { delete value; }
+};
+consteval S fn() { return S(5); }
+int fn2() { return 2; } // expected-note {{declared here}}
+
+constexpr int a = *fn().value;
+constinit int b = *fn().value;
+const int c = *fn().value;
+int d = *fn().value;
+
+constexpr int e = *fn().value + fn2(); // expected-error {{must be initialized by a constant expression}} \
+ // expected-error {{call to consteval function 'lvalue_to_rvalue_init_from_heap::fn' is not a constant expression}} \
+ // expected-note {{non-constexpr function 'fn2'}} \
+ // expected-note {{pointer to heap-allocated object}}
+
+int f = *fn().value + fn2(); // expected-error {{call to consteval function 'lvalue_to_rvalue_init_from_heap::fn' is not a constant expression}} \
+ // expected-note {{pointer to heap-allocated object}}
+}
+#endif
diff --git a/clang/test/SemaCXX/enum-scoped.cpp b/clang/test/SemaCXX/enum-scoped.cpp
index b1d9a215c437c7..d7b7923430affa 100644
--- a/clang/test/SemaCXX/enum-scoped.cpp
+++ b/clang/test/SemaCXX/enum-scoped.cpp
@@ -53,6 +53,7 @@ enum class E4 {
e1 = -2147483648, // ok
e2 = 2147483647, // ok
e3 = 2147483648 // expected-error{{enumerator value evaluates to 2147483648, which cannot be narrowed to type 'int'}}
+ // expected-warning at -1{{changes value}}
};
enum class E5 {
diff --git a/clang/test/SemaCXX/ext-int.cpp b/clang/test/SemaCXX/ext-int.cpp
index 931842b7e3c53b..000b871ccd3433 100644
--- a/clang/test/SemaCXX/ext-int.cpp
+++ b/clang/test/SemaCXX/ext-int.cpp
@@ -25,7 +25,7 @@ _BitInt(33) Declarations(_BitInt(48) &Param) { // Useable in params and returns.
unsigned _BitInt(1) l;
signed _BitInt(1) m; // expected-error{{signed _BitInt must have a bit size of at least 2}}
- constexpr _BitInt(6) n = 33;
+ constexpr _BitInt(6) n = 33; // expected-warning{{implicit conversion from 'int' to 'const _BitInt(6)' changes value from 33 to -31}}
constexpr _BitInt(7) o = 33;
// Check imposed max size.
diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp
index 9c1a955743f1ee..97fdbb7232b135 100644
--- a/clang/unittests/Support/TimeProfilerTest.cpp
+++ b/clang/unittests/Support/TimeProfilerTest.cpp
@@ -193,6 +193,7 @@ Frontend
| ParseDeclarationOrFunctionDefinition (test.cc:16:1)
| | ParseFunctionDefinition (slow_test)
| | | EvaluateAsInitializer (slow_value)
+| | | EvaluateAsConstantExpr (<test.cc:17:33, col:59>)
| | | EvaluateAsConstantExpr (<test.cc:18:11, col:37>)
| ParseDeclarationOrFunctionDefinition (test.cc:22:1)
| | EvaluateAsConstantExpr (<test.cc:23:31, col:57>)
>From c58a3244dfd3b174a6c8ac516f151400d081a29d Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Fri, 26 Apr 2024 14:36:33 -0400
Subject: [PATCH 7/7] Formatting fixes.
---
clang/lib/Sema/SemaChecking.cpp | 9 ++++-----
clang/lib/Sema/SemaDeclCXX.cpp | 4 ++--
clang/lib/Sema/SemaExpr.cpp | 3 +--
3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 8d078c23e5bbbe..939b507c7051c4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16548,11 +16548,10 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
std::string PrettySourceValue = toString(Value, 10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
- S.Diag(
- E->getExprLoc(),
- S.PDiag(diag::warn_impcast_integer_precision_constant)
- << PrettySourceValue << PrettyTargetValue << E->getType() << T
- << E->getSourceRange() << SourceRange(CC));
+ S.Diag(E->getExprLoc(),
+ S.PDiag(diag::warn_impcast_integer_precision_constant)
+ << PrettySourceValue << PrettyTargetValue << E->getType()
+ << T << E->getSourceRange() << SourceRange(CC));
return;
}
}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e3d0efe6876cf0..1949a0b7ff46fd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18584,8 +18584,8 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// An expression or conversion is in an 'immediate function context' if it
// is potentially evaluated and either:
// [...]
- // - it is a subexpression of a manifestly constant-evaluated expression or
- // conversion.
+ // - it is a subexpression of a manifestly constant-evaluated expression
+ // or conversion.
ExprEvalContexts.back().InImmediateFunctionContext = true;
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 1758eebcebac73..147a26b0061ee5 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18011,8 +18011,7 @@ HandleImmediateInvocations(Sema &SemaRef,
Sema::ExpressionEvaluationContextRecord &Rec) {
if ((Rec.ImmediateInvocationCandidates.size() == 0 &&
Rec.ReferenceToConsteval.size() == 0) ||
- Rec.isImmediateFunctionContext() ||
- SemaRef.RebuildingImmediateInvocation)
+ Rec.isImmediateFunctionContext() || SemaRef.RebuildingImmediateInvocation)
return;
/// When we have more than 1 ImmediateInvocationCandidates or previously
More information about the cfe-commits
mailing list