News for hackers. Stuff that matters.
Re:C23: A Slightly Better C by bheadmaster on Sunday January 21, 2024 @03:31PM (#39082727)
It's actually a struct that only has a name in the scope of the function which returns `auto`, and thus cannot be named outside of it. Like this:

    #include <iostream>

    auto createVoldemortType(int value) {
        struct Voldemort {
            int value;
        };
        return Voldemort{value};
    }

    int main() {
        auto voldemort = createVoldemortType(7);
        std::cout << voldemort.value << std::endl; // output: 7
    }
Re:C23: A Slightly Better C by krater23 on Sunday January 21, 2024 @04:26PM (#39083245)
This way to code is a good reason to make auto the same tabu as goto.
Re:C23: A Slightly Better C by trealira on Sunday January 21, 2024 @05:08PM (#39083592)
I wonder how much this complicates parsing C++. Because of this, you can't discard/free struct and class definitions as soon as you leave the scope, like you can in C, because the definition can still escape the scope by being returned from a function with the "auto" keyword.
Re:C23: A Slightly Better C by humanrebar on Sunday January 21, 2024 @05:53PM (#39083915)
The entities and their destructors still have names that the compiler and linker understand. Programs just can't name them.
Re:C23: A Slightly Better C by trealira on Sunday January 21, 2024 @06:11PM (#39084041)
I mean that it would complicate just the parser.

For many compilers, as soon as the parser sees a left curly brace, it pushes a symbol table onto a stack, and when it sees the corresponding right curly brace, it pops the symbol table off the stack, and "forgets" any declarations that were made inside that scope. That is so things like this work as expected.

  {
      int x = 0;
      {
          int x = 1;
          printf("%d\n", x); // prints 1
      }
      printf("%d\n", x); // prints 0
  }
But, in C++, using the auto keyword, declarations can escape their scope with auto. I'll change the C++ code that OP wrote. The C++ compiler has to correctly resolve cases like this, which means it can't just forget all the declarations within the scope of the function after the definition is done.

    #include <iostream>

    auto createVoldemortType(int value) {
        struct Voldemort {
            int value;
        };
        return Voldemort{value};
    }

    struct Voldemort {
        std::string value;
    };

    int main() {
        auto voldemort = createVoldemortType(7);
        std::cout << voldemort.value << std::endl; // output: 7
    }
Re:C23: A Slightly Better C by danhau on Monday January 22, 2024 @08:10AM (#39089104)
During semantic analysis a parser usually attaches symbol info (of some kind) to the already existing abstract syntax tree, or creates a new tree entirely. Whenever it needs to know about a type, it just walks the tree to the node with the type definition. That way there’s really never any data that‘s forgotten.

At least that’s how I think the parsers work I‘m familiar with.

Re:C23: A Slightly Better C by trealira on Monday January 22, 2024 @01:14PM (#39093044)
Yeah, it depends on the compiler.

I've read a book about a BLISS compiler [1] that does this, but still uses a stack like I described [2]. It implements a hash table that used linked list nodes for collision. A new declaration adds a new name to the table, and it attaches the node to uses of the name in expressions of the syntax tree.

When a scope is exited, the declarations from that scope are removed from the symbol table, but because they're still attached to the syntax tree, they can't just be freed. They're added to a linked list of "purged" nodes, so that the information they contain can be used later during code generation, and then freed.

One-pass compilers don't have this problem; they really can just free the memory for reuse, because after they exit a scope, they've already generated the assembly or machine code from the high-level language.

However, I don't know what LLVM or GCC, or any other remotely modern compiler, does. I haven't read the code much.

[1]: https://en.wikipedia.org/wiki/The_Design_of_an_Optimizing_Co...

[2]: Actually, it intertwines the stack and the symbol table in a complicated way, so there's only one hash table, and multiple stacks within it. It's explained by a diagram they include on page 13. You can find a PDF of it here: https://kilthub.cmu.edu/articles/journal_contribution/The_de...

Re:C23: A Slightly Better C by fuzztester on Sunday January 21, 2024 @06:16PM (#39084069)
How does the argument 7 get passed to the value field in the Voldemort struct?

I don't see any code ther that does that. Is it implicitly passed?

I don't know C++, though I did know C somewhat well earlier.

Re:C23: A Slightly Better C by fuzztester on Sunday January 21, 2024 @06:19PM (#39084085)
Oops, I missed the line:

return Voldemort{value};

I guess that does it.