================
@@ -7541,18 +7541,55 @@ Sema::BuildCompoundLiteralExpr(SourceLocation 
LParenLoc, TypeSourceInfo *TInfo,
   //  "If the compound literal occurs outside the body of a function, the
   //  initializer list shall consist of constant expressions."
   if (IsFileScope)
-    if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
+    if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr)) {
+      // A default argument or default member initializer containing an
+      // immediate call or source_location is rebuilt at each use site, where
+      // its elements are evaluated (see BuildCXXDefaultArgExpr).
+      bool InDefaultArgOrInit =
+          isCheckingDefaultArgumentOrInitializer() ||
+          InnermostDeclarationWithDelayedImmediateInvocations().has_value();
       for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
         Expr *Init = ILE->getInit(i);
-        if (!Init->isTypeDependent() && !Init->isValueDependent() &&
-            !Init->isConstantInitializer(Context)) {
+        // An immediate invocation is already a ConstantExpr and receives its
+        // value at the end of the full-expression.
+        if (isa<ConstantExpr>(Init))
+          continue;
+        if (Init->isTypeDependent() || Init->isValueDependent()) {
+          ILE->setInit(i, ConstantExpr::Create(Context, Init));
+          continue;
+        }
+        // Only a reference member is initialized by a glvalue.
+        bool IsRef = Init->isGLValue();
+        if (!Init->isConstantInitializer(Context, IsRef)) {
----------------
akash-manna-sky wrote:

Tried it and it works out well. The per-element `isConstantInitializer` call is 
gone; an element is accepted when its constant-context evaluation succeeds 
without side effects, keeping the old tolerance for folded UB like signed 
overflow. Deferred elements are still evaluated for validity, just not stored. 
Each element is now evaluated once instead of twice, and the only behavior 
change is that `(RR[1]){1}` with an `int&&` member, the last case in the FIXME 
crash test, now gets "not a compile-time constant" instead of crashing CodeGen, 
matching how `(RT){1}` is already rejected. Test converted accordingly. The 
whole-literal check below still uses `isConstantInitializer` for non-list 
initializers.


https://github.com/llvm/llvm-project/pull/221390
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to