Skip to content

Commit

Permalink
[clang] Short-circuit trivial constructors when evaluating arrays
Browse files Browse the repository at this point in the history
VisitCXXConstructExpr() will later do something similar, but for large
arrays, we should try to do it once an not for every element.

Fixes #56774

Differential Revision: https://reviews.llvm.org/D130791
  • Loading branch information
tbaederr committed Aug 3, 2022
1 parent 3d51e27 commit 11e52ec
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -54,6 +54,9 @@ Bug Fixes
`Issue 56800 <https://github.com/llvm/llvm-project/issues/56800>`_.
- Fix `#56772 <https://github.com/llvm/llvm-project/issues/56772>`_ - invalid
destructor names were incorrectly accepted on template classes.
- Improve compile-times with large dynamic array allocations with trivial
constructors. This fixes
`Issue 56774<https://github.com/llvm/llvm-project/issues/56774>`_.

Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
36 changes: 23 additions & 13 deletions clang/lib/AST/ExprConstant.cpp
Expand Up @@ -10833,6 +10833,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
if (FinalSize == 0)
return true;

bool HasTrivialConstructor = CheckTrivialDefaultConstructor(
Info, E->getExprLoc(), E->getConstructor(),
E->requiresZeroInitialization());
LValue ArrayElt = Subobject;
ArrayElt.addArray(Info, E, CAT);
// We do the whole initialization in two passes, first for just one element,
Expand All @@ -10856,19 +10859,26 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
for (unsigned I = OldElts; I < N; ++I)
Value->getArrayInitializedElt(I) = Filler;

// Initialize the elements.
for (unsigned I = OldElts; I < N; ++I) {
if (!VisitCXXConstructExpr(E, ArrayElt,
&Value->getArrayInitializedElt(I),
CAT->getElementType()) ||
!HandleLValueArrayAdjustment(Info, E, ArrayElt,
CAT->getElementType(), 1))
return false;
// When checking for const initilization any diagnostic is considered
// an error.
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
!Info.keepEvaluatingAfterFailure())
return false;
if (HasTrivialConstructor && N == FinalSize) {
// If we have a trivial constructor, only evaluate it once and copy
// the result into all the array elements.
APValue &FirstResult = Value->getArrayInitializedElt(0);
for (unsigned I = OldElts; I < FinalSize; ++I)
Value->getArrayInitializedElt(I) = FirstResult;
} else {
for (unsigned I = OldElts; I < N; ++I) {
if (!VisitCXXConstructExpr(E, ArrayElt,
&Value->getArrayInitializedElt(I),
CAT->getElementType()) ||
!HandleLValueArrayAdjustment(Info, E, ArrayElt,
CAT->getElementType(), 1))
return false;
// When checking for const initilization any diagnostic is considered
// an error.
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
!Info.keepEvaluatingAfterFailure())
return false;
}
}
}

Expand Down

0 comments on commit 11e52ec

Please sign in to comment.