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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions