From f90e4060fd88c69426732c366450ec0a79e56e02 Mon Sep 17 00:00:00 2001 From: MikePopoloski Date: Tue, 4 Jan 2022 08:20:23 -0500 Subject: [PATCH] Fix regression in class parameters with defaults that refer to other parameters --- source/symbols/ClassSymbols.cpp | 7 ++++--- source/symbols/InstanceSymbols.cpp | 9 +++++---- source/symbols/ParameterBuilder.cpp | 6 ++++-- source/symbols/ParameterBuilder.h | 3 ++- tests/unittests/ClassTests.cpp | 15 +++++++++++++++ 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/source/symbols/ClassSymbols.cpp b/source/symbols/ClassSymbols.cpp index 0d854e695..4ae9981a0 100644 --- a/source/symbols/ClassSymbols.cpp +++ b/source/symbols/ClassSymbols.cpp @@ -762,9 +762,10 @@ const Type* GenericClassDefSymbol::getSpecializationImpl( SmallVectorSized paramValues; SmallVectorSized typeParams; for (auto& decl : paramDecls) { + bool isOverriden = false; bool anyErrors = false; auto& param = paramBuilder.createParam(decl, instanceLoc, forceInvalidParams, isForDefault, - anyErrors); + isOverriden, anyErrors); if (anyErrors) { if (isForDefault) @@ -779,7 +780,7 @@ const Type* GenericClassDefSymbol::getSpecializationImpl( if (sym.kind == SymbolKind::Parameter) { auto& ps = sym.as(); - if (!forceInvalidParams) + if (!forceInvalidParams && isOverriden) ps.getDeclaredType()->resolveAt(context); if (!param.isLocalParam()) { @@ -788,7 +789,7 @@ const Type* GenericClassDefSymbol::getSpecializationImpl( } else { auto& tps = sym.as(); - if (!forceInvalidParams) + if (!forceInvalidParams && isOverriden) tps.targetType.forceResolveAt(context); if (!param.isLocalParam()) { diff --git a/source/symbols/InstanceSymbols.cpp b/source/symbols/InstanceSymbols.cpp index f2c5e74ad..574fcd52b 100644 --- a/source/symbols/InstanceSymbols.cpp +++ b/source/symbols/InstanceSymbols.cpp @@ -561,7 +561,7 @@ InstanceBodySymbol& InstanceBodySymbol::fromDefinition(Compilation& comp, result->addMembers(*import); // Add in all parameter ports. - bool unused = false; + bool unused1 = false, unused2 = false; SmallVectorSized params; auto paramIt = definition.parameters.begin(); while (paramIt != definition.parameters.end()) { @@ -570,7 +570,7 @@ InstanceBodySymbol& InstanceBodySymbol::fromDefinition(Compilation& comp, break; auto& param = paramBuilder.createParam(decl, instanceLoc, isUninstantiated, - /* suppressErrors */ false, unused); + /* suppressErrors */ false, unused1, unused2); params.append(¶m); result->addMember(param.symbol); paramIt++; @@ -593,8 +593,9 @@ InstanceBodySymbol& InstanceBodySymbol::fromDefinition(Compilation& comp, auto& decl = *paramIt; ASSERT(declarator.name.valueText() == decl.name); - auto& param = paramBuilder.createParam(decl, instanceLoc, isUninstantiated, - /* suppressErrors */ false, unused); + auto& param = + paramBuilder.createParam(decl, instanceLoc, isUninstantiated, + /* suppressErrors */ false, unused1, unused2); params.append(¶m); result->addMember(param.symbol); paramIt++; diff --git a/source/symbols/ParameterBuilder.cpp b/source/symbols/ParameterBuilder.cpp index e335be292..573fa7179 100644 --- a/source/symbols/ParameterBuilder.cpp +++ b/source/symbols/ParameterBuilder.cpp @@ -118,7 +118,7 @@ void ParameterBuilder::setAssignments(const ParameterValueAssignmentSyntax& synt const ParameterSymbolBase& ParameterBuilder::createParam(const Definition::ParameterDecl& decl, SourceLocation instanceLoc, bool forceInvalidValues, - bool suppressErrors, + bool suppressErrors, bool& isOverriden, bool& anyErrors) const { auto reportError = [&](auto& param) { anyErrors = true; @@ -131,8 +131,10 @@ const ParameterSymbolBase& ParameterBuilder::createParam(const Definition::Param auto& comp = scope.getCompilation(); const ExpressionSyntax* newInitializer = nullptr; - if (auto it = assignments.find(decl.name); it != assignments.end()) + if (auto it = assignments.find(decl.name); it != assignments.end()) { newInitializer = it->second; + isOverriden = newInitializer != nullptr; + } if (decl.isTypeParam) { auto param = comp.emplace(decl.name, decl.location, decl.isLocalParam, diff --git a/source/symbols/ParameterBuilder.h b/source/symbols/ParameterBuilder.h index e4d1be112..bbafe3eb3 100644 --- a/source/symbols/ParameterBuilder.h +++ b/source/symbols/ParameterBuilder.h @@ -40,7 +40,8 @@ class ParameterBuilder { const ParameterSymbolBase& createParam(const Definition::ParameterDecl& decl, SourceLocation instanceLoc, bool forceInvalidValues, - bool suppressErrors, bool& anyErrors) const; + bool suppressErrors, bool& isOverriden, + bool& anyErrors) const; static void createDecls(const Scope& scope, const ParameterDeclarationBaseSyntax& syntax, bool isLocal, bool isPort, SmallVector& results); diff --git a/tests/unittests/ClassTests.cpp b/tests/unittests/ClassTests.cpp index 981b88048..4ee03a3ca 100644 --- a/tests/unittests/ClassTests.cpp +++ b/tests/unittests/ClassTests.cpp @@ -2502,3 +2502,18 @@ endclass compilation.addSyntaxTree(tree); NO_COMPILATION_ERRORS; } + +TEST_CASE("Class parameter defaults regression") { + auto tree = SyntaxTree::fromText(R"( +class C #(type T1=int, T2=T1, parameter T1 foo = 1, parameter int bar = foo); +endclass + +module m; + C c = new; +endmodule +)"); + + Compilation compilation; + compilation.addSyntaxTree(tree); + NO_COMPILATION_ERRORS; +}