mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
dtoh: Emit public imports in aggregates whenever possible
Previously only top-level imports were included by the header generator. This isn't sufficient because patterns like `ASTCodegen` require the imported symbols to be available as members of the aggregate. Also added the checks for `static` and non-public imports that were lost in the first PR.
This commit is contained in:
parent
1b6d90cc74
commit
45810b608f
6 changed files with 2463 additions and 1660 deletions
|
@ -9,7 +9,7 @@ experimental C++ header generator:
|
|||
- `extern(D)` structs and classes are emitted if referenced by an exported symbol
|
||||
- Forward declarations consistently include `template<...>`
|
||||
- `extern(C++, class)`, `extern(C++, struct)` affects forward declarations
|
||||
- Renamed imports are emitted as `using ...`
|
||||
- Renamed or local imports are emitted as `using ...` when possible
|
||||
- Complex types are emitted as `_Complex`.
|
||||
- Declarations are emitted before the first member access
|
||||
- Global variables with invalid names in C++ are omitted
|
||||
|
|
|
@ -556,22 +556,57 @@ public:
|
|||
buf.writestring("using ");
|
||||
writeIdentifier(alias_, i.loc, "renamed import");
|
||||
buf.writestring(" = ");
|
||||
// Start at module scope to avoid collisions with local symbols
|
||||
if (this.context.adparent)
|
||||
buf.writestring("::");
|
||||
buf.writestring(sym.ident.toString());
|
||||
writeDeclEnd();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Omit local imports
|
||||
assert(i.parent);
|
||||
if (!i.parent.isModule())
|
||||
// Only missing without semantic analysis
|
||||
// FIXME: Templates need work due to missing parent & imported module
|
||||
if (!i.parent)
|
||||
{
|
||||
ignored("local %s", i.toChars());
|
||||
assert(tdparent);
|
||||
ignored("`%s` because it's inside of a template declaration", i.toChars());
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-public imports don't create new symbols, include as needed
|
||||
if (i.visibility.kind < AST.Visibility.Kind.public_)
|
||||
return;
|
||||
|
||||
// Symbols from static imports should be emitted inline
|
||||
if (i.isstatic)
|
||||
return;
|
||||
|
||||
const isLocal = !i.parent.isModule();
|
||||
|
||||
// Need module for symbol lookup
|
||||
assert(i.mod);
|
||||
|
||||
// Emit an alias for each public module member
|
||||
if (isLocal && i.names.length == 0)
|
||||
{
|
||||
assert(i.mod.symtab);
|
||||
foreach (entry; i.mod.symtab.tab.asRange)
|
||||
{
|
||||
auto ident = entry.key;
|
||||
auto sym = entry.value;
|
||||
|
||||
// Skip invisible members
|
||||
import dmd.access : symbolIsVisible;
|
||||
if (!symbolIsVisible(i, sym))
|
||||
continue;
|
||||
|
||||
includeSymbol(sym);
|
||||
if (auto err = writeImport(sym, ident))
|
||||
ignored("public import for `%s` because `using` %s", ident.toChars(), err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Include all public imports and emit using declarations for each alias
|
||||
foreach (const idx, name; i.names)
|
||||
{
|
||||
|
@ -1592,6 +1627,16 @@ public:
|
|||
|
||||
override void visit(AST.EnumMember em)
|
||||
{
|
||||
assert(em.ed);
|
||||
|
||||
// Members of anonymous members are reachable without referencing the
|
||||
// EnumDeclaration, e.g. public import foo : someEnumMember;
|
||||
if (em.ed.isAnonymous())
|
||||
{
|
||||
visit(em.ed);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(false, "This node type should be handled in the EnumDeclaration");
|
||||
}
|
||||
|
||||
|
|
3978
src/dmd/frontend.h
3978
src/dmd/frontend.h
File diff suppressed because it is too large
Load diff
|
@ -51,6 +51,11 @@ class ImportsC
|
|||
|
||||
typedef int32_t MyStdcInt;
|
||||
|
||||
enum
|
||||
{
|
||||
IgnoreErrors = 0,
|
||||
};
|
||||
|
||||
typedef int32_t T;
|
||||
|
||||
extern "C" int32_t x;
|
||||
|
@ -90,6 +95,30 @@ typedef TSD<int32_t, int16_t > TSI;
|
|||
using aliasName = ImportsC;
|
||||
|
||||
using MyStdc = MyStdcInt;
|
||||
|
||||
struct FullImport final
|
||||
{
|
||||
using MyStdcInt = ::MyStdcInt;
|
||||
using ImportsC = ::ImportsC;
|
||||
FullImport()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectiveImports final
|
||||
{
|
||||
using aliasName = ::ImportsC;
|
||||
SelectiveImports()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct PrivateImport final
|
||||
{
|
||||
PrivateImport()
|
||||
{
|
||||
}
|
||||
};
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -141,3 +170,24 @@ public import dtoh_imports :
|
|||
importFunc,
|
||||
aliasName = ImportsC,
|
||||
MyStdc = MyStdcInt;
|
||||
|
||||
struct FullImport
|
||||
{
|
||||
public import dtoh_imports;
|
||||
|
||||
}
|
||||
|
||||
struct SelectiveImports
|
||||
{
|
||||
public import dtoh_imports :
|
||||
importFunc,
|
||||
aliasName = ImportsC;
|
||||
|
||||
public static import dtoh_imports;
|
||||
}
|
||||
|
||||
struct PrivateImport
|
||||
{
|
||||
import dtoh_imports;
|
||||
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ extern void importFunc();
|
|||
// Ignored renamed import `myFunc = importFunc` because `using` only supports types
|
||||
struct A final
|
||||
{
|
||||
// Ignored local __anonymous
|
||||
// Ignored renamed import `myFunc = importFunc` because `using` only supports types
|
||||
A()
|
||||
{
|
||||
}
|
||||
|
@ -82,6 +82,23 @@ public:
|
|||
extern void unused();
|
||||
|
||||
// Ignored variable dtoh_verbose.and because its name is a special operator in C++
|
||||
template <typename T>
|
||||
struct FullImportTmpl final
|
||||
{
|
||||
// Ignored `dtoh_imports` because it's inside of a template declaration
|
||||
FullImportTmpl()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SelectiveImportsTmpl final
|
||||
{
|
||||
// Ignored `__anonymous` because it's inside of a template declaration
|
||||
SelectiveImportsTmpl()
|
||||
{
|
||||
}
|
||||
};
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -112,7 +129,7 @@ public import dtoh_imports : myFunc = importFunc;
|
|||
|
||||
extern(C++) struct A
|
||||
{
|
||||
import core.stdc.errno : cErrorC = errno;
|
||||
public import dtoh_imports : myFunc = importFunc;
|
||||
}
|
||||
|
||||
extern(C++) struct Hidden
|
||||
|
@ -140,3 +157,16 @@ extern(C++) class Visitor
|
|||
extern(C++) void unused() {}
|
||||
|
||||
extern(C++) __gshared bool and;
|
||||
|
||||
extern(C++) struct FullImportTmpl(T)
|
||||
{
|
||||
public import dtoh_imports;
|
||||
|
||||
}
|
||||
|
||||
extern(C++) struct SelectiveImportsTmpl(T)
|
||||
{
|
||||
public import dtoh_imports :
|
||||
importFunc,
|
||||
aliasName = ImportsC;
|
||||
}
|
||||
|
|
|
@ -5,3 +5,9 @@ public import dtoh_imports2 : MyStdcInt = customInt;
|
|||
class ImportsC {}
|
||||
|
||||
void importFunc() {}
|
||||
|
||||
private struct HiddenData {}
|
||||
|
||||
enum : int {
|
||||
IgnoreErrors
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue