Skip to content

Commit 69d0c4c

Browse files
zyn0217cor3ntin
andauthoredJan 22, 2025
[Clang] SubstituteConstraintExpressionWithoutSatisfaction needs an unevaluated context (#123883)
It turns out that the substitution for expression comparing also needs an unevaluated context, otherwise any reference to immediate functions might not be properly handled. As a fallout, this also guards the VLA transformation under unevaluated context with `InConditionallyConstantEvaluateContext` to avoid duplicate diagnostics. Fixes llvm/llvm-project#123472 --------- Co-authored-by: cor3ntin <[email protected]>
1 parent ca65055 commit 69d0c4c

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed
 

‎clang/docs/ReleaseNotes.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ Bug Fixes to C++ Support
968968
constraints are applied. (#GH122134)
969969
- Fixed canonicalization of pack indexing types - Clang did not always recognized identical pack indexing. (#GH123033)
970970
- Fixed a nested lambda substitution issue for constraint evaluation. (#GH123441)
971-
971+
- Fixed various false diagnostics related to the use of immediate functions. (#GH123472)
972972

973973
Bug Fixes to AST Handling
974974
^^^^^^^^^^^^^^^^^^^^^^^^^

‎clang/lib/Parse/ParseExpr.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,25 @@ ExprResult Parser::ParseArrayBoundExpression() {
248248
// If we parse the bound of a VLA... we parse a non-constant
249249
// constant-expression!
250250
Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true;
251+
// For a VLA type inside an unevaluated operator like:
252+
//
253+
// sizeof(typeof(*(int (*)[N])array))
254+
//
255+
// N and array are supposed to be ODR-used.
256+
// Initially when encountering `array`, it is deemed unevaluated and non-ODR
257+
// used because that occurs before parsing the type cast. Therefore we use
258+
// Sema::TransformToPotentiallyEvaluated() to rebuild the expression to ensure
259+
// it's actually ODR-used.
260+
//
261+
// However, in other unevaluated contexts as in constraint substitution, it
262+
// would end up rebuilding the type twice which is unnecessary. So we push up
263+
// a flag to help distinguish these cases.
264+
for (auto Iter = Actions.ExprEvalContexts.rbegin() + 1;
265+
Iter != Actions.ExprEvalContexts.rend(); ++Iter) {
266+
if (!Iter->isUnevaluated())
267+
break;
268+
Iter->InConditionallyConstantEvaluateContext = true;
269+
}
251270
return ParseConstantExpressionInExprEvalContext(NotTypeCast);
252271
}
253272

‎clang/lib/Sema/SemaConcept.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,9 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
10271027
ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
10281028
/*NewThisContext=*/false);
10291029
}
1030+
EnterExpressionEvaluationContext UnevaluatedContext(
1031+
S, Sema::ExpressionEvaluationContext::Unevaluated,
1032+
Sema::ReuseLambdaContextDecl);
10301033
ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
10311034
const_cast<clang::Expr *>(ConstrExpr), MLTAL);
10321035
if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())

‎clang/lib/Sema/SemaExpr.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -4630,8 +4630,9 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
46304630

46314631
// Adds overload of TransformToPotentiallyEvaluated for TypeSourceInfo to
46324632
// properly deal with VLAs in nested calls of sizeof and typeof.
4633-
if (isUnevaluatedContext() && ExprKind == UETT_SizeOf &&
4634-
TInfo->getType()->isVariablyModifiedType())
4633+
if (currentEvaluationContext().isUnevaluated() &&
4634+
currentEvaluationContext().InConditionallyConstantEvaluateContext &&
4635+
ExprKind == UETT_SizeOf && TInfo->getType()->isVariablyModifiedType())
46354636
TInfo = TransformToPotentiallyEvaluated(TInfo);
46364637

46374638
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.

‎clang/test/SemaTemplate/concepts-out-of-line-def.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -737,3 +737,17 @@ ptr<U> make_item(auto &&args)
737737
ptr<char> p;
738738

739739
} // namespace GH114685
740+
741+
namespace GH123472 {
742+
743+
consteval bool fn() { return true; }
744+
745+
struct S {
746+
template <typename T>
747+
static consteval void mfn() requires (bool(&fn));
748+
};
749+
750+
template <typename T>
751+
consteval void S::mfn() requires (bool(&fn)) {}
752+
753+
}

0 commit comments

Comments
 (0)
Please sign in to comment.