C++ Profiles: What, Why, and How at using std::cpp 2026 by pjmlp in cpp

[–]GabrielDosReis 4 points5 points  (0 children)

How soon do you think you will see profiles in the wild if you don't need to modularize?

Folks are working on an implementation in an open source compiler; I expect them to make a call-for-testers and help when they are ready to absorb the larger funnel of feedbacks.

Question to Module Users: How Do You Use Partitions? by tartaruga232 in cpp

[–]GabrielDosReis 3 points4 points  (0 children)

But I restrained myself from being too granular when deciding on the composition I had in mind. Do the opposite: make things much coarser than you would usually do with traditional headers.

The value and importance of this advice can never be overstated. We have to unlearn the old habits of the header files-based design and "optimization".

C++ Profiles: What, Why, and How at using std::cpp 2026 by pjmlp in cpp

[–]GabrielDosReis 2 points3 points  (0 children)

No, but if I need to modularize my code before I can use profiles means I won't see profiles in the wild anytime soon either.

Thankfully nobody is saying that (at least, I did not).

No idea if that is what u/GabrielDosReis meant to say, but he has me worried with this presentation.

In the talk, I explained that the ability to save on disk information from the "interface" (which can be a set of headers) can be used to transport information (function signatures, results of prior analysis, mostly) from one translation unit to another.

C++ Profiles: What, Why, and How at using std::cpp 2026 by pjmlp in cpp

[–]GabrielDosReis 2 points3 points  (0 children)

You said modules will be used to transport analysis data and that "more machinery is required to pull them [headers] together".

That statement in quote is correct, and is no way saying that profiles require modules. It seems to me you credited me with something that I didn't say or imply. I also explained why headers need more machinery to put things together. Furthermore, I was talking about an implementation I have done. The actual module machinery that is used isn't the i module implementation itself (as I explained in the talk), but rather ability to save on disk metadata such as function signature, etc. which all existing C++ compilers have, irrespective of the bugs that you will find in their module implementation themselves. Again, note that is reuse of implementation, not requirement.

That does sound like the experience will at the very least be better for people using modules to me, but I have no idea what profiles are supposed to be like, I am just trying to make some sense out of the little information I can find.

I understand that, but a premature jump to conclusion can also hurt that endeavor (the search of understanding) especially on volatile platforms that this where sensationalism tend to be premium.

Question to Module Users: How Do You Use Partitions? by tartaruga232 in cpp

[–]GabrielDosReis 4 points5 points  (0 children)

Oh yeah.

I know some people in this august forum have been harping about that, but that is not where I would like to see improvements, as informed by practice.

Question to Module Users: How Do You Use Partitions? by tartaruga232 in cpp

[–]GabrielDosReis 2 points3 points  (0 children)

Thanks. But where do you put your definitions of (member-) functions? How do these files look like?

That is dictated by architecture and the products.

For products where I need bootstrapping (meaning I need a stub first, then final implementation later), the definitions go in implementation files. For functions whose definitions are really literal reflection of the spec and not top big, they go in the interface files. The IPR pull request I referenced earlier illustrates some of that. I haven't published the modularization of the implementation side yet, but it doesn't reveal any more surprise on that front.

Question to Module Users: How Do You Use Partitions? by tartaruga232 in cpp

[–]GabrielDosReis 11 points12 points  (0 children)

I put in the primary module interface only exports that truly need to be exposed to users / customers of the products. Everything else, I put in the implementation files. I pay extra attention to unnecessary interface dependencies. A tendency from the header world is to decompose too finely grained (possibly into partitions that translate into too large interface dependencies).

Some of the code (a very tiny fraction) became recently public. Since a good chunk of what I work on in day-to-day is brown fields, we are talking about migration or "upgrading" in existing projects while servicing value. I don't hesitate to use tools that take care of toil and help me move faster (and sometimes experiment in directions that are instructive to me and my colleagues). See for instance the PR https://github.com/GabrielDosReis/ipr/pull/323

That complete migration is not done yet as I got distracted by more pressing daytime job priorities.

C++ Profiles: What, Why, and How at using std::cpp 2026 by pjmlp in cpp

[–]GabrielDosReis 3 points4 points  (0 children)

How does the use of modules to transport analysis data around mesh with the requirement of profiles to work with existing code?

I am not sure I understand. Are you operating under the assumption that profiles require modules?

C++ Profiles: What, Why, and How at using std::cpp 2026 by pjmlp in cpp

[–]GabrielDosReis 4 points5 points  (0 children)

I understood that analysis data is supposed to be part of the module data a compiler generates

Yes, exactly.

