Skip to content

Commit edd6f3d

Browse files
authored
cgen: stop treating every .m as an Objective-C import (#26794)
cgen was using a plain `contains('.m')` check when deciding whether a hash directive should be deferred until after V type definitions. That worked for real Objective-C includes, but it also caught unrelated cases like a `#insert` under a `@VMODROOT` path that happened to include a `.m` directory, or a `#define` value containing `.m`. When that happened, the directive was moved out of the normal include section and never emitted. Tighten the check so only `#include` and `#preinclude` directives whose target file actually ends in `.m` get the Objective-C treatment, and add regression tests for both the `#insert` and `#define` cases.
1 parent e8d0714 commit edd6f3d

4 files changed

Lines changed: 28 additions & 5 deletions

File tree

‎vlib/v/gen/c/cgen.v‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6179,10 +6179,11 @@ fn (mut g Gen) hash_stmt(node ast.HashStmt) {
61796179
} else {
61806180
&ast.HashStmtNode(&node)
61816181
}
6182+
is_objc_target := is_objc_hash_target(node.kind, node.main)
61826183

61836184
match node.kind {
61846185
'include', 'insert', 'define' {
6185-
if node.main.contains('.m') {
6186+
if is_objc_target {
61866187
// Objective C code import, include it after V types, so that e.g. `string` is
61876188
// available there
61886189
if the_node !in g.definition_nodes {
@@ -6195,7 +6196,7 @@ fn (mut g Gen) hash_stmt(node ast.HashStmt) {
61956196
}
61966197
}
61976198
'preinclude' {
6198-
if node.main.contains('.m') {
6199+
if is_objc_target {
61996200
// Objective C code import, include it after V types, so that e.g. `string` is
62006201
// available there
62016202
if the_node !in g.definition_nodes {
@@ -6216,6 +6217,18 @@ fn (mut g Gen) hash_stmt(node ast.HashStmt) {
62166217
}
62176218
}
62186219

6220+
fn is_objc_hash_target(kind string, raw_target string) bool {
6221+
if kind !in ['include', 'preinclude'] {
6222+
return false
6223+
}
6224+
mut target := raw_target.trim_space()
6225+
if target.len >= 2 && ((target.starts_with('"') && target.ends_with('"'))
6226+
|| (target.starts_with('<') && target.ends_with('>'))) {
6227+
target = target[1..target.len - 1]
6228+
}
6229+
return os.file_name(target).ends_with('.m')
6230+
}
6231+
62196232
fn (mut g Gen) gen_hash_stmts(mut sb strings.Builder, node &ast.HashStmtNode, section string) {
62206233
match node {
62216234
ast.IfExpr {
@@ -6272,12 +6285,13 @@ fn (mut g Gen) gen_hash_stmts(mut sb strings.Builder, node &ast.HashStmtNode, se
62726285
// #inlude,#define,#insert => `includes` section
62736286
// #postinclude => `postincludes` section
62746287
// '*.m' in #include or #preinclude => `definitions` section
6288+
is_objc_target := is_objc_hash_target(node.kind, node.main)
62756289
need_gen_stmt := match section {
62766290
'preincludes' {
6277-
if node.kind == 'preinclude' && !node.main.contains('.m') { true } else { false }
6291+
if node.kind == 'preinclude' && !is_objc_target { true } else { false }
62786292
}
62796293
'includes' {
6280-
if node.kind in ['include', 'define', 'insert'] && !node.main.contains('.m') {
6294+
if node.kind in ['include', 'define', 'insert'] && !is_objc_target {
62816295
true
62826296
} else {
62836297
false
@@ -6286,7 +6300,7 @@ fn (mut g Gen) gen_hash_stmts(mut sb strings.Builder, node &ast.HashStmtNode, se
62866300
'definitions' {
62876301
// Objective C code import, include it after V types, so that e.g. `string` is
62886302
// available there
6289-
if node.kind in ['include', 'preinclude'] && node.main.contains('.m') {
6303+
if node.kind in ['include', 'preinclude'] && is_objc_target {
62906304
true
62916305
} else {
62926306
false
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define DOT_M_INSERT_OK 1
2+
#define DOT_M_DEFINE_OK "tmp/project.m/value.h"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define DOT_M_INSERT_OK 1
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// This reproduces a false positive in the old `.contains('.m')` check:
2+
// neither the inserted header nor the define value is an Objective-C `.m` import.
3+
#insert "@DIR/hash_stmt_dot_m_false_positive.m.h"
4+
#define DOT_M_DEFINE_OK "tmp/project.m/value.h"
5+
6+
fn main() {}

0 commit comments

Comments
 (0)