Merge pull request #11669 from MoonlightSentinel/silent-headers

Make "ignored..." comments in the C++ header generation optional
This commit is contained in:
Sebastian Wilzbach 2020-09-02 20:45:11 +02:00 committed by GitHub
commit 8f9ad0520e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 197 additions and 2108 deletions

View file

@ -0,0 +1,22 @@
C++ header generation omits `Ignored ...` comments by default
The C++ header generated used to write comments when it encountered
non-`extern(C++)` declarations, e.g.
---
// test.d
void foo() {}
---
---
// test.h
[...]
// ignoring function test.foo because of linkage
---
This caused a lot of bloat in the generated header file and is now
customizable via the `-HC=<mode> switch which accepts either
`verbose` (write comments) and `silent` (omit comments). The default
was changed to `silent`.
Note: The header generator is still considerer experimental, so please
submit any bugs encountered to [the bug tracker](https://issues.dlang.org).

View file

@ -369,8 +369,16 @@ dmd -cov -unittest myprog.d
Option("Hf=<filename>", Option("Hf=<filename>",
"write 'header' file to filename" "write 'header' file to filename"
), ),
Option("HC", Option("HC[=[silent|verbose]]",
"generate C++ 'header' file" "generate C++ 'header' file",
`Generate C++ 'header' files using the given configuration:",
$(DL
$(DT silent)$(DD only list extern(C[++]) declarations (default))
$(DT verbose)$(DD also add comments for ignored declarations (e.g. extern(D)))
)`,
),
Option("HC=[?|h|help]",
"list available modes for C++ 'header' file generation"
), ),
Option("HCd=<directory>", Option("HCd=<directory>",
"write C++ 'header' file to directory" "write C++ 'header' file to directory"
@ -882,4 +890,11 @@ struct CLIUsage
=c++14 Sets `__traits(getTargetInfo, \"cppStd\")` to `201402` =c++14 Sets `__traits(getTargetInfo, \"cppStd\")` to `201402`
=c++17 Sets `__traits(getTargetInfo, \"cppStd\")` to `201703` =c++17 Sets `__traits(getTargetInfo, \"cppStd\")` to `201703`
"; ";
/// Options supported by -HC
enum hcUsage = "Available header generation modes:
=[h|help|?] List information on all available choices
=silent Silently ignore non-exern(C[++]) declarations
=verbose Add a comment for ignored non-exern(C[++]) declarations
";
} }

View file

@ -418,6 +418,7 @@ public:
bool hasAnonNumericEnum; bool hasAnonNumericEnum;
bool hasNumericConstant; bool hasNumericConstant;
bool hasTypedConstant; bool hasTypedConstant;
const bool printIgnored;
this(OutBuffer* checkbuf, OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf) this(OutBuffer* checkbuf, OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf)
{ {
@ -425,6 +426,7 @@ public:
this.fwdbuf = fwdbuf; this.fwdbuf = fwdbuf;
this.donebuf = donebuf; this.donebuf = donebuf;
this.buf = buf; this.buf = buf;
this.printIgnored = global.params.doCxxHdrGeneration == CxxHeaderMode.verbose;
} }
private EnumKind getEnumKind(AST.Type type) private EnumKind getEnumKind(AST.Type type)
@ -486,11 +488,14 @@ public:
} }
if (isBuildingCompiler && s.getModule() && s.getModule().isFrontendModule()) if (isBuildingCompiler && s.getModule() && s.getModule().isFrontendModule())
{
if (printIgnored)
{ {
buf.printf("// ignored %s %s", s.kind(), s.toPrettyChars()); buf.printf("// ignored %s %s", s.kind(), s.toPrettyChars());
buf.writenl(); buf.writenl();
} }
} }
}
override void visit(AST.Import i) override void visit(AST.Import i)
{ {
@ -529,10 +534,13 @@ public:
auto save = linkage; auto save = linkage;
linkage = ld.linkage; linkage = ld.linkage;
if (ld.linkage != LINK.c && ld.linkage != LINK.cpp) if (ld.linkage != LINK.c && ld.linkage != LINK.cpp)
{
if (printIgnored)
{ {
buf.printf("// ignoring %s block because of linkage", ld.toPrettyChars()); buf.printf("// ignoring %s block because of linkage", ld.toPrettyChars());
buf.writenl(); buf.writenl();
} }
}
else else
{ {
visit(cast(AST.AttribDeclaration)ld); visit(cast(AST.AttribDeclaration)ld);
@ -572,21 +580,30 @@ public:
auto tf = cast(AST.TypeFunction)fd.type; auto tf = cast(AST.TypeFunction)fd.type;
if (!tf || !tf.deco) if (!tf || !tf.deco)
{
if (printIgnored)
{ {
buf.printf("// ignoring function %s because semantic hasn't been run", fd.toPrettyChars()); buf.printf("// ignoring function %s because semantic hasn't been run", fd.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
if (tf.linkage != LINK.c && tf.linkage != LINK.cpp) if (tf.linkage != LINK.c && tf.linkage != LINK.cpp)
{
if (printIgnored)
{ {
buf.printf("// ignoring function %s because of linkage", fd.toPrettyChars()); buf.printf("// ignoring function %s because of linkage", fd.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
if (!adparent && !fd.fbody) if (!adparent && !fd.fbody)
{
if (printIgnored)
{ {
buf.printf("// ignoring function %s because it's extern", fd.toPrettyChars()); buf.printf("// ignoring function %s because it's extern", fd.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
@ -699,6 +716,7 @@ public:
break; break;
case EnumKind.Other: case EnumKind.Other:
if (printIgnored)
buf.printf("// ignoring enum `%s` because type `%s` is currently not supported for enum constants.\n", vd.toPrettyChars(), type.toChars()); buf.printf("// ignoring enum `%s` because type `%s` is currently not supported for enum constants.\n", vd.toPrettyChars(), type.toChars());
return; return;
} }
@ -724,9 +742,12 @@ public:
if (tdparent && vd.type && !vd.type.deco) if (tdparent && vd.type && !vd.type.deco)
{ {
if (linkage != LINK.c && linkage != LINK.cpp) if (linkage != LINK.c && linkage != LINK.cpp)
{
if (printIgnored)
{ {
buf.printf("// ignoring variable %s because of linkage", vd.toPrettyChars()); buf.printf("// ignoring variable %s because of linkage", vd.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
typeToBuffer(vd.type, vd.ident); typeToBuffer(vd.type, vd.ident);
@ -738,15 +759,21 @@ public:
vd.parent && vd.parent.isModule()) vd.parent && vd.parent.isModule())
{ {
if (vd.linkage != LINK.c && vd.linkage != LINK.cpp) if (vd.linkage != LINK.c && vd.linkage != LINK.cpp)
{
if (printIgnored)
{ {
buf.printf("// ignoring variable %s because of linkage", vd.toPrettyChars()); buf.printf("// ignoring variable %s because of linkage", vd.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
if (vd.storage_class & AST.STC.tls) if (vd.storage_class & AST.STC.tls)
{
if (printIgnored)
{ {
buf.printf("// ignoring variable %s because of thread-local storage", vd.toPrettyChars()); buf.printf("// ignoring variable %s because of thread-local storage", vd.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
if (vd.linkage == LINK.c) if (vd.linkage == LINK.c)
@ -848,9 +875,13 @@ public:
// Ignore. It's taken care of while visiting FuncDeclaration // Ignore. It's taken care of while visiting FuncDeclaration
return; return;
} }
if (printIgnored)
{
buf.printf("// ignored %s %s", ad.aliassym.kind(), ad.aliassym.toPrettyChars()); buf.printf("// ignored %s %s", ad.aliassym.kind(), ad.aliassym.toPrettyChars());
buf.writenl(); buf.writenl();
} }
}
override void visit(AST.Nspace ns) override void visit(AST.Nspace ns)
{ {
@ -928,9 +959,12 @@ public:
visited[cast(void*)sd] = true; visited[cast(void*)sd] = true;
if (linkage != LINK.c && linkage != LINK.cpp) if (linkage != LINK.c && linkage != LINK.cpp)
{
if (printIgnored)
{ {
buf.printf("// ignoring non-cpp struct %s because of linkage", sd.toChars()); buf.printf("// ignoring non-cpp struct %s because of linkage", sd.toChars());
buf.writenl(); buf.writenl();
}
return; return;
} }
@ -1112,6 +1146,7 @@ public:
visited[cast(void*)cd] = true; visited[cast(void*)cd] = true;
if (!cd.isCPPclass()) if (!cd.isCPPclass())
{ {
if (printIgnored)
buf.printf("// ignoring non-cpp class %s\n", cd.toChars()); buf.printf("// ignoring non-cpp class %s\n", cd.toChars());
return; return;
} }
@ -1174,6 +1209,7 @@ public:
//if (linkage != LINK.c && linkage != LINK.cpp) //if (linkage != LINK.c && linkage != LINK.cpp)
//{ //{
//if (printIgnored)
//buf.printf("// ignoring non-cpp enum %s because of linkage\n", ed.toChars()); //buf.printf("// ignoring non-cpp enum %s because of linkage\n", ed.toChars());
//return; //return;
//} //}
@ -1691,9 +1727,12 @@ public:
} }
if (linkage != LINK.c && linkage != LINK.cpp) if (linkage != LINK.c && linkage != LINK.cpp)
{
if (printIgnored)
{ {
buf.printf("// ignoring template %s because of linkage", td.toPrettyChars()); buf.printf("// ignoring template %s because of linkage", td.toPrettyChars());
buf.writenl(); buf.writenl();
}
return; return;
} }

File diff suppressed because it is too large Load diff

View file

@ -110,6 +110,14 @@ enum CppStdRevision : uint
cpp17 = 2017_03 cpp17 = 2017_03
} }
/// Configuration for the C++ header generator
enum CxxHeaderMode : uint
{
none, /// Don't generate headers
silent, /// Generate headers
verbose /// Generate headers and add comments for hidden declarations
}
// Put command line switches in here // Put command line switches in here
extern (C++) struct Param extern (C++) struct Param
{ {
@ -206,6 +214,7 @@ extern (C++) struct Param
bool revertUsage; // print help on -revert switch bool revertUsage; // print help on -revert switch
bool previewUsage; // print help on -preview switch bool previewUsage; // print help on -preview switch
bool externStdUsage; // print help on -extern-std switch bool externStdUsage; // print help on -extern-std switch
bool hcUsage; // print help on -HC switch
bool logo; // print compiler logo bool logo; // print compiler logo
CPU cpu = CPU.baseline; // CPU instruction set to target CPU cpu = CPU.baseline; // CPU instruction set to target
@ -240,7 +249,7 @@ extern (C++) struct Param
const(char)[] hdrname; // write 'header' file to docname const(char)[] hdrname; // write 'header' file to docname
bool hdrStripPlainFunctions = true; // strip the bodies of plain (non-template) functions bool hdrStripPlainFunctions = true; // strip the bodies of plain (non-template) functions
bool doCxxHdrGeneration; // write 'Cxx header' file CxxHeaderMode doCxxHdrGeneration; /// Generate 'Cxx header' file
const(char)[] cxxhdrdir; // write 'header' file to docdir directory const(char)[] cxxhdrdir; // write 'header' file to docdir directory
const(char)[] cxxhdrname; // write 'header' file to docname const(char)[] cxxhdrname; // write 'header' file to docname

View file

@ -89,6 +89,14 @@ enum CppStdRevision
CppStdRevisionCpp17 = 201703 CppStdRevisionCpp17 = 201703
}; };
/// Configuration for the C++ header generator
enum class CxxHeaderMode
{
none, /// Don't generate headers
silent, /// Generate headers
verbose /// Generate headers and add comments for hidden declarations
};
// Put command line switches in here // Put command line switches in here
struct Param struct Param
{ {
@ -172,6 +180,7 @@ struct Param
bool revertUsage; // print help on -revert switch bool revertUsage; // print help on -revert switch
bool previewUsage; // print help on -preview switch bool previewUsage; // print help on -preview switch
bool externStdUsage; // print help on -extern-std switch bool externStdUsage; // print help on -extern-std switch
bool hcUsage; // print help on -HC switch
bool logo; // print logo; bool logo; // print logo;
CPU cpu; // CPU instruction set to target CPU cpu; // CPU instruction set to target
@ -206,7 +215,7 @@ struct Param
DString hdrname; // write 'header' file to docname DString hdrname; // write 'header' file to docname
bool hdrStripPlainFunctions; // strip the bodies of plain (non-template) functions bool hdrStripPlainFunctions; // strip the bodies of plain (non-template) functions
bool doCxxHdrGeneration; // write 'Cxx header' file CxxHeaderMode doCxxHdrGeneration; // write 'Cxx header' file
DString cxxhdrdir; // write 'header' file to docdir directory DString cxxhdrdir; // write 'header' file to docdir directory
DString cxxhdrname; // write 'header' file to docname DString cxxhdrname; // write 'header' file to docname

View file

@ -295,7 +295,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params)
} }
import dmd.cli : CLIUsage; import dmd.cli : CLIUsage;
mixin(generateUsageChecks(["mcpu", "transition", "check", "checkAction", mixin(generateUsageChecks(["mcpu", "transition", "check", "checkAction",
"preview", "revert", "externStd"])); "preview", "revert", "externStd", "hc"]));
if (params.manual) if (params.manual)
{ {
@ -2165,7 +2165,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param
} }
else if (p[1] == 'H' && p[2] == 'C') // https://dlang.org/dmd.html#switch-HC else if (p[1] == 'H' && p[2] == 'C') // https://dlang.org/dmd.html#switch-HC
{ {
params.doCxxHdrGeneration = true; params.doCxxHdrGeneration = CxxHeaderMode.silent;
switch (p[3]) switch (p[3])
{ {
case 'd': // https://dlang.org/dmd.html#switch-HCd case 'd': // https://dlang.org/dmd.html#switch-HCd
@ -2178,6 +2178,24 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param
goto Lnoarg; goto Lnoarg;
params.cxxhdrname = (p + 4 + (p[4] == '=')).toDString; params.cxxhdrname = (p + 4 + (p[4] == '=')).toDString;
break; break;
case '=':
enum len = "-HC=".length;
mixin(checkOptionsMixin("hcUsage", "`-HC=<mode>` requires a valid mode"));
const mode = arg[len .. $];
switch (mode)
{
case "silent":
/* already set above */
break;
case "verbose":
params.doCxxHdrGeneration = CxxHeaderMode.verbose;
break;
default:
errorInvalidSwitch(p);
params.hcUsage = true;
return false;
}
break;
case 0: case 0:
break; break;
default: default:

View file

@ -1,5 +1,5 @@
/* /*
REQUIRED_ARGS: -HC -c -o- REQUIRED_ARGS: -HC=silent -c -o-
PERMUTE_ARGS: PERMUTE_ARGS:
TEST_OUTPUT: TEST_OUTPUT:
--- ---
@ -20,13 +20,10 @@ typedef int32_t T;
extern "C" int32_t x; extern "C" int32_t x;
// ignored variable dtoh_AliasDeclaration.x
extern "C" int32_t foo(int32_t x); extern "C" int32_t foo(int32_t x);
// ignored function dtoh_AliasDeclaration.foo
extern int32_t foo2(int32_t x); extern int32_t foo2(int32_t x);
// ignored function dtoh_AliasDeclaration.foo2
struct S; struct S;
typedef S aliasS; typedef S aliasS;
@ -35,7 +32,6 @@ struct S2;
typedef S2 aliasS2; typedef S2 aliasS2;
// ignoring non-cpp class C
typedef C* aliasC; typedef C* aliasC;
class C2; class C2;

View file

@ -32,7 +32,6 @@ public:
C2(int32_t a); C2(int32_t a);
}; };
// ignoring non-cpp class C3
class Aligned class Aligned
{ {
public: public:

View file

@ -64,7 +64,6 @@ struct A
{ {
int32_t a; int32_t a;
S s; S s;
// ignoring extern () block because of linkage
extern "C" void bar(); extern "C" void bar();
void baz(int32_t x = 42); void baz(int32_t x = 42);
struct struct

View file

@ -16,7 +16,6 @@ struct A
{ {
// Ignoring var x alignment 0 // Ignoring var x alignment 0
T x; T x;
// ignoring function foo because semantic hasn't been run
}; };
struct B struct B

View file

@ -11,8 +11,6 @@ TEST_OUTPUT:
#include <stdint.h> #include <stdint.h>
// ignoring variable dtoh_VarDeclaration.x because of linkage
// ignoring variable dtoh_VarDeclaration.y because of linkage
extern "C" int32_t z; extern "C" int32_t z;
extern int32_t t; extern int32_t t;
@ -21,7 +19,6 @@ struct S;
struct S2; struct S2;
// ignoring non-cpp class C
class C2; class C2;
union U; union U;

View file

@ -98,7 +98,6 @@ END_ENUM(STC, STC, stc)
ENUM_CONSTANT(STC, STC_D, (STC)3) ENUM_CONSTANT(STC, STC_D, (STC)3)
// ignoring non-cpp struct Foo because of linkage
BEGIN_ENUM_TYPE(Foo, MyEnum, MYENUM, myenum) BEGIN_ENUM_TYPE(Foo, MyEnum, MYENUM, myenum)
ENUM_KEY_TYPE(Foo, A, Foo(42), MyEnum, MYENUM, myenum, ME) ENUM_KEY_TYPE(Foo, A, Foo(42), MyEnum, MYENUM, myenum, ME)
ENUM_KEY_TYPE(Foo, B, Foo(84), MyEnum, MYENUM, myenum, ME) ENUM_KEY_TYPE(Foo, B, Foo(84), MyEnum, MYENUM, myenum, ME)
@ -119,12 +118,6 @@ END_ENUM_TYPE(FooCpp, MyEnumCpp, MYENUMCPP, myenumcpp)
ENUM_CONSTANT(MyEnum, testCpp, Foo(42)) ENUM_CONSTANT(MyEnum, testCpp, Foo(42))
// ignoring enum `dtoh_enum.b` because type `int[]` is currently not supported for enum constants.
// ignoring enum `dtoh_enum.c` because type `int[int]` is currently not supported for enum constants.
// ignoring function dtoh_enum.foo because it's extern
// ignoring enum `dtoh_enum.d` because type `extern (C) void function()` is currently not supported for enum constants.
// ignoring variable dtoh_enum.e_b because of linkage
// ignoring enum `dtoh_enum.e` because type `immutable(bool)*` is currently not supported for enum constants.
--- ---
*/ */

View file

@ -11,9 +11,6 @@ TEST_OUTPUT:
#include <stdint.h> #include <stdint.h>
// ignoring function dtoh_functions.foo because of linkage
// ignoring function dtoh_functions.fun because it's extern
// ignoring function dtoh_functions.fun2 because it's extern
extern "C" int32_t bar(int32_t x); extern "C" int32_t bar(int32_t x);
extern "C" int32_t bar2(int32_t x); extern "C" int32_t bar2(int32_t x);

View file

@ -0,0 +1,42 @@
/*
REQUIRED_ARGS: -HC=verbose
TEST_OUTPUT:
---
// Automatically generated by Digital Mars D Compiler v$n$
#pragma once
#include <stddef.h>
#include <stdint.h>
// ignoring function dtoh_verbose.foo because of linkage
// ignoring extern () block because of linkage
// ignoring function dtoh_verbose.bar because of linkage
// ignoring non-cpp struct S because of linkage
// ignoring non-cpp class C
// ignoring function dtoh_verbose.bar because it's extern
// ignoring variable dtoh_verbose.i1 because of linkage
// ignored function dtoh_verbose.templ!int.templ
---
*/
void foo() {}
extern (D) {
int i;
}
void bar();
struct S {}
class C {}
extern(C++) void bar();
int i1;
void templ(T)(T t) {}
alias inst = templ!int;