diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2025-05-15 12:00:50 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-15 10:00:50 -0700 |
| commit | d961f4438ef865028d289148d22e0fb5c0d8319a (patch) | |
| tree | ee9adf165634f89fc2454761c706f12292e58b69 | |
| parent | b325474c4aba52cca7e0bcd4eae02d23ca4ab9a3 (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.
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 82 | ||||
| -rw-r--r-- | tests/initializer-list/cpp-style-default-member-init.slang | 100 |
2 files changed, 170 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) { diff --git a/tests/initializer-list/cpp-style-default-member-init.slang b/tests/initializer-list/cpp-style-default-member-init.slang new file mode 100644 index 000000000..48ee221cf --- /dev/null +++ b/tests/initializer-list/cpp-style-default-member-init.slang @@ -0,0 +1,100 @@ +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj -vk -output-using-type +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj -output-using-type + +struct NonCStyle +{ + int x = 3; + float y = 4.0f; + int z[2] = {5, 6}; + float2 w = {7.0f, 8.0f}; + + __init(int x) + { + this.x = x; + } + + __init(int x, float y) + { + this.x = x; + this.y = y; + } + + __init(int arr[2]) + { + this.z[0] = arr[0]; + this.z[1] = arr[1]; + } + + __init(float2 vec) + { + this.w= vec; + } +} + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer<float> outputBuffer; +void test() +{ + int idx = 0; + NonCStyle s1 = NonCStyle(1); + outputBuffer[idx++] = s1.x; + // BUFFER: 1 + outputBuffer[idx++] = s1.y; + // BUFFER: 4.0 + outputBuffer[idx++] = s1.z[0]; + // BUFFER: 5 + outputBuffer[idx++] = s1.z[1]; + // BUFFER: 6 + outputBuffer[idx++] = s1.w.x; + // BUFFER: 7 + outputBuffer[idx++] = s1.w.y; + // BUFFER: 8 + + NonCStyle s2 = NonCStyle(1, 12.0); + outputBuffer[idx++] = s2.x; + // BUFFER: 1 + outputBuffer[idx++] = s2.y; + // BUFFER: 12.0 + outputBuffer[idx++] = s2.z[0]; + // BUFFER: 5 + outputBuffer[idx++] = s2.z[1]; + // BUFFER: 6 + outputBuffer[idx++] = s2.w.x; + // BUFFER: 7 + outputBuffer[idx++] = s2.w.y; + // BUFFER: 8 + + NonCStyle s3 = NonCStyle(Array<int, 2>(21u, 22u)); + outputBuffer[idx++] = s3.x; + // BUFFER: 3 + outputBuffer[idx++] = s3.y; + // BUFFER: 4.0 + outputBuffer[idx++] = s3.z[0]; + // BUFFER: 21 + outputBuffer[idx++] = s3.z[1]; + // BUFFER: 22 + outputBuffer[idx++] = s3.w.x; + // BUFFER: 7 + outputBuffer[idx++] = s3.w.y; + // BUFFER: 8 + + NonCStyle s4 = NonCStyle(float2(31, 32)); + outputBuffer[idx++] = s4.x; + // BUFFER: 3 + outputBuffer[idx++] = s4.y; + // BUFFER: 4.0 + outputBuffer[idx++] = s4.z[0]; + // BUFFER: 5 + outputBuffer[idx++] = s4.z[1]; + // BUFFER: 6 + outputBuffer[idx++] = s4.w.x; + // BUFFER: 31 + outputBuffer[idx++] = s4.w.y; + // BUFFER: 32 +} + +[shader("compute")] +void computeMain() +{ + test(); +} |
