From 74cdfed9d649db0dba413ca28960d0bf93c6f78a Mon Sep 17 00:00:00 2001 From: drpriver Date: Wed, 9 Apr 2025 16:16:54 -0700 Subject: [PATCH] ImportC: improve error message for size_t (#21187) Resolves: https://github.com/dlang/dmd/issues/20414 Add some hints for common missing includes. --- compiler/src/dmd/expressionsem.d | 30 ++++++++++++++------ compiler/src/dmd/imphint.d | 24 ++++++++++++++++ compiler/src/dmd/typesem.d | 33 ++++++++++++++-------- compiler/test/fail_compilation/test20414.c | 15 ++++++++++ compiler/test/fail_compilation/test23003.c | 2 +- 5 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 compiler/test/fail_compilation/test20414.c diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index d12f442889..61ef350bde 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -4116,16 +4116,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor /* Look for what user might have meant */ - if (const n = importHint(exp.ident.toString())) - error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); - else if (auto s2 = sc.search_correct(exp.ident)) - error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); - else if (const p = Scope.search_correct_C(exp.ident)) - error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p); - else if (exp.ident == Id.dollar) - error(exp.loc, "undefined identifier `$`"); + if (!(sc && sc.inCfile)) + { + if (const n = importHint(exp.ident.toString())) + error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(exp.ident)) + error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); + else if (const p = Scope.search_correct_C(exp.ident)) + error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p); + else if (exp.ident == Id.dollar) + error(exp.loc, "undefined identifier `$`"); + else + error(exp.loc, "undefined identifier `%s`", exp.ident.toChars()); + } else - error(exp.loc, "undefined identifier `%s`", exp.ident.toChars()); + { + if (const n = cIncludeHint(exp.ident.toString())) + error(exp.loc, "`%s` is not defined, perhaps `#include %.*s` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(exp.ident)) + error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); + else + error(exp.loc, "undefined identifier `%s`", exp.ident.toChars()); + } result = ErrorExp.get(); } diff --git a/compiler/src/dmd/imphint.d b/compiler/src/dmd/imphint.d index 382a0f3786..e22bcc8b12 100644 --- a/compiler/src/dmd/imphint.d +++ b/compiler/src/dmd/imphint.d @@ -26,8 +26,15 @@ const(char)[] importHint(const(char)[] s) @safe return *entry; return null; } +const(char)[] cIncludeHint(const(char)[] s) @safe +{ + if (auto entry = s in cHints) + return *entry; + return null; +} private immutable string[string] hints; +private immutable string[string] cHints; shared static this() { @@ -83,6 +90,23 @@ shared static this() "InterpolationHeader": "core.interpolation", "InterpolationFooter": "core.interpolation", ]; + cHints = [ + "NULL": "", + "calloc": "", + "fopen": "", + "fprintf": "", + "free": "", + "malloc": "", + "memcpy": "", + "memmove": "", + "memset": "", + "printf": "", + "ptrdiff_t": "", + "size_t": "", + "stderr": "", + "stdin": "", + "stdout": "", + ]; } unittest diff --git a/compiler/src/dmd/typesem.d b/compiler/src/dmd/typesem.d index 9b706d162c..59f22fa778 100644 --- a/compiler/src/dmd/typesem.d +++ b/compiler/src/dmd/typesem.d @@ -169,17 +169,28 @@ private void resolveHelper(TypeQualified mt, Loc loc, Scope* sc, Dsymbol s, Dsym */ const p = mt.mutableOf().unSharedOf().toChars(); auto id = Identifier.idPool(p[0 .. strlen(p)]); - if (const n = importHint(id.toString())) - error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr); - else if (auto s2 = sc.search_correct(id)) - error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); - else if (const q = Scope.search_correct_C(id)) - error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q); - else if ((id == Id.This && sc.getStructClassScope()) || - (id == Id._super && sc.getClassScope())) - error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p); - else - error(loc, "undefined identifier `%s`", p); + if (!(sc && sc.inCfile)) + { + if (const n = importHint(id.toString())) + error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(id)) + error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); + else if (const q = Scope.search_correct_C(id)) + error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q); + else if ((id == Id.This && sc.getStructClassScope()) || + (id == Id._super && sc.getClassScope())) + error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p); + else + error(loc, "undefined identifier `%s`", p); + } + else { + if (const n = cIncludeHint(id.toString())) + error(loc, "`%s` is not defined, perhaps `#include %.*s` ?", p, cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(id)) + error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); + else + error(loc, "undefined identifier `%s`", p); + } pt = Type.terror; return; diff --git a/compiler/test/fail_compilation/test20414.c b/compiler/test/fail_compilation/test20414.c new file mode 100644 index 0000000000..90fff588f9 --- /dev/null +++ b/compiler/test/fail_compilation/test20414.c @@ -0,0 +1,15 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test20414.c(1): Error: `size_t` is not defined, perhaps `#include ` ? +fail_compilation/test20414.c(2): Error: `ptrdiff_t` is not defined, perhaps `#include ` ? +fail_compilation/test20414.c(3): Error: `NULL` is not defined, perhaps `#include ` is needed? +fail_compilation/test20414.c(5): Error: undefined identifier `fooo`, did you mean function `foo`? +--- +*/ + +#line 1 +size_t x; +ptrdiff_t pd; +void *p = NULL; +void foo(void); +void (*fp)(void) = &fooo; diff --git a/compiler/test/fail_compilation/test23003.c b/compiler/test/fail_compilation/test23003.c index 3a5d92d783..df4c46fc87 100644 --- a/compiler/test/fail_compilation/test23003.c +++ b/compiler/test/fail_compilation/test23003.c @@ -1,6 +1,6 @@ /* TEST_OUTPUT: --- -fail_compilation/test23003.c(101): Error: undefined identifier `size_t` +fail_compilation/test23003.c(101): Error: `size_t` is not defined, perhaps `#include ` ? fail_compilation/test23003.c(102): Error: undefined identifier `object` --- */