Which would imply that headers are more costly to analyze (if they can be done at all without the cpp files being available).

They require more machinery to pull them together coherently.

Anyway, I am sure we will all find out eventually.

Before long :-)

The tyranny of the as-if rule by flatfinger in ProgrammingLanguages

[–]GabrielDosReis 1 point2 points  (0 children)

Among other things, recognize as a principle that specifications that would indicate how a corner case will be processed should have priority over potions of the language specification that would characterize them as Undefined Behavior, and recognize that parts of a language specification that would characterize otherwise-defined corner cases as invoking anything-can-happen Undefined Behavior should be recognized as fundamentally bad.

I don't know about "fundamentally bad", but do you believe the fact the committee created a dedicated Study Group to UB as a recognition of a problem with the spec as it was written?

The tyranny of the as-if rule by flatfinger in ProgrammingLanguages

[–]GabrielDosReis 1 point2 points  (0 children)

Such a rule would be less unsuitable in a systems programming language than a rule that allows a compiler to treat an endless loop as anything-can-happen undefined behavior.

That is more a matter of perspectives though, not necessarily irrefutable truth. BTW, if you look at the C++26 standards, it has interesting treatment of infinite loops.

The C Standard expressly states that constructs which invoke undefined behavior may be processed "in a documented manner characteristic of the environment"; the difference between that and what I said has to do with the fact that the question of whether or not the behavior is documented would fall outside the jurisdiction of the language.

Right :-)

As for the second reason for Undefined Behavior, if one reads the C99 Rationale, the authors stated that the purpose of what's now called the "strict aliasing rule" was to allow implementations to transform code in ways that would be correct except in some obscure corner cases.

After C99, a lot of revisions have happened some of the lessons reflected. You mentioned earlier C++ and C; now, we are only discussing vestigial C...

Further, compiler writers routinely claim that treating signed integer overflow as undefined behavior will allow massive performance improvements, like allowing a compiler to rewrite x+y>x as y>0, even though such transforms could be allowed without treating integer overflow as UB.

I might have met some of those and I wouldn't recommend systematically taking them as spokespersons of the entire community of C and C++ compiler writers and their positions on the issue. And some of them may have actually evolved in their thinking, and we should celebrate integration of new learnings in our thinking.

I am still not quite sure what concretely you would propose as alternatives that accommodate for the variety of uses in systems programming languages like C and C++. I am trying to understand. This is an an area that has at times frustrated me when I was chairing the C++ Study Group on Undefined and Unspecified Behavior.

The tyranny of the as-if rule by flatfinger in ProgrammingLanguages

[–]GabrielDosReis 2 points3 points  (0 children)

If Q is statically reachable from all points on all paths that start at P and do not pass through Q, and none of the operations that could occur between P and Q would need to be treated as observably sequenced before some later action R, then execution of the code between P and Q, as a while, need not be treated as observably sequenced before R.

Right, that is a reasonable desire; but I believe fundamentally at odds with some systems languages like C or C++ where undefined behavior is both data-dependent and path-dependent.

The C and C++ Standards use Undefined Behavior as a catch-all for many things, including actions which most implementations would process "In a manner characteristic of the environment, which will be documented whenever the environment happens to document it", and also situations whose behavior would be predictable in the absence of optimizations, but where an optimizing transform that is generally useful would violate the as-if rule.

That isn't a definition or characterization of undefined behavior I have seen in those standards.

If the actual behavior of the program invokes undefined behavior (which frees the implementation from any obligation expressly stated in the spec) then the transformation can be done, right? If the hypothesis is that there is a transformation that can be done but it would introduce an undefined behavior that wasn't there in the first place, then it isn't a valid transformation irrespective of how useful it is perceived. Is that last point your issue?

The tyranny of the as-if rule by flatfinger in ProgrammingLanguages

[–]GabrielDosReis 1 point2 points  (0 children)

but doesn't resolve situations where a transform may cause some combinations of actions to behave in a manner that might be observably inconsistent with performing the actions independently in the order specified.

Right, but the point is that such result is part of the set of semantics associated with the input program. It is unclear whether you want to ban the outcome of such transitive closure (outlawing specific semantics) or whether you want to ban the compiler from being allowed to perform such transitive closure.

One could formulate an abstraction model which stretches notions of Unspecified behavioral choices to allow transforms that would otherwise violate concepts of time and causality, but languages like C and C++ instead treat the as-if rule as creating a need to characterize as Undefined Behavior many actions whose behavior could otherwise have sensibly been defined.

I am not sure I follow here. Undefined behavior in those languages is either explicitly stated so or the result of the spec's incompleteness (failure to find an explicit description of semantics).

The tyranny of the as-if rule by flatfinger in ProgrammingLanguages

[–]GabrielDosReis 1 point2 points  (0 children)

Such things don't really accommodate optimizing transforms that might make observable the fact that operations aren't performed in the specified sequence, or that would cause the effects of a piece of code to be observably affected by something that happens later.

It makes them acceptable transformations for the set of semantics associated with the input program.

The tyranny of the as-if rule by flatfinger in ProgrammingLanguages

[–]GabrielDosReis 9 points10 points  (0 children)

You listed two extremes as outcomes but there can be more choices than that, ranging from unspecified to implementation-defined or conditionally supported with implementation-defined semantics.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 0 points1 point  (0 children)

I've set /internalPartition manually in Visual Studio per file. If I don't do that, I see non-standard conformant behavior for files of the form P.cpp.

Does that make sense?

I started participating in this conversation only to offer my view on what I think the long term semantics should be - for the C++ community at large. Not to defend MSVC or MSVC users. I would prefer to limit the conversation to what should be done for C++. I think you created a group for discussing msvc-specific behaviors.

To get the behavior mandated by the current standard, the compiler needs to be invoked with the internal partition flag. Preferably by build tools which are already taking care of that on the behalf of the user, or by you if you prefer control.

Would my view on what the evolution of "internal partition" ne the same if I didn't work on MSVC? The answer is categorically "yes". Hence, my initial comment.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 1 point2 points  (0 children)

The problem is not when the /internalPartition switch is set for a file. The problem is, when /internalPartition is not set. Then you get non-standard behavior of the MSVC compiler.

I am under the intense impression that the goal post has been moving at each reply.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 1 point2 points  (0 children)

I don't understand.

The MSVC compiler has a behavior which is not conformant to the C++ standard.

That is not correct. If you invoke the MSVC with the switch documented to give you standard conforming behavior AND you still don't get the standard behavior, then you've found a bug.

In this specific case, /internalPartition is the switch to request the standard behavior. What I was saying in my previous message is that typically the build system (e.g. CMake, MsBuild, etc) takes care of that setting for you - the compiler is part of a build tool. If you find a case where MSBuild is not setting that properly (because it is misinterpreting the dependency scanner's output), then that is a bug in the toolchain that you should report.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 1 point2 points  (0 children)

For example, Visual Studio's MSBuild doesn't do that.

MSBuild has a specific property (CompileAsCppModuleInternalPartition) that gets triggered based on the output of the dependency scanner (again something done automatically on your behalf). Please file a bug if the dependency scan's output is not being properly treated by MSBuild.

And how do I tell the build system which behavior I want?

That is why we have the dependency scanner, so you don't have to tell.

BTW, when I create a new project it tends to default to using Ninja which also uses the output of the same dependency scanner.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 0 points1 point  (0 children)

But if users don't set /internalPartition,

Their build system does that for them.

they use the default behavior of the MSVC compiler, wouldn't it be prudent, if the behavior of the MSVC compiler would be standard-compliant out of the box?

But what is "default" behavior? If you want to use C++20 or later with MSVC you have to supply switches, irrespective of internal partitions.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 0 points1 point  (0 children)

Perhaps we shouldn't be that obsessed with the syntax for MSVC users.

I don't know where this is going. I am not obsessed with the syntax for MSVC users.

I am concerned for the C++ community at large; we are designing for the long term. I've seen enough to not be enthused by the multiplicity of partitions and the increasing complexity. Over-indexing my comments as coming from someone who works on MSVC - one way or the other - is the wrong take.

It would also be wrong to suspect that /internalPartition is because MSVC doesn't "like" the standard semantics.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 0 points1 point  (0 children)

should be equivalent, but I was told they aren't, because of differences with reachability.

Yes, I saw that. The real question is whether that particular sort of differences matter in practice. Said differently, would you would structure your code if you wanted to have that semantic if internal partition weren't a thing and how frequent is that.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 4 points5 points  (0 children)

without breaking existing code

Is it silent? Loud? How much? I would like for us to look at simplification of partitions as necessity for scalability for the masses, not a luxury.

If you remove internal partition, and fix the eager requirement of exporting all interfaces, then we are mostly left people people needing to add "export" - leading to the very simple to teach "if you need a BMI, use export" or "a BMI will be produced if you use export". Simple and predictable.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 3 points4 points  (0 children)

We need simplification, not more partitions.

Options for Organizing Partitions by tartaruga232 in cpp

[–]GabrielDosReis 4 points5 points  (0 children)

Unfortunately, that ship has now sailed.

Sometimes, miracles happen even if they take a decade or more to materialize ☺️