Skip to content

Commit 8dba2df

Browse files
committed
Fix a VLA diagnostic regression - BuildArrayType() is doubly called under unevaluated context
1 parent 5427c74 commit 8dba2df

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

clang/lib/Parse/ParseExpr.cpp

Lines changed: 19 additions & 0 deletions
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+
// in which the expression N is supposed to be ODR-used, as is the `array`.
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/SemaExpr.cpp

Lines changed: 3 additions & 2 deletions
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.

0 commit comments

Comments
 (0)