Skip to content

Commit

Permalink
Make _grpc.h types C++20 compatible
Browse files Browse the repository at this point in the history
As of C++20, it is malformed to have an unnamed class used in typedef with a
base class. In the generated reflection code for a service, we were using the
following construct to create a reflectable entry for each field in a
struct.

```
struct service {
    typedef struct /* no name */ : ::bond::reflection::MethodTemplate<...> {} method_name;
}
```

Now, instead of using an unnamed class, we generate a named class and refer
to that:

```
struct service {
    typedef struct method_name_type : ::bond::reflection::MethodTemplate<...> {} field_name;
}
```

This commit is very similar in spirit to f1cb707. See that commit for
even more details about what's going on.

Also adds a test that compiles a service that has method names that
conflict with the names in `MethodTemplate`. The gRPC++ unit test CMake
now has a single library with the compiled generated code.

Fixes #1027
  • Loading branch information
chwarr authored May 18, 2020
1 parent d7557f2 commit 3454728
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 62 deletions.
15 changes: 13 additions & 2 deletions compiler/src/Language/Bond/Codegen/Cpp/Grpc_h.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ grpc_h export_attribute cpp file imports declarations = ("_grpc.h", [lt|

public: struct service
{
#{newlineSep 3 methodTemplate serviceMethods}
#{newlineSep 3 (uncurry methodTemplate) (zip serviceMethods uniqueMethodTemplateStructNames)}
};

private: typedef boost::mpl::list<> methods0;
Expand Down Expand Up @@ -167,7 +167,18 @@ grpc_h export_attribute cpp file imports declarations = ("_grpc.h", [lt|
where
static m = [lt|(void)#{methodMetadataVar m};|]

methodTemplate m = [lt|typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<#{declName}, #{payload $ methodTypeToMaybe (methodInput m)}, #{resultType m}, &#{methodMetadataVar m}> {} #{methodName m};|]
-- unique names for each of the MethodTemplate derived structs that
-- we need to generate in the same order as serviceMethods.
uniqueMethodTemplateStructNames :: [String]
uniqueMethodTemplateStructNames = uniqueNames (map (\n -> n ++ "_type") methodNames) reservedNames
where
methodNames = map methodName serviceMethods
reservedNames = methodTemplateReservedNames ++ methodNames
-- methodTemplateReservedNames are names used in ::bond::reflection::MethodTemplate<>
methodTemplateReservedNames = ["MethodTemplate", "service_type", "input_type", "result_type", "metadata", "method"]

methodTemplate :: Method -> String -> L.Text
methodTemplate m methodTemplateStructName = [lt|typedef struct #{methodTemplateStructName} : ::bond::ext::grpc::reflection::MethodTemplate<#{declName}, #{payload $ methodTypeToMaybe (methodInput m)}, #{resultType m}, &#{methodMetadataVar m}> {} #{methodName m};|]

proxyName = "Client" :: String
serviceName = "Service" :: String
Expand Down
10 changes: 5 additions & 5 deletions compiler/tests/generated/generic_service_grpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ template <typename Payload>

public: struct service
{
typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<Foo, Payload, void, &s_foo31_metadata> {} foo31;
typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<Foo, void, Payload, &s_foo32_metadata> {} foo32;
typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<Foo, Payload, Payload, &s_foo33_metadata> {} foo33;
typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<Foo, ::tests::SomeBox<int32_t>, void, &s_ConsumesGeneric1_metadata> {} ConsumesGeneric1;
typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<Foo, ::tests::SomeBox<std::vector<int32_t> >, void, &s_ConsumesGeneric2_metadata> {} ConsumesGeneric2;
typedef struct foo31_type : ::bond::ext::grpc::reflection::MethodTemplate<Foo, Payload, void, &s_foo31_metadata> {} foo31;
typedef struct foo32_type : ::bond::ext::grpc::reflection::MethodTemplate<Foo, void, Payload, &s_foo32_metadata> {} foo32;
typedef struct foo33_type : ::bond::ext::grpc::reflection::MethodTemplate<Foo, Payload, Payload, &s_foo33_metadata> {} foo33;
typedef struct ConsumesGeneric1_type : ::bond::ext::grpc::reflection::MethodTemplate<Foo, ::tests::SomeBox<int32_t>, void, &s_ConsumesGeneric1_metadata> {} ConsumesGeneric1;
typedef struct ConsumesGeneric2_type : ::bond::ext::grpc::reflection::MethodTemplate<Foo, ::tests::SomeBox<std::vector<int32_t> >, void, &s_ConsumesGeneric2_metadata> {} ConsumesGeneric2;
};

private: typedef boost::mpl::list<> methods0;
Expand Down
2 changes: 1 addition & 1 deletion compiler/tests/generated/service_attributes_grpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct Foo final

public: struct service
{
typedef struct : ::bond::ext::grpc::reflection::MethodTemplate<Foo, ::tests::Param, ::tests::Result, &s_foo_metadata> {} foo;
typedef struct foo_type : ::bond::ext::grpc::reflection::MethodTemplate<Foo, ::tests::Param, ::tests::Result, &s_foo_metadata> {} foo;
};

private: typedef boost::mpl::list<> methods0;
Expand Down
21 changes: 21 additions & 0 deletions compiler/tests/generated/service_grpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,27 @@ namespace tests

const ::bond::Metadata Foo::Schema::s_cq_metadata
= ::bond::reflection::MetadataInit("cq");

const ::bond::Metadata Foo::Schema::s_foo11_type_metadata
= ::bond::reflection::MetadataInit("foo11_type");

const ::bond::Metadata Foo::Schema::s_MethodTemplate_metadata
= ::bond::reflection::MetadataInit("MethodTemplate");

const ::bond::Metadata Foo::Schema::s_service_type_metadata
= ::bond::reflection::MetadataInit("service_type");

const ::bond::Metadata Foo::Schema::s_input_type_metadata
= ::bond::reflection::MetadataInit("input_type");

const ::bond::Metadata Foo::Schema::s_result_type_metadata
= ::bond::reflection::MetadataInit("result_type");

const ::bond::Metadata Foo::Schema::s_metadata_metadata
= ::bond::reflection::MetadataInit("metadata");

const ::bond::Metadata Foo::Schema::s_method_metadata
= ::bond::reflection::MetadataInit("method");


} // namespace tests
140 changes: 140 additions & 0 deletions compiler/tests/generated/service_grpc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,55 @@ public static class Foo
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<BasicTypes>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_foo11_type = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"foo11_type",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_MethodTemplate = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"MethodTemplate",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_service_type = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"service_type",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_input_type = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"input_type",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_result_type = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"result_type",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_metadata = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"metadata",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>> Method_method = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<global::Bond.Void>, global::Bond.Grpc.IMessage<global::Bond.Void>>(
global::Grpc.Core.MethodType.Unary,
ServiceName,
"method",
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance,
global::Bond.Grpc.Marshaller<global::Bond.Void>.Instance);

public abstract class FooBase
{
public abstract global::System.Threading.Tasks.Task foo11(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);
Expand Down Expand Up @@ -228,6 +277,20 @@ public abstract class FooBase
public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<dummy>> foo44(global::Bond.Grpc.IMessage<dummy> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<BasicTypes>> cq(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> foo11_type(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> MethodTemplate(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> service_type(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> input_type(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> result_type(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> metadata(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);

public abstract global::System.Threading.Tasks.Task<global::Bond.Grpc.IMessage<global::Bond.Void>> method(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.ServerCallContext context);
}

public class FooClient : global::Grpc.Core.ClientBase<FooClient>
Expand Down Expand Up @@ -448,6 +511,76 @@ public virtual void foo15Async(global::Bond.Grpc.IMessage<global::tests2.OtherBa
return CallInvoker.AsyncUnaryCall(Method_cq, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> foo11_typeAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return foo11_typeAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> foo11_typeAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_foo11_type, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> MethodTemplateAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return MethodTemplateAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> MethodTemplateAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_MethodTemplate, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> service_typeAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return service_typeAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> service_typeAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_service_type, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> input_typeAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return input_typeAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> input_typeAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_input_type, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> result_typeAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return result_typeAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> result_typeAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_result_type, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> metadataAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return metadataAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> metadataAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_metadata, null, options, request);
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> methodAsync(global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return methodAsync(global::Bond.Grpc.Message.Void, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
}

public virtual global::Grpc.Core.AsyncUnaryCall<global::Bond.Grpc.IMessage<global::Bond.Void>> methodAsync(global::Bond.Grpc.IMessage<global::Bond.Void> request, global::Grpc.Core.CallOptions options)
{
return CallInvoker.AsyncUnaryCall(Method_method, null, options, request);
}

protected override FooClient NewInstance(global::Grpc.Core.ClientBase.ClientBaseConfiguration configuration)
{
return new FooClient(configuration);
Expand Down Expand Up @@ -477,6 +610,13 @@ protected override FooClient NewInstance(global::Grpc.Core.ClientBase.ClientBase
.AddMethod(Method_foo43, serviceImpl.foo43)
.AddMethod(Method_foo44, serviceImpl.foo44)
.AddMethod(Method_cq, serviceImpl.cq)
.AddMethod(Method_foo11_type, serviceImpl.foo11_type)
.AddMethod(Method_MethodTemplate, serviceImpl.MethodTemplate)
.AddMethod(Method_service_type, serviceImpl.service_type)
.AddMethod(Method_input_type, serviceImpl.input_type)
.AddMethod(Method_result_type, serviceImpl.result_type)
.AddMethod(Method_metadata, serviceImpl.metadata)
.AddMethod(Method_method, serviceImpl.method)
.Build();
}
}
Expand Down
Loading

0 comments on commit 3454728

Please sign in to comment.