From d961f4438ef865028d289148d22e0fb5c0d8319a Mon Sep 17 00:00:00 2001 From: kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> Date: Thu, 15 May 2025 12:00:50 -0500 Subject: Implement C++ style default member initializer (#7087) close #7069. We just insert the assignment expression to the beginning of the user-defined ctor, where the assignee is the member with init expression. --- source/slang/slang-check-decl.cpp | 82 +++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 12 deletions(-) (limited to 'source') diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index bdd59c2c5..e7ce8721a 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -380,8 +380,13 @@ private: bool isMemberInitCtor, Index& paramIndex); - MemberExpr* createMemberExpr(ThisExpr* thisExpr, Scope* scope, Decl* member); + AssignExpr* createMemberAssignmentExpr( + ThisExpr* thisExpr, + Scope* scope, + Decl* member, + Expr* rightHandSideExpr); Expr* createCtorParamExpr(ConstructorDecl* ctor, Index paramIndex); + void maybeInsertDefaultInitExpr(StructDecl* structDecl); }; template @@ -9194,10 +9199,11 @@ static SeqStmt* _ensureCtorBodyIsSeqStmt(ASTBuilder* m_astBuilder, ConstructorDe return as(stmt->body); } -MemberExpr* SemanticsDeclBodyVisitor::createMemberExpr( +AssignExpr* SemanticsDeclBodyVisitor::createMemberAssignmentExpr( ThisExpr* thisExpr, Scope* scope, - Decl* member) + Decl* member, + Expr* rightHandSideExpr) { MemberExpr* memberExpr = m_astBuilder->create(); memberExpr->baseExpression = thisExpr; @@ -9207,7 +9213,15 @@ MemberExpr* SemanticsDeclBodyVisitor::createMemberExpr( memberExpr->name = member->getName(); memberExpr->type = GetTypeForDeclRef(member->getDefaultDeclRef(), member->loc); - return memberExpr; + if (!memberExpr->type.isLeftValue) + return nullptr; + + auto assign = m_astBuilder->create(); + assign->left = memberExpr; + assign->right = rightHandSideExpr; + assign->loc = member->loc; + + return assign; } Expr* SemanticsDeclBodyVisitor::createCtorParamExpr(ConstructorDecl* ctor, Index paramIndex) @@ -9345,15 +9359,10 @@ void SemanticsDeclBodyVisitor::synthesizeCtorBodyForMember( } } - MemberExpr* memberExpr = createMemberExpr(thisExpr, ctor->ownedScope, member); - if (!memberExpr->type.isLeftValue) + auto assign = createMemberAssignmentExpr(thisExpr, ctor->ownedScope, member, initExpr); + if (!assign) return; - auto assign = m_astBuilder->create(); - assign->left = memberExpr; - assign->right = initExpr; - assign->loc = member->loc; - auto stmt = m_astBuilder->create(); stmt->expression = assign; stmt->loc = member->loc; @@ -9363,13 +9372,61 @@ void SemanticsDeclBodyVisitor::synthesizeCtorBodyForMember( checkedMemberVarExpr = cachedDeclToCheckedVar[member]; else { - checkedMemberVarExpr = CheckTerm(memberExpr); + checkedMemberVarExpr = CheckTerm(assign->left); cachedDeclToCheckedVar.add({member, checkedMemberVarExpr}); } seqStmtChild->stmts.add(stmt); } +// This function inserts the default initialization expression for every member who +// has init expression at beginning of the user-defined ctor. We don't need to do this +// for synthesized ctor, because synthesized ctor already handle this at the function +// parameters +void SemanticsDeclBodyVisitor::maybeInsertDefaultInitExpr(StructDecl* structDecl) +{ + // If there is no explicit constructor, we don't need to do anything. + if (!_hasExplicitConstructor(structDecl, false)) + return; + + // traverse all the constructors and insert the default initialization expressions. + for (auto ctor : structDecl->getMembersOfType()) + { + ThisExpr* thisExpr = m_astBuilder->create(); + thisExpr->scope = ctor->ownedScope; + thisExpr->type = ctor->returnType.type; + auto seqStmtChild = m_astBuilder->create(); + seqStmtChild->stmts.reserve(structDecl->members.getCount()); + + for (auto& member : structDecl->members) + { + if (auto varDeclBase = as(member)) + { + if (varDeclBase->hasModifier() || + varDeclBase->getName() == nullptr || varDeclBase->initExpr == nullptr) + continue; + + auto assign = createMemberAssignmentExpr( + thisExpr, + ctor->ownedScope, + member, + varDeclBase->initExpr); + if (!assign) + continue; + + auto stmt = m_astBuilder->create(); + stmt->expression = assign; + stmt->loc = member->loc; + seqStmtChild->stmts.add(stmt); + } + } + if (seqStmtChild->stmts.getCount() != 0) + { + auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor); + seqStmt->stmts.insert(0, seqStmtChild); + } + } +} void SemanticsDeclBodyVisitor::synthesizeCtorBody( DeclAndCtorInfo& structDeclInfo, @@ -9476,6 +9533,7 @@ void SemanticsDeclBodyVisitor::visitAggTypeDecl(AggTypeDecl* aggTypeDecl) } synthesizeCtorBody(structDeclInfo, inheritanceDefaultCtorList, structDecl); + maybeInsertDefaultInitExpr(structDecl); if (structDeclInfo.defaultCtor) { -- cgit v1.2.3