================ @@ -5695,19 +5694,35 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + + // CWG1815 + // Support lifetime extension of temporary created by aggregate + // initialization using a default member initializer. We should always rebuild + // the initializer if it contains any temporaries (if the initializer + // expression is an ExprWithCleanups). Then make sure the normal lifetime + // extension code recurses into the default initializer and does lifetime + // extension when warranted. + bool ContainsAnyTemporaries = + isa_and_present<ExprWithCleanups>(Field->getInClassInitializer()); + if (V.HasImmediateCalls || InLifetimeExtendingContext || + ContainsAnyTemporaries) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; - + // Pass down lifetime extending flag, and collect temporaries in + // CreateMaterializeTemporaryExpr when we rewrite the call argument. + keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; + + // Rebuild CXXDefaultInitExpr might cause diagnostics. + SFINAETrap Trap(*this); ---------------- yronglin wrote:
Here we add `SFINAETrap Trap(*this)`. It was used to resolve the issue which looks like https://github.com/llvm/llvm-project/blob/main/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp . A shorter reproducer: ``` class Private { Private(int); // expected-note {{here}} public: Private(); }; class S { Private p = 42; // expected-error {{private constructor}} S() {} // expected-error {{call to deleted constructor of 'NoDefault'}} \ expected-error {{must explicitly initialize the member 'e1' which does not have a default constructor}} S(int) {} }; // FIXME: test the other forms which use copy-initialization ``` `Field->getInClassInitializer()` contains an `bad access error`, then we try to rebuild this initializer, the diagnostic will emit 3 times. (The result of `Field->getInClassInitializer()->containsErrors()` 3 times are `false`). 1st time: parser member initializer. 2nd time: After rebuild, Line 5726 ` Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc);` 3rd time: After rebuild, Line 5726 ` Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc);` ``` ./error.cpp:8:15: error: field of type 'Private' has private constructor 8 | Private p = 42; // expected-error {{private constructor}} | ^ ./error.cpp:2:3: note: implicitly declared private here 2 | Private(int); // expected-note {{here}} | ^ ./error.cpp:8:15: error: field of type 'Private' has private constructor 8 | Private p = 42; // expected-error {{private constructor}} | ^ ./error.cpp:2:3: note: implicitly declared private here 2 | Private(int); // expected-note {{here}} | ^ ./error.cpp:8:15: error: field of type 'Private' has private constructor 8 | Private p = 42; // expected-error {{private constructor}} | ^ ./error.cpp:2:3: note: implicitly declared private here 2 | Private(int); // expected-note {{here}} | ^ 3 errors generated. ``` https://github.com/llvm/llvm-project/pull/92527 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits