CHECK(spec.scope() != nullptr);
const Symbol &typeSymbol{spec.typeSymbol()};
+ if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
+ if (auto *msg{context.Say(typeName,
+ "ABSTRACT derived type '%s' cannot be used in a structure constructor"_err_en_US,
+ typeName.ToString().data())}) {
+ msg->Attach(
+ typeSymbol.name(), "Declaration of ABSTRACT derived type"_en_US);
+ }
+ }
+
// This list holds all of the components in the derived type and its
// parents. The symbols for whole parent components appear after their
// own components and before the components of the types that extend them.
// initialize X or A by name, but not both.
const auto &details{typeSymbol.get<semantics::DerivedTypeDetails>()};
std::list<const Symbol *> components{details.OrderComponents(*spec.scope())};
- if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
- if (auto *msg{context.Say(typeName,
- "ABSTRACT derived type '%s' cannot be used in a structure constructor"_err_en_US,
- typeName.ToString().data())}) {
- msg->Attach(
- typeSymbol.name(), "Declaration of ABSTRACT derived type"_en_US);
- }
- }
+ auto nextAnonymous{components.begin()};
std::set<parser::CharBlock> unavailable;
bool anyKeyword{false};
const parser::Expr &expr{
*std::get<parser::ComponentDataSource>(component.t).v};
parser::CharBlock source{expr.source};
+ const Symbol *symbol{nullptr};
if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
source = kw->v.source;
+ symbol = kw->v.symbol;
anyKeyword = true;
- } else if (anyKeyword) { // C7100
- context.Say(source,
- "Value in structure constructor lacks a component name"_err_en_US);
- checkConflicts = false; // stem cascade
- }
- if (component.symbol == nullptr) {
- context.Say(
- source, "INTERNAL: StructureConstructor lacks symbol"_err_en_US);
- continue;
- }
- const Symbol &symbol{*component.symbol};
- if (symbol.has<semantics::TypeParamDetails>()) {
- context.Say(source,
- "Type parameter '%s' cannot be a component of this structure constructor"_err_en_US,
- symbol.name().ToString().data());
- } else if (checkConflicts) {
- auto componentIter{
- std::find(components.begin(), components.end(), &symbol)};
- if (unavailable.find(symbol.name()) != unavailable.cend()) {
- // C797, C798
+ } else {
+ if (anyKeyword) { // C7100
context.Say(source,
- "Component '%s' conflicts with another component earlier in this structure constructor"_err_en_US,
- symbol.name().ToString().data());
- } else if (symbol.test(Symbol::Flag::ParentComp)) {
- // Make earlier components unavailable once a whole parent appears.
- for (auto it{components.begin()}; it != componentIter; ++it) {
- unavailable.insert((*it)->name());
+ "Value in structure constructor lacks a component name"_err_en_US);
+ checkConflicts = false; // stem cascade
+ }
+ while (nextAnonymous != components.end()) {
+ symbol = *nextAnonymous++;
+ if (!symbol->test(Symbol::Flag::ParentComp)) {
+ break;
}
- } else {
- // Make whole parent components unavailable after any of their
- // constituents appear.
- for (auto it{componentIter}; it != components.end(); ++it) {
- if ((*it)->test(Symbol::Flag::ParentComp)) {
+ }
+ if (symbol == nullptr) {
+ context.Say(
+ source, "Unexpected value in structure constructor"_err_en_US);
+ }
+ }
+ if (symbol != nullptr) {
+ if (symbol->has<semantics::TypeParamDetails>()) {
+ context.Say(source,
+ "Type parameter '%s' cannot be a component of this structure constructor"_err_en_US,
+ symbol->name().ToString().data());
+ } else if (checkConflicts) {
+ auto componentIter{
+ std::find(components.begin(), components.end(), symbol)};
+ if (unavailable.find(symbol->name()) != unavailable.cend()) {
+ // C797, C798
+ context.Say(source,
+ "Component '%s' conflicts with another component earlier in this structure constructor"_err_en_US,
+ symbol->name().ToString().data());
+ } else if (symbol->test(Symbol::Flag::ParentComp)) {
+ // Make earlier components unavailable once a whole parent appears.
+ for (auto it{components.begin()}; it != componentIter; ++it) {
unavailable.insert((*it)->name());
}
+ } else {
+ // Make whole parent components unavailable after any of their
+ // constituents appear.
+ for (auto it{componentIter}; it != components.end(); ++it) {
+ if ((*it)->test(Symbol::Flag::ParentComp)) {
+ unavailable.insert((*it)->name());
+ }
+ }
}
}
- }
- unavailable.insert(symbol.name());
- if (MaybeExpr value{AnalyzeExpr(context, expr)}) {
- // TODO pmk: C7104, C7105 check that pointer components are
- // being initialized with data/procedure designators appropriately
- result.Add(symbol, std::move(*value));
+ unavailable.insert(symbol->name());
+ if (MaybeExpr value{AnalyzeExpr(context, expr)}) {
+ // TODO pmk: C7104, C7105 check that pointer components are
+ // being initialized with data/procedure designators appropriately
+ result.Add(*symbol, std::move(*value));
+ }
}
}
EndDeclTypeSpec();
SetDeclTypeSpecState(savedState);
- auto &typeName{std::get<parser::Name>(parsedType.t)};
- const DerivedTypeSpec *spec{type ? type->AsDerived() : nullptr};
- const Symbol *typeSymbol{spec ? &spec->typeSymbol() : nullptr};
+ if (type == nullptr) {
+ return false;
+ }
+ const DerivedTypeSpec *spec{type->AsDerived()};
const Scope *typeScope{spec ? spec->scope() : nullptr};
-
- // This list holds all of the components in the derived type and its
- // parents. The symbols for whole parent components appear after their
- // own components and before the components of the types that extend them.
- // E.g., TYPE :: A; REAL X; END TYPE
- // TYPE, EXTENDS(A) :: B; REAL Y; END TYPE
- // produces the component list X, A, Y.
- // The order is important below because a structure constructor can
- // initialize X or A by name, but not both.
- SymbolList components;
- bool ok{typeSymbol != nullptr && typeScope != nullptr};
- if (ok) {
- components =
- typeSymbol->get<DerivedTypeDetails>().OrderComponents(*typeScope);
- if (typeSymbol->attrs().test(Attr::ABSTRACT)) { // C796
- SayWithDecl(typeName, *typeSymbol,
- "ABSTRACT type cannot be used in a structure constructor"_err_en_US);
- }
+ if (typeScope == nullptr) {
+ return false;
}
// N.B C7102 is implicitly enforced by having inaccessible types not
// being found in resolution.
- auto nextAnonymous{components.begin()};
for (const auto &component :
std::get<std::list<parser::ComponentSpec>>(x.t)) {
// Visit the component spec expression, but not the keyword, since
// we need to resolve its symbol in the scope of the derived type.
- const parser::Expr &value{
- *std::get<parser::ComponentDataSource>(component.t).v};
- Walk(value);
- const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)};
- const Symbol *symbol{nullptr};
- SourceName source{value.source};
- if (kw.has_value()) {
- source = kw->v.source;
- if (ok) {
- symbol = FindInTypeOrParents(*typeScope, kw->v);
- if (symbol == nullptr) { // C7101
- Say(source,
- "Keyword '%s' is not a component of this derived type"_err_en_US);
- ok = false;
- }
+ Walk(std::get<parser::ComponentDataSource>(component.t));
+ if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
+ if (const Symbol * symbol{FindInTypeOrParents(*typeScope, kw->v)}) {
+ CheckAccessibleComponent(kw->v.source, *symbol); // C7102
+ } else { // C7101
+ Say(kw->v.source,
+ "Keyword '%s' is not a component of this derived type"_err_en_US);
}
- } else if (ok) {
- while (nextAnonymous != components.end()) {
- symbol = *nextAnonymous++;
- if (symbol->test(Symbol::Flag::ParentComp)) {
- symbol = nullptr;
- } else {
- break;
- }
- }
- if (symbol == nullptr) {
- Say(source, "Unexpected value in structure constructor"_err_en_US);
- break;
- }
- }
- if (symbol != nullptr) {
- // Save the resolved component's symbol (if any) in the parse tree.
- component.symbol = symbol;
- CheckAccessibleComponent(source, *symbol); // C7102
}
}
return false;