-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang] Fix potential constant expression checking with constexpr-unknown. #149227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] Fix potential constant expression checking with constexpr-unknown. #149227
Conversation
…nown. 0717657 improved constexpr-unkown diagnostics, but potential constant expression checking broke in the process: we produce diagnostics in more cases. Supress the diagnostics as appropriate. This fix affects -Winvalid-constexpr and the enable_if attribute. (The -Winvalid-constexpr diagnostic isn't really important right now, but it will become important if we allow constexpr-unknown with pre-C++23 standards.) Fixes llvm#149041. Fixes llvm#149188.
@llvm/pr-subscribers-clang Author: Eli Friedman (efriedma-quic) Changes0717657 improved constexpr-unkown diagnostics, but potential constant expression checking broke in the process: we produce diagnostics in more cases. Supress the diagnostics as appropriate. This fix affects -Winvalid-constexpr and the enable_if attribute. (The -Winvalid-constexpr diagnostic isn't really important right now, but it will become important if we allow constexpr-unknown with pre-C++23 standards.) Fixes #149041. Fixes #149188. Full diff: https://github.com/llvm/llvm-project/pull/149227.diff 3 Files Affected:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 767cc4c3b19eb..8797eaddd0e18 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4450,7 +4450,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
} else if (!IsAccess) {
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
- } else if (IsConstant && Info.checkingPotentialConstantExpression() &&
+ } else if ((IsConstant || BaseType->isReferenceType()) &&
+ Info.checkingPotentialConstantExpression() &&
BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) {
// This variable might end up being constexpr. Don't diagnose it yet.
} else if (IsConstant) {
@@ -4491,9 +4492,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// a null BaseVal. Any constexpr-unknown variable seen here is an error:
// we can't access a constexpr-unknown object.
if (AK != clang::AK_Dereference && !BaseVal) {
- Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
- << AK << VD;
- Info.Note(VD->getLocation(), diag::note_declared_at);
+ if (!Info.checkingPotentialConstantExpression()) {
+ Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
+ << AK << VD;
+ Info.Note(VD->getLocation(), diag::note_declared_at);
+ }
return CompleteObject();
}
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
index 03fea91169787..979d29476c119 100644
--- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp
+++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
@@ -357,3 +357,27 @@ namespace pointer_comparisons {
static_assert(!f4()); // expected-error {{static assertion expression is not an integral constant expression}} \
// expected-note {{in call to 'f4()'}}
}
+
+namespace enable_if_1 {
+ template <__SIZE_TYPE__ N>
+ constexpr void foo(const char (&Str)[N])
+ __attribute((enable_if(__builtin_strlen(Str), ""))) {}
+
+ void x() {
+ foo("1234");
+ }
+}
+
+namespace enable_if_2 {
+ constexpr const char (&f())[];
+ extern const char (&Str)[];
+ constexpr int foo()
+ __attribute((enable_if(__builtin_strlen(Str), "")))
+ {return __builtin_strlen(Str);}
+
+ constexpr const char (&f())[] {return "a";}
+ constexpr const char (&Str)[] = f();
+ void x() {
+ constexpr int x = foo();
+ }
+}
diff --git a/clang/test/SemaCXX/constexpr-never-constant.cpp b/clang/test/SemaCXX/constexpr-never-constant.cpp
index 307810ee263dd..ca6dff22275d5 100644
--- a/clang/test/SemaCXX/constexpr-never-constant.cpp
+++ b/clang/test/SemaCXX/constexpr-never-constant.cpp
@@ -24,3 +24,8 @@ constexpr void other_func() {
throw 12;
}
+
+// Make sure these don't trigger the diagnostic.
+extern const bool& b;
+constexpr bool fun1() { return b; }
+constexpr bool fun2(const bool& b) { return b; }
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (presumably, we want to backport that)
namespace enable_if_1 { | ||
template <__SIZE_TYPE__ N> | ||
constexpr void foo(const char (&Str)[N]) | ||
__attribute((enable_if(__builtin_strlen(Str), ""))) {} | ||
|
||
void x() { | ||
foo("1234"); | ||
} | ||
} | ||
|
||
namespace enable_if_2 { | ||
constexpr const char (&f())[]; | ||
extern const char (&Str)[]; | ||
constexpr int foo() | ||
__attribute((enable_if(__builtin_strlen(Str), ""))) | ||
{return __builtin_strlen(Str);} | ||
|
||
constexpr const char (&f())[] {return "a";} | ||
constexpr const char (&Str)[] = f(); | ||
void x() { | ||
constexpr int x = foo(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you reference the issue (either a comment or in the namespace name)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We normally use the namespace name, I think we should stick w/ that.
// Make sure these don't trigger the diagnostic. | ||
extern const bool& b; | ||
constexpr bool fun1() { return b; } | ||
constexpr bool fun2(const bool& b) { return b; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you reference the issue (either a comment or in the namespace name)?
/cherry-pick 6a60f18 |
Failed to cherry-pick: 6a60f18 https://github.com/llvm/llvm-project/actions/runs/16355033735 Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
namespace enable_if_1 { | ||
template <__SIZE_TYPE__ N> | ||
constexpr void foo(const char (&Str)[N]) | ||
__attribute((enable_if(__builtin_strlen(Str), ""))) {} | ||
|
||
void x() { | ||
foo("1234"); | ||
} | ||
} | ||
|
||
namespace enable_if_2 { | ||
constexpr const char (&f())[]; | ||
extern const char (&Str)[]; | ||
constexpr int foo() | ||
__attribute((enable_if(__builtin_strlen(Str), ""))) | ||
{return __builtin_strlen(Str);} | ||
|
||
constexpr const char (&f())[] {return "a";} | ||
constexpr const char (&Str)[] = f(); | ||
void x() { | ||
constexpr int x = foo(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We normally use the namespace name, I think we should stick w/ that.
0717657 improved constexpr-unkown diagnostics, but potential constant expression checking broke in the process: we produce diagnostics in more cases. Supress the diagnostics as appropriate.
This fix affects -Winvalid-constexpr and the enable_if attribute. (The -Winvalid-constexpr diagnostic isn't really important right now, but it will become important if we allow constexpr-unknown with pre-C++23 standards.)
Fixes #149041. Fixes #149188.