summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorkaizhangNV <149626564+kaizhangNV@users.noreply.github.com>2025-05-15 12:00:50 -0500
committerGitHub <noreply@github.com>2025-05-15 10:00:50 -0700
commitd961f4438ef865028d289148d22e0fb5c0d8319a (patch)
treeee9adf165634f89fc2454761c706f12292e58b69 /source
parentb325474c4aba52cca7e0bcd4eae02d23ca4ab9a3 (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-check-decl.cpp82
1 files changed, 70 insertions, 12 deletions
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<typename VisitorType>
@@ -9194,10 +9199,11 @@ static SeqStmt* _ensureCtorBodyIsSeqStmt(ASTBuilder* m_astBuilder, ConstructorDe
return as<SeqStmt>(stmt->body);
}
-MemberExpr* SemanticsDeclBodyVisitor::createMemberExpr(
+AssignExpr* SemanticsDeclBodyVisitor::createMemberAssignmentExpr(
ThisExpr* thisExpr,
Scope* scope,
- Decl* member)
+ Decl* member,
+ Expr* rightHandSideExpr)
{
MemberExpr* memberExpr = m_astBuilder->create<MemberExpr>();
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<AssignExpr>();
+ 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<AssignExpr>();
- assign->left = memberExpr;
- assign->right = initExpr;
- assign->loc = member->loc;
-
auto stmt = m_astBuilder->create<ExpressionStmt>();
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<ConstructorDecl>())
+ {
+ ThisExpr* thisExpr = m_astBuilder->create<ThisExpr>();
+ thisExpr->scope = ctor->ownedScope;
+ thisExpr->type = ctor->returnType.type;
+ auto seqStmtChild = m_astBuilder->create<SeqStmt>();
+ seqStmtChild->stmts.reserve(structDecl->members.getCount());
+
+ for (auto& member : structDecl->members)
+ {
+ if (auto varDeclBase = as<VarDeclBase>(member))
+ {
+ if (varDeclBase->hasModifier<HLSLStaticModifier>() ||
+ varDeclBase->getName() == nullptr || varDeclBase->initExpr == nullptr)
+ continue;
+
+ auto assign = createMemberAssignmentExpr(
+ thisExpr,
+ ctor->ownedScope,
+ member,
+ varDeclBase->initExpr);
+ if (!assign)
+ continue;
+
+ auto stmt = m_astBuilder->create<ExpressionStmt>();
+ 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)
{