Skip to content

Commit

Permalink
Remove the code removing invalid member init ctor
Browse files Browse the repository at this point in the history
  • Loading branch information
kaizhangNV committed Jan 23, 2025
1 parent c5b43c5 commit 1788d3b
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 76 deletions.
124 changes: 49 additions & 75 deletions source/slang/slang-check-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<VarDeclBase*>& resultMembers);
List<KeyValuePair<VarDeclBase*, String>>& resultMembers);
};

struct SemanticsDeclHeaderVisitor : public SemanticsDeclVisitorBase,
Expand Down Expand Up @@ -2159,23 +2159,6 @@ static List<ConstructorDecl*> _getCtorList(
return ctorList;
}

template<typename VisitorType>
static void checkSynthesizedConstructorWithoutDiagnostic(VisitorType& subVisitor, Decl* decl)
{
subVisitor.dispatch(decl);
auto tempSink = subVisitor.getSink();
if (tempSink->getErrorCount() > 0)
{
auto structDecl = as<StructDecl>(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`,
Expand Down Expand Up @@ -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<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 (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<StructDecl>(constructorDecl->parentDecl);
ConstructorDecl* defaultCtor = nullptr;
if (structDecl->m_synthesizedCtorMap.tryGetValue(
(int)ConstructorDecl::ConstructorFlavor::SynthesizedDefault,
defaultCtor))
{
auto structDecl = as<StructDecl>(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(
Expand Down Expand Up @@ -9356,6 +9327,9 @@ void SemanticsDeclBodyVisitor::synthesizeCtorBodyForMember(
cachedDeclToCheckedVar.add({member, checkedMemberVarExpr});
}

if (!checkedMemberVarExpr->type.isLeftValue)
return;

seqStmtChild->stmts.add(stmt);
}

Expand Down Expand Up @@ -10022,20 +9996,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);
Expand Down Expand Up @@ -12236,10 +12196,10 @@ void SemanticsDeclAttributesVisitor::checkPrimalSubstituteOfAttribute(
DeclAssociationKind::PrimalSubstituteFunc);
}

bool SemanticsDeclAttributesVisitor::_searchMembersWithHigherVisibility(
bool SemanticsDeclAttributesVisitor::_searchInitializableMembers(
StructDecl* structDecl,
const DeclVisibility ctorVisibility,
List<VarDeclBase*>& resultMembers)
List<KeyValuePair<VarDeclBase*, String>>& resultMembers)
{
auto findMembers = [&](StructDecl* structDecl)
{
Expand All @@ -12249,11 +12209,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);
}
};

Expand All @@ -12274,12 +12238,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<VarDeclBase>(param),
baseTypeDeclRef.getDecl()->getName()->text));
}
}
}
Expand Down Expand Up @@ -12332,8 +12298,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<VarDeclBase*> resultMembers;
if (!_searchMembersWithHigherVisibility(structDecl, ctorVisibility, resultMembers))
List<KeyValuePair<VarDeclBase*, String>> resultMembers;
if (!_searchInitializableMembers(structDecl, ctorVisibility, resultMembers))
return;

// synthesize the constructor signature:
Expand All @@ -12350,7 +12316,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<ParamDecl>();
ctorParam->type = (TypeExp)member->type;

Expand All @@ -12361,7 +12329,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);

Expand Down
2 changes: 1 addition & 1 deletion tests/diagnostics/variable-redeclaration.slang
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions tests/diagnostics/variable-redeclaration.slang.expected
Original file line number Diff line number Diff line change
Expand Up @@ -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;
^~~~
Expand Down

0 comments on commit 1788d3b

Please sign in to comment.