Giter VIP home page Giter VIP logo

Comments (5)

rjmccall avatar rjmccall commented on June 21, 2024

Is there a reason to treat them differently from an unscoped enum? Are there compilers that do anything different?

from cxx-abi.

zygoloid avatar zygoloid commented on June 21, 2024

Unscoped enums are passed as their promoted type, and can be retrieved thusly with va_arg. Scoped enums don't promote, so we would need to decide how to pass them (as the underlying type, or as the promoted underlying type?) and what types can validly be used with va_arg to retrieve them (the original enum type, its underlying type, and/or its promoted underlying type).

Does anyone still use have a macro implementation of va_arg that can't easily carry custom logic to deal with this case?

from cxx-abi.

rjmccall avatar rjmccall commented on June 21, 2024

You're right that you'd have to pass the scoped enum type to va_arg to read the argument, but as far as I can tell that's always been valid. And a macro implementation of va_arg would presumably just read the value out of the va_list as a scoped_enum * and then bump up to the next slot, exactly like it would any other type.

I guess what I'm saying is that I'm surprised that people think that this hasn't been supported behavior for the last 10+ years. Was there a bug report or something?

from cxx-abi.

zygoloid avatar zygoloid commented on June 21, 2024

Well, consider enum class X : char {};. Presumably that would be passed as an int, because the psABI doesn't specify how to pass anything smaller. But now consider a simple va_arg macro:

#define va_arg(list, type) (*(type*)(list -= sizeof(type)))

That macro fails for X, because it will bump list an insufficient distance. GCC and Clang both support this anyway, but GCC at least does not support the corresponding case where you use char instead of X (Clang allows even that and makes it work).

If on the other hand we had enum X : char {}; instead of enum class X : char {}; then the rules are clear that X is promoted to int when passed through ..., and va_arg(list, X) has undefined behavior.

So we have at least a choice between treating scoped and unscoped enums the same (and requiring the promoted underlying type to be used in the va_arg), or treating them differently (and allowing -- and perhaps expecting -- the original type to be used in the va_arg for the scoped case). And the latter is the status quo in GCC and Clang.

from cxx-abi.

rjmccall avatar rjmccall commented on June 21, 2024

Well, psABIs definitely specify how to pass e.g. a one-byte struct, and if that struct is trivially copyable it's allowed with varargs, so it's not strictly true that psABIs don't specify how to pass anything smaller, even if it's not obvious that that would be the right rule to use for scoped enums.

That definition of va_arg doesn't work for similar reasons. It also doesn't correctly handle the partitioning of the argument area into aligned slots in general, although for a target with sizeof(int) == sizeof(void*) it might incidentally work out for at least standard types. It also walks the argument area in the wrong direction from the normal convention, although that's a fixable mistake. (It's actually quite awkward to fix: I think you'd have to do something awful like * (const T *) (*(const char (**)[(sizeof(T) + slot_size - 1) / slot_size * slot_size]) list)++)), and even that relies on types never being overaligned for a slot, and of course it has strict-aliasing problems.)

Anyway, I agree that we need to specify some sort of default rule for psABIs that are written purely in terms of C/Fortran/whatever. Note that that means specifying a rule for these types in general, not just a rule for variadic arguments. Since we have to lower them to concepts known to be handled by the psABI, I think we have two options: handle them as the underlying type or handle them as a struct containing a single field of the underlying type. The former seems like the more obvious choice.

I would suggest:

Let E be a scoped enumeration type with underlying type U. Unless the psABI provides specific rules for E, they are as follows:

  • An object of type E has the same representation and characteristics as an object of type U.
  • An argument of type E is passed as if it were converted to type U and as if the corresponding parameter (if any) was of type U.
  • A return value of type E is returned as if it were converted to type U and returned from a function with return type U.

If an argument of type U would be subject to the default argument promotions, the implementation must perform the appropriate promotion to an argument of type E even though the promotions do not formally apply. Note that programs are required to pass E to va_arg, not U, which may cause trouble for simple definitions of va_arg.

I don't think we've actually specified this lowering as this level of detail for any of the existing C++-specific types. For example, we give layout rules for member pointers, but not CC rules; and I'm not sure we ever specify that references have the same representation as pointers.

from cxx-abi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.