fortrangoingonforty/armfortas / c3e91c2

Browse files

Detect TBP-call returning character in print path char-expression check

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
c3e91c2fa1cda9633df35c374ca12236a15cedfd
Parents
75a6c00
Tree
483bbd2

1 changed file

StatusFile+-
M src/ir/lower.rs 55 1
src/ir/lower.rsmodified
@@ -40350,7 +40350,61 @@ fn expr_is_character_expr(
4035040350
                                     }))
4035140351
                         })
4035240352
                         .unwrap_or(false)
40353
-            } else if let Expr::ComponentAccess { .. } = &callee.node {
40353
+            } else if let Expr::ComponentAccess {
40354
+                base: tbp_base,
40355
+                component: tbp_component,
40356
+            } = &callee.node
40357
+            {
40358
+                // F2008 §4.5.4 type-bound procedure call: `obj%method()`
40359
+                // where `method` is a TBP (not a data field). The data-
40360
+                // field lookups below return None for a TBP since TBPs
40361
+                // don't appear in `layout.fields`. Without this branch
40362
+                // the print path mis-classifies a TBP returning
40363
+                // `character(:), allocatable :: r` as non-character and
40364
+                // emits a scalar writer that reads the descriptor
40365
+                // pointer as an integer — surfaced as a silently
40366
+                // empty `print *, e%print()` for stdlib_linalg_state's
40367
+                // state_message TBP.
40368
+                let tbp_char = type_layouts.and_then(|tl| {
40369
+                    let (_, base_type) =
40370
+                        resolve_component_base_for_method(b, locals, tbp_base, st, tl)?;
40371
+                    let layout = tl.get(&base_type)?;
40372
+                    let bp = layout.bound_proc(tbp_component)?;
40373
+                    // The TBP `target_name` carries the mangled IR symbol
40374
+                    // (e.g. `afs_modproc_mod_proc`); the symbol table is
40375
+                    // keyed by the source-level procedure name. Strip the
40376
+                    // mangling prefix and the leading module segment so
40377
+                    // the lookup hits the function symbol with its
40378
+                    // type_info populated.
40379
+                    let raw_target = bp.target_name.as_str();
40380
+                    let stripped = raw_target
40381
+                        .strip_prefix("afs_modproc_")
40382
+                        .map(|s| {
40383
+                            // Format: afs_modproc_<module>_<proc>. Module
40384
+                            // name itself can contain underscores, so
40385
+                            // try progressively shorter prefixes until
40386
+                            // the symtab finds a match.
40387
+                            let mut candidates: Vec<String> = Vec::new();
40388
+                            candidates.push(s.to_string());
40389
+                            let mut cursor = s;
40390
+                            while let Some(idx) = cursor.find('_') {
40391
+                                cursor = &cursor[idx + 1..];
40392
+                                candidates.push(cursor.to_string());
40393
+                            }
40394
+                            candidates
40395
+                        })
40396
+                        .unwrap_or_else(|| vec![raw_target.to_string()]);
40397
+                    let target = stripped
40398
+                        .iter()
40399
+                        .find_map(|cand| st.find_symbol_any_scope(cand))?;
40400
+                    Some(matches!(
40401
+                        target.type_info,
40402
+                        Some(crate::sema::symtab::TypeInfo::Character { .. })
40403
+                    ))
40404
+                });
40405
+                if let Some(true) = tbp_char {
40406
+                    return true;
40407
+                }
4035440408
                 type_layouts
4035540409
                     .and_then(|tl| {
4035640410
                         component_array_local_info(b, locals, callee, st, tl).or_else(|| {