diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index b302d94dde..bc8a339196 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -104,10 +104,10 @@ struct SemanticsDeclAttributesVisitor : public SemanticsDeclVisitorBase, // We will defer the actual implementation of the constructor to the body visit, because // we will have full information about each field in the struct during that stage. void _synthesizeCtorSignature(StructDecl* structDecl); - bool _searchMembersWithHigherVisibility( + bool _searchInitializableMembers( StructDecl* structDecl, const DeclVisibility ctorVisibility, - List& resultMembers); + List>& resultMembers); }; struct SemanticsDeclHeaderVisitor : public SemanticsDeclVisitorBase, @@ -2159,23 +2159,6 @@ static List _getCtorList( return ctorList; } -template -static void checkSynthesizedConstructorWithoutDiagnostic(VisitorType& subVisitor, Decl* decl) -{ - subVisitor.dispatch(decl); - auto tempSink = subVisitor.getSink(); - if (tempSink->getErrorCount() > 0) - { - auto structDecl = as(decl->parentDecl); - structDecl->members.remove(decl); - structDecl->invalidateMemberDictionary(); - structDecl->buildMemberDictionary(); - structDecl->m_synthesizedCtorMap.remove( - (int)ConstructorDecl::ConstructorFlavor::SynthesizedMemberInit); - } - return; -} - void SemanticsDeclHeaderVisitor::visitStructDecl(StructDecl* structDecl) { // As described above in `SemanticsDeclHeaderVisitor::checkVarDeclCommon`, @@ -8139,46 +8122,34 @@ SemanticsContext SemanticsDeclBodyVisitor::registerDifferentiableTypesForFunc( void SemanticsDeclBodyVisitor::visitFunctionDeclBase(FunctionDeclBase* decl) { + auto newContext = registerDifferentiableTypesForFunc(decl); + if (const auto body = decl->body) + { + checkStmt(decl->body, newContext); + } + if (auto constructorDecl = as(decl)) { - // When checking the synthesized constructor, it's possible to hit error, but we don't want - // to report this error, because this function is not created by user. Instead, when we - // detect this error, we will remove this synthesized constructor from the struct. if (constructorDecl->containsFlavor( ConstructorDecl::ConstructorFlavor::SynthesizedMemberInit) && - !m_checkForSynthesizedCtor) + !getSink()->getErrorCount()) { - DiagnosticSink tempSink; - SemanticsContext subContext = withSink(&tempSink); - subContext.setCheckForSynthesizedCtor(true); - SemanticsDeclBodyVisitor subVisitor(subContext); - checkSynthesizedConstructorWithoutDiagnostic(subVisitor, decl); // Once we have checked the definition of synthesized constructor, we can return delete // the default constructor if it exists, because we only need to have one constructor. - if (tempSink.getErrorCount() == 0) + auto structDecl = as(constructorDecl->parentDecl); + ConstructorDecl* defaultCtor = nullptr; + if (structDecl->m_synthesizedCtorMap.tryGetValue( + (int)ConstructorDecl::ConstructorFlavor::SynthesizedDefault, + defaultCtor)) { - auto structDecl = as(constructorDecl->parentDecl); - ConstructorDecl* defaultCtor = nullptr; - if (structDecl->m_synthesizedCtorMap.tryGetValue( - (int)ConstructorDecl::ConstructorFlavor::SynthesizedDefault, - defaultCtor)) - { - structDecl->members.remove(defaultCtor); - structDecl->invalidateMemberDictionary(); - structDecl->buildMemberDictionary(); - structDecl->m_synthesizedCtorMap.remove( - (int)ConstructorDecl::ConstructorFlavor::SynthesizedDefault); - } + structDecl->members.remove(defaultCtor); + structDecl->invalidateMemberDictionary(); + structDecl->buildMemberDictionary(); + structDecl->m_synthesizedCtorMap.remove( + (int)ConstructorDecl::ConstructorFlavor::SynthesizedDefault); } - return; } } - - auto newContext = registerDifferentiableTypesForFunc(decl); - if (const auto body = decl->body) - { - checkStmt(decl->body, newContext); - } } void SemanticsVisitor::getGenericParams( @@ -10022,20 +9993,6 @@ Type* SemanticsVisitor::findResultTypeForConstructorDecl(ConstructorDecl* decl) void SemanticsDeclHeaderVisitor::visitConstructorDecl(ConstructorDecl* decl) { - // When checking the synthesized constructor, it's possible to hit error, but we don't want to - // report this error, because this function is not created by user. Instead, when we detect this - // error, we will remove this synthesized constructor from the struct. - if (decl->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedMemberInit) && - !m_checkForSynthesizedCtor) - { - DiagnosticSink tempSink; - SemanticsContext subContext = withSink(&tempSink); - subContext.setCheckForSynthesizedCtor(true); - SemanticsDeclHeaderVisitor subVisitor(subContext); - checkSynthesizedConstructorWithoutDiagnostic(subVisitor, decl); - return; - } - // We need to compute the result type for this declaration, // since it wasn't filled in for us. decl->returnType.type = findResultTypeForConstructorDecl(decl); @@ -12236,10 +12193,10 @@ void SemanticsDeclAttributesVisitor::checkPrimalSubstituteOfAttribute( DeclAssociationKind::PrimalSubstituteFunc); } -bool SemanticsDeclAttributesVisitor::_searchMembersWithHigherVisibility( +bool SemanticsDeclAttributesVisitor::_searchInitializableMembers( StructDecl* structDecl, const DeclVisibility ctorVisibility, - List& resultMembers) + List>& resultMembers) { auto findMembers = [&](StructDecl* structDecl) { @@ -12249,11 +12206,15 @@ bool SemanticsDeclAttributesVisitor::_searchMembersWithHigherVisibility( MemberFilterStyle::Instance)) { auto varDecl = varDeclRef.getDecl(); - if (getDeclVisibility(varDecl) >= ctorVisibility) - { - resultMembers.add(varDecl); - structDecl->m_membersVisibleInCtor.add(varDecl); - } + if (getDeclVisibility(varDecl) < ctorVisibility) + continue; + + auto type = GetTypeForDeclRef(varDeclRef, varDecl->loc); + if (!type.isLeftValue) + continue; + + resultMembers.add(KeyValuePair(varDecl, structDecl->getName()->text)); + structDecl->m_membersVisibleInCtor.add(varDecl); } }; @@ -12274,12 +12235,14 @@ bool SemanticsDeclAttributesVisitor::_searchMembersWithHigherVisibility( // otherwise, it's not accessible so we will not pick up. if (ctor && getDeclVisibility(ctor) >= ctorVisibility) { - for (auto param : ctor->getParameters()) + for (ParamDecl* param : ctor->getParameters()) { // Because the parameters in the ctor must have the higher or equal visibility // than the ctor itself, we don't need to check the visibility level of the // parameter. - resultMembers.add(param); + resultMembers.add(KeyValuePair( + as(param), + baseTypeDeclRef.getDecl()->getName()->text)); } } } @@ -12332,8 +12295,8 @@ void SemanticsDeclAttributesVisitor::_synthesizeCtorSignature(StructDecl* struct // Only the members whose visibility level is higher or equal than the // constructor's visibility level will appear in the constructor's parameter list. - List resultMembers; - if (!_searchMembersWithHigherVisibility(structDecl, ctorVisibility, resultMembers)) + List> resultMembers; + if (!_searchInitializableMembers(structDecl, ctorVisibility, resultMembers)) return; // synthesize the constructor signature: @@ -12350,7 +12313,9 @@ void SemanticsDeclAttributesVisitor::_synthesizeCtorSignature(StructDecl* struct bool stopProcessingDefaultValues = false; for (SlangInt i = resultMembers.getCount() - 1; i >= 0; i--) { - auto member = resultMembers[i]; + auto member = resultMembers[i].key; + auto memberContainerName = resultMembers[i].value; + auto ctorParam = m_astBuilder->create(); ctorParam->type = (TypeExp)member->type; @@ -12361,7 +12326,13 @@ void SemanticsDeclAttributesVisitor::_synthesizeCtorSignature(StructDecl* struct stopProcessingDefaultValues = true; ctorParam->parentDecl = ctor; - ctorParam->nameAndLoc = NameLoc(member->getName(), ctor->loc); + + Name* paramName = (memberContainerName == structDecl->getName()->text) + ? member->getName() + : getName(memberContainerName + "_" + member->getName()->text); + + ctorParam->nameAndLoc = NameLoc(paramName, ctor->loc); + ctorParam->loc = ctor->loc; ctor->members.add(ctorParam); diff --git a/tests/diagnostics/variable-redeclaration.slang b/tests/diagnostics/variable-redeclaration.slang index bbd6a07c01..d238442e8c 100644 --- a/tests/diagnostics/variable-redeclaration.slang +++ b/tests/diagnostics/variable-redeclaration.slang @@ -37,7 +37,7 @@ int testLocalShadowing(int x) } // Structure fields - +// Note: more diagnostics will be reported here because of the constructor synthesis struct S { int f; diff --git a/tests/diagnostics/variable-redeclaration.slang.expected b/tests/diagnostics/variable-redeclaration.slang.expected index 1998c13c82..1d4108fc49 100644 --- a/tests/diagnostics/variable-redeclaration.slang.expected +++ b/tests/diagnostics/variable-redeclaration.slang.expected @@ -30,6 +30,12 @@ tests/diagnostics/variable-redeclaration.slang(21): error 30200: declaration of tests/diagnostics/variable-redeclaration.slang(20): note: see previous declaration of 'y' int y = x; ^ +tests/diagnostics/variable-redeclaration.slang(41): error 30200: declaration of 'f' conflicts with existing declaration +struct S + ^ +tests/diagnostics/variable-redeclaration.slang(41): note: see previous declaration of 'f' +struct S + ^ tests/diagnostics/variable-redeclaration.slang(53): error 39999: ambiguous reference to 'size' return size; ^~~~