diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -54,6 +54,9 @@ `Issue 56800 `_. - Fix `#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`_. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10833,6 +10833,9 @@ 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, @@ -10856,19 +10859,26 @@ 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; + } } }