HLSL does not support pointers or references. This change generates errors in sema for generating pointer, and reference types as well as common operators (address-of, dereference, arrow), which are used with pointers and are unsupported in HLSL.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
I think you're going to need semantic restrictions as well as parsing restrictions because of type deduction. Even if you don't support templates (yet), there's still auto, decltype, __typeof__, and __auto_type (I probably missed some, lol) to worry about.
Also... can HLSL be combined with Objective-C mode (do we have to worry about their pointers as well)?
clang/test/ParserHLSL/parse_pointer.hlsl | ||
---|---|---|
10 ↗ | (On Diff #420670) | |
12 ↗ | (On Diff #420670) | I am proud of you for this test case, because I was going to ask for it. :-D |
23 ↗ | (On Diff #420670) | Here are a few more fun test cases (which may require semantic tests instead of parsing tests): void func(); void devilish_language(auto look_ma_no_pointers); // templates get you the same effects as well void test() { int x; devilish_language(&x); // I presume we want this to be diagnosed devilish_language(func); // I think you wanted this to not be diagnosed? devilish_language("oh no, not array decay!"); // Same here as function decay? auto but_but_but = "please, stop Aaron!" + 0; // Uhhh... is the addition okay but the declaration bad? int array[2]; *(&array[0] + 1) = 12; // Maaaayybbbe this is fine? } (Thing for you to double-check: do any targets predefine macros that expand to a pointer? I checked InitPreprocessor.cpp and things looked fine there, but I didn't check targets.) |
clang/test/ParserHLSL/parse_reference.hlsl | ||
4 ↗ | (On Diff #420670) | |
18 ↗ | (On Diff #420670) | Similar extra tests involving type deduction as the pointer tests. |
Thankfully HLSL is like C++98-based... I don't think we support any of those cases.
Also... can HLSL be combined with Objective-C mode (do we have to worry about their pointers as well)?
Oh god... Now you're giving me nightmares. I feel like implementing objc_msgsend on a GPU might be a bridge (or ten) too far...
clang/test/ParserHLSL/parse_pointer.hlsl | ||
---|---|---|
23 ↗ | (On Diff #420670) | I am in awe of your gift for finding ways to trip things up :) I think most of these we can't hit because of auto. Eyeballing that lat case we _might_ handle it. I'll double check. |
Oh, were compilers that easy... https://godbolt.org/z/EMasKrdh3
Also... can HLSL be combined with Objective-C mode (do we have to worry about their pointers as well)?
Oh god... Now you're giving me nightmares. I feel like implementing objc_msgsend on a GPU might be a bridge (or ten) too far...
Heh, good. Can you make sure we reject that situation loudly in the frontend (in another patch, on another day, no rush)?
clang/test/ParserHLSL/parse_pointer.hlsl | ||
---|---|---|
23 ↗ | (On Diff #420670) | I am broken for writing decent code after spending so many years in Core thinking about edge cases. :-D Btw, here's another one to try: int i = *(int *)0; // Check that pointer types used in expressions are caught, same for reference |
Yes absolutely. I haven't yet added any Sema-specific validations yet that are complex enough to break out, but we will 100% get there soon.
Not sure what you mean by downstream compiler. The current official HLSL compiler is a fork of clang-3.7. We don't intend to merge code in either direction. The fork does have modifications throughout clang including the parser, sema, and codegen layers.
I had a meeting with @beanz today because I was also pretty surprised. Chris, it might make sense to type up a bit of what we talked about as an FAQ and maybe stick it in Clang's docs directory; WDYT?
Totally agree. I had actually started working on something to help bring new contributors into the effort. I'll try to get something up this week.
Updating based on PR feedback.
I've moved the error reporting into Sema, and added additional errors for unsupported operators.
I've also expanded the test coverage with some of @aaron.ballman's cursed code, which improves coverage substantailly.
clang/include/clang/Basic/DiagnosticSemaKinds.td | ||
---|---|---|
11593–11598 | Should we be adding .* and ->* to the list of unsupported operators? (Hmmm, or can we never get to those operators because we can't form the base expression anyway?) | |
clang/lib/Sema/SemaExpr.cpp | ||
15372–15377 | How should this interplay with overloaded operators on user-defined types? Is that case allowed so long as it doesn't form a pointer or a reference? (We should add test coverage for that.) | |
clang/lib/Sema/SemaExprMember.cpp | ||
1739–1740 | Same question here for overloaded operators. | |
clang/test/SemaHLSL/prohibit_reference.hlsl | ||
5 | void chirp(int &&); // error |
One comment inline. Update coming in a few minutes.
clang/lib/Sema/SemaExpr.cpp | ||
---|---|---|
15372–15377 | So, the "correct" end goal is that we don't support overloading those operators. We have a few limitations on which operators we allow overloading for, generally any operators that in normal use return references or pointers, we don't allow you to overload. That said, I wrote some test code to see where this falls over with my current change: struct Fish { struct Fins { int Left; int Right; }; int X; int operator *() { return X; } Fins operator ->() { return Fins(); } }; int gone_fishing() { Fish F; int Result = *F; // works... and is consistent with DXC Result += F->Left; // error: member reference type 'Fish::Fins' is not a pointer return Result; } In the existing compiler we produce an error on definition of operators that aren't supported. I'd like to handle improving the diagnostics for those operators that way in a later patch if that is okay. The .* and .-> operators I couldn't get errors to actually trigger because I couldn't think of a way to write them that wasn't dependent on getting a member pointer, which errors and causes the remaining expression to not be checked. |
LGTM aside from the formatting nit.
clang/lib/Sema/SemaExpr.cpp | ||
---|---|---|
15372–15377 |
That's fine by me.
Perfect, I couldn't find a way either, we can punt on that until we find a concrete issue. |
Should we be adding .* and ->* to the list of unsupported operators? (Hmmm, or can we never get to those operators because we can't form the base expression anyway?)