Skip to content

UB if mp is used from multiple TUs #73

@jlebar

Description

@jlebar

Thanks for putting this library out there. I think it's very cool!

Unfortunately I think there are major UB sharp edges if you use it from multiple translation units. Not sure if you're aware, but since you didn't mention it in the docs I thought maybe you're not.

The root issue is that the value returned by mp::meta<T> is not stable across TUs, because the ID you get depends on the instantiation order.

That in and of itself doesn't necessarily sound like a dealbreaker, just don't pass mp::info across TUs.

But I think it's worse than that. If you ever use mp::meta<T> inside a function that itself is used in two TUs, you get an ODR violation, because that function essentially has two different definitions in the two TUs.

For example:

// foo.h
[[attribute::noinline]] template <typename T> mp::info get_info() { return mp::meta<T>; }
// foo.cc
#include "foo.h"
assert(get_info<int>() == mp::meta<int>);
assert(get_info<float>() == mp::meta<float>);

// bar.cc
#include "foo.h"
assert(get_info<float>() == mp::meta<float>);
assert(get_info<int>() == mp::meta<int>);

In this reproducer, I expect the assertions in foo.cc or in bar.cc to fail (although I didn't actually test it :).

I expect this is a problem in practice only if the function that uses mp::meta<T> itself is not inlined.

Here's a chatgpt conversation that I used to check my work in case it helps, although I expect you're better at C++ than me and don't need it. https://chatgpt.com/share/6941b79f-e1a0-8008-b7f3-d41cc5539d24

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions