Skip to content

Expanding results in repeated first argument on Windows #120

Open
@HaydnTrigg

Description

@HaydnTrigg

Describe the bug
Trying to expand the members of a struct that contains 'Cheese', 'Bacon', 'Burger'. Compiling for Linux results in expected output, for Windows however 'Cheese' is repeated 3 times.

Expected behavior in Godbolt https://godbolt.org/z/3fo8zGGbc

Observed behavior

Cheese
Cheese
Cheese

Expected behavior

Cheese
Bacon
Burger

To Reproduce
I am compiling this test program using clang-cl and overriding the system headers to include libcxx before MSVC.

The source code

#include <experimental/meta>
#include <vector>
#include <iostream>

// start 'expand' definition
namespace __impl
{
    template <auto... vals>
    struct replicator_type
    {
        template <typename F>
        constexpr void operator>>(F body) const
        {
            (body.template operator()<vals>(), ...);
        }
    };

    template <auto... vals>
    replicator_type<vals...> replicator = {};
}

template <typename R>
consteval auto expand(R range)
{
    std::vector<std::meta::info> args;
    for (auto r : range)
    {
        args.push_back(std::meta::reflect_value(r));
    }
    return substitute(^^__impl::replicator, args);
}
// end 'expand' definition

struct MyStruct
{
    std::string Cheese;
    std::string Bacon;
    std::string Burger;
};

int main(int argc, const char *argv[])
{
    [:expand(nonstatic_data_members_of(^^MyStruct)):] >> [&]<auto dm>
    {
        using T = typename[:type_of(dm):];
        std::cout << identifier_of(dm) << std::endl;
    };

    return 0;
}

Relevant command line
-std=c++26 -freflection -freflection-new-syntax -freflection-latest

Environment (please complete the following information):

  • Operating System and Version: Windows 11 23H2

Compiled Clang using the following

"C:\Program Files\CMake\bin\cmake.exe" ^
    -G Ninja ^
    -S p2996/llvm ^
    -B build ^
    -DCMAKE_BUILD_TYPE="MinSizeRel" ^
    -DCMAKE_INSTALL_PREFIX="A:\install" ^
    -DLLVM_TARGETS_TO_BUILD="X86" ^
    -DLLVM_ENABLE_PROJECTS="clang" ^
    -DLLVM_ENABLE_RUNTIMES="libcxx;libc" ^
    -DLIBCXX_CXX_ABI="vcruntime" ^
    -DLIBCXX_ENABLE_SHARED=YES ^
    -DLIBCXX_ENABLE_STATIC=NO ^
    -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=YES ^
    -DLIBCXX_ENABLE_EXCEPTIONS=YES
ninja -C build clang runtimes install-clang install-clang-libraries install-clang-headers install-runtimes install-clang-resource-headers

Additional context
I have added some extra logging to substitute that spits out some output just before executing SetAndSucceed and the output from the compile option and program is as follows.

StructuralValue: meta::info ReflectionKind:4 Name:Cheese
StructuralValue: meta::info ReflectionKind:4 Name:Bacon
StructuralValue: meta::info ReflectionKind:4 Name:Burger
StructuralValue: meta::info ReflectionKind:4 Name:Cheese
StructuralValue: meta::info ReflectionKind:4 Name:Bacon
StructuralValue: meta::info ReflectionKind:4 Name:Burger
Cheese
Cheese
Cheese
// just before SetAndSucceed add P(TArgs);
auto P = [](SmallVector<TemplateArgument, 4>& TArgs) {
  for(auto TArg : TArgs)
  {
    if (TArg.getKind() == TemplateArgument::StructuralValue) {
        const QualType T = TArg.getStructuralValueType();
        const APValue & RV = TArg.getAsStructuralValue();

        std::string Name;
        if (auto *ND = dyn_cast<NamedDecl>(RV.getReflectedDecl())) {
          if (auto *II = ND->getIdentifier())
            Name = II->getName();
          else if (auto *II = ND->getDeclName().getCXXLiteralIdentifier())
            Name = II->getName();
        }

        llvm::outs() << "StructuralValue: " << T.getAsString() << " ReflectionKind:" << (int)RV.getReflectionKind() << " Name:" << Name << "\n";
    } else {
        llvm::outs() << "Non-type template argument. " << TArg.getKind() << "\n";
    }
  }
};

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