}
PutLower(decls_ << "::", typeSymbol);
auto &typeScope{*typeSymbol.scope()};
- if (details.hasTypeParams()) {
+ if (!details.paramNames().empty()) {
bool first{true};
decls_ << '(';
- for (const auto *symbol : CollectSymbols(typeScope)) {
- if (symbol->has<TypeParamDetails>()) {
- PutLower(first ? decls_ : decls_ << ',', *symbol);
- first = false;
- }
+ for (const auto &name : details.paramNames()) {
+ PutLower(first ? decls_ : decls_ << ',', name.ToString());
+ first = false;
}
decls_ << ')';
}
const Symbol *ResolveDerivedType(const parser::Name &);
bool CanBeTypeBoundProc(const Symbol &);
Symbol *FindExplicitInterface(const parser::Name &);
- Symbol &MakeTypeSymbol(const parser::Name &, Details &&);
+ bool MakeTypeSymbol(const parser::Name &, Details &&);
bool OkToAddComponent(const parser::Name &, bool isParentComp = false);
// Declare an object or procedure entity.
void DeclarationVisitor::Post(const parser::DerivedTypeDef &x) {
std::set<SourceName> paramNames;
auto &scope{currScope()};
+ auto &details{scope.symbol()->get<DerivedTypeDetails>()};
auto &stmt{std::get<parser::Statement<parser::DerivedTypeStmt>>(x.t)};
for (auto ¶mName : std::get<std::list<parser::Name>>(stmt.statement.t)) {
+ details.add_paramName(paramName.source);
auto *symbol{FindInScope(scope, paramName)};
if (!symbol) {
Say(paramName,
"Duplicate type parameter name: '%s'"_err_en_US); // C731
}
}
- auto &details{scope.symbol()->get<DerivedTypeDetails>()};
- details.set_hasTypeParams(!paramNames.empty());
for (const auto &[name, symbol] : currScope()) {
if (symbol->has<TypeParamDetails>() && !paramNames.count(name)) {
SayDerivedType(name,
Say(stmt.source,
"A sequence type may not have the EXTENDS attribute"_err_en_US); // C735
}
- if (details.hasTypeParams()) {
+ if (!details.paramNames().empty()) {
Say(stmt.source,
"A sequence type may not have type parameters"_err_en_US); // C740
}
std::get<std::optional<parser::ScalarIntConstantExpr>>(decl.t)}) {
details.set_init(EvaluateExpr(*init));
}
- MakeTypeSymbol(name, std::move(details));
- SetType(name, *type);
+ if (MakeTypeSymbol(name, std::move(details))) {
+ SetType(name, *type);
+ }
}
EndDecl();
}
}
// Create a symbol for a type parameter, component, or procedure binding in
-// the current derived type scope.
-Symbol &DeclarationVisitor::MakeTypeSymbol(
+// the current derived type scope. Return false on error.
+bool DeclarationVisitor::MakeTypeSymbol(
const parser::Name &name, Details &&details) {
Scope &derivedType{currScope()};
CHECK(derivedType.kind() == Scope::Kind::DerivedType);
"Type parameter, component, or procedure binding '%s'"
" already defined in this type"_err_en_US,
*symbol, "Previous definition of '%s'"_en_US);
- return *symbol;
+ return false;
} else {
auto attrs{GetAttrs()};
// Apply binding-private-stmt if present and this is a procedure binding
std::holds_alternative<ProcBindingDetails>(details)) {
attrs.set(Attr::PRIVATE);
}
- return MakeSymbol(name, attrs, details);
+ MakeSymbol(name, attrs, details);
+ return true;
}
}
class DerivedTypeDetails {
public:
- bool hasTypeParams() const { return hasTypeParams_; }
+ const std::list<SourceName> ¶mNames() const { return paramNames_; }
const Symbol *extends() const { return extends_; }
bool sequence() const { return sequence_; }
- void set_hasTypeParams(bool x = true) { hasTypeParams_ = x; }
+ void add_paramName(const SourceName &name) { paramNames_.emplace_back(name); }
void set_extends(const Symbol *extends) { extends_ = extends; }
void set_sequence(bool x = true) { sequence_ = x; }
private:
- bool hasTypeParams_{false};
+ std::list<SourceName> paramNames_;
const Symbol *extends_{nullptr};
bool sequence_{false};
};