diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h index 08951513dc..75c90e27a5 100644 --- a/source/slang/slang-ast-builder.h +++ b/source/slang/slang-ast-builder.h @@ -80,6 +80,15 @@ class SharedASTBuilder : public RefObject } return m_thisTypeName; } + + Name* getCtorName() + { + if (!m_ctorName) + { + m_ctorName = getNamePool()->getName("$init"); + } + return m_ctorName; + } protected: // State shared between ASTBuilders @@ -114,6 +123,7 @@ class SharedASTBuilder : public RefObject NamePool* m_namePool = nullptr; Name* m_thisTypeName = nullptr; + Name* m_ctorName = nullptr; // This is a private builder used for these shared types ASTBuilder* m_astBuilder = nullptr; diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp index 9bbea118a3..44d4cfd830 100644 --- a/source/slang/slang-check-conversion.cpp +++ b/source/slang/slang-check-conversion.cpp @@ -550,7 +550,7 @@ namespace Slang // b. Collect and coerce init-list arguments into constructor parameters // c. Create InvokeExpr for our valid ConstructorDecl List ctorList = _getCtorList(this->getASTBuilder(), this, toStructDecl, nullptr); - bool allowCStyleInitList = checkIfCStyleStruct(this, toStructDecl); + bool allowCStyleInitList = isCStyleStructDecl(this, toStructDecl, ctorList); List maybeArgList; maybeArgList.reserve(argCount); diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 32fe693b1f..7d0a41094e 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -2798,7 +2798,7 @@ namespace Slang // `checkIfCStyleStruct` must check after we add all possible Ctors. // If we are a CStyleStruct add DefaultConstructExpr to all params (excluding arg 0) - bool isCStyleStruct = checkIfCStyleStruct(this, structDecl); + bool isCStyleStruct = isCStyleStructDecl(this, structDecl, ctorList); if (isCStyleStruct && generatedMemberwiseCtors.getCount() > 0) { // We know the user provided 0 non-default ctor's, we only had a chance to generate non default Ctors above in this AST pass. @@ -8299,6 +8299,7 @@ namespace Slang return ctor->containsOption(ConstructorTags::Synthesized) && ctor->getParameters().getCount() != 0 && !allParamHaveInitExpr(ctor); + // return ctor->findModifier(); } template @@ -8766,7 +8767,7 @@ namespace Slang } // Compiler generated ctor may be destroyed - bool destroyedDefaultCtor = false; + bool destroyedDefaultCtor = false; if(structDeclInfo.m_defaultCtor && structDeclInfo.m_defaultCtor->containsOption(ConstructorTags::Synthesized)) { diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 334737c97e..265b00ca2c 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -3037,7 +3037,7 @@ namespace Slang Expr* constructZeroInitListFunc(SemanticsVisitor* visitor, StructDecl* structDecl, Type* structDeclType, ConstructZeroInitListOptions options); FuncDecl* findZeroInitListFunc(StructDecl* structDecl); - bool checkIfCStyleStruct(SemanticsVisitor* visitor, StructDecl* decl); + bool isCStyleStructDecl(SemanticsVisitor* visitor, StructDecl* decl, List const& ctorList); DefaultConstructExpr* createDefaultConstructExprForType(ASTBuilder* m_astBuilder, QualType type, SourceLoc loc); diff --git a/source/slang/slang-constructor-utility.cpp b/source/slang/slang-constructor-utility.cpp index 76bdfcc9ae..6d42c9284b 100644 --- a/source/slang/slang-constructor-utility.cpp +++ b/source/slang/slang-constructor-utility.cpp @@ -12,23 +12,27 @@ namespace Slang return defaultConstructExpr; } + bool allParamHaveInitExpr(ConstructorDecl* ctor) + { + for (auto i : ctor->getParameters()) + if (!i->initExpr) + return false; + return true; + } + ConstructorDecl* _getDefaultCtor(StructDecl* structDecl) { for (auto ctor : structDecl->getMembersOfType()) { - if (!ctor->body || ctor->members.getCount() != 0) + // 1. default ctor must have definition + // 2. default ctor must have no parameters or all parameters have init expr + if (!ctor->body || (ctor->members.getCount() != 0 && !allParamHaveInitExpr(ctor))) continue; return ctor; } return nullptr; } - bool allParamHaveInitExpr(ConstructorDecl* ctor) - { - for (auto i : ctor->getParameters()) - if (!i->initExpr) - return false; - return true; - } + List _getCtorList(ASTBuilder* m_astBuilder, SemanticsVisitor* visitor, StructDecl* structDecl, ConstructorDecl** defaultCtorOut) { List ctorList; @@ -36,7 +40,7 @@ namespace Slang auto ctorLookupResult = lookUpMember( m_astBuilder, visitor, - visitor->getName("$init"), + m_astBuilder->getSharedASTBuilder()->getCtorName(), DeclRefType::create(m_astBuilder, structDecl), structDecl->ownedScope, LookupMask::Function, @@ -63,7 +67,7 @@ namespace Slang return ctorList; } - for (auto m : ctorLookupResult.items) + for (auto m : ctorLookupResult) { lookupResultHandle(m); } @@ -151,7 +155,7 @@ namespace Slang return nullptr; } - Expr* _constructZeroInitListFuncMakeDefaultCtor(SemanticsVisitor* visitor, StructDecl* structDecl, Type* structDeclType, ConstructorDecl* defaultCtor) + Expr* constructDefaultCtorInvocationExpr(SemanticsVisitor* visitor, StructDecl* structDecl, Type* structDeclType, ConstructorDecl* defaultCtor) { auto* invoke = visitor->getASTBuilder()->create(); auto member = visitor->getASTBuilder()->getMemberDeclRef(structDecl->getDefaultDeclRef(), defaultCtor); @@ -192,34 +196,34 @@ namespace Slang } } if(canCreateCtor) - return _constructZeroInitListFuncMakeDefaultCtor(visitor, structDecl, structDeclType, defaultCtor); + return constructDefaultCtorInvocationExpr(visitor, structDecl, structDeclType, defaultCtor); } // 2. - if (auto zeroInitListFunc = findZeroInitListFunc(structDecl)) + if (auto defaultInitFunc = findZeroInitListFunc(structDecl)) { auto* invoke = visitor->getASTBuilder()->create(); DeclRef member; auto declRefType = as(structDeclType); if(declRefType && as(declRefType->getDeclRefBase())) - member = visitor->getASTBuilder()->getMemberDeclRef(as(declRefType->getDeclRefBase()), zeroInitListFunc); + member = visitor->getASTBuilder()->getMemberDeclRef(as(declRefType->getDeclRefBase()), defaultInitFunc); else - member = visitor->getASTBuilder()->getMemberDeclRef(structDecl, zeroInitListFunc); + member = visitor->getASTBuilder()->getMemberDeclRef(structDecl, defaultInitFunc); - invoke->functionExpr = visitor->ConstructDeclRefExpr(member, nullptr, zeroInitListFunc->getName(), zeroInitListFunc->loc, nullptr); + invoke->functionExpr = visitor->ConstructDeclRefExpr(member, nullptr, defaultInitFunc->getName(), defaultInitFunc->loc, nullptr); invoke->type = structDeclType; return invoke; } // 3. if (defaultCtor) - return _constructZeroInitListFuncMakeDefaultCtor(visitor, structDecl, structDeclType, defaultCtor); + return constructDefaultCtorInvocationExpr(visitor, structDecl, structDeclType, defaultCtor); // 4. return createDefaultConstructExprForType(visitor->getASTBuilder(), QualType(structDeclType), {}); } - bool checkIfCStyleStruct(SemanticsVisitor* visitor, StructDecl* structDecl) + bool isCStyleStructDecl(SemanticsVisitor* visitor, StructDecl* structDecl, List const& ctorList) { // CStyleStruct follows the following rules: // 1. Does not contain a non 'Synthesized' Ctor (excluding 'DefaultCtor') @@ -236,7 +240,6 @@ namespace Slang return *isCStyleStruct; // Add to IsCStyleStruct cache - auto ctorList = _getCtorList(visitor->getASTBuilder(), visitor, structDecl, nullptr); int nonDefaultInitCount = 0; for (auto i : ctorList) {