Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable /Zc:preprocessor #10593

Merged
2 commits merged into from
Jul 13, 2021
Merged

Enable /Zc:preprocessor #10593

2 commits merged into from
Jul 13, 2021

Conversation

lhecker
Copy link
Member

@lhecker lhecker commented Jul 9, 2021

This commit is a preparation for upcoming changes to KeyChordSerialization for #7539 and #10203.
In order to support variadic macros, /Zc:preprocessor was enabled, which required changing unrelated parts of the project.

PR Checklist

  • I work here
  • Tests added/passed

Validation Steps Performed

  • Project still compiles ✔️

@lhecker lhecker force-pushed the dev/lhecker/7539-key-bindings branch from b521529 to a949fd9 Compare July 12, 2021 18:45
@lhecker lhecker marked this pull request as ready for review July 12, 2021 18:59
@lhecker lhecker force-pushed the dev/lhecker/7539-key-bindings branch from bf821dd to ffe7273 Compare July 12, 2021 19:03
@lhecker

This comment has been minimized.

@lhecker lhecker force-pushed the dev/lhecker/7539-key-bindings branch from ffe7273 to d09c3a2 Compare July 12, 2021 19:13
@@ -212,7 +212,7 @@ constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexce
#ifdef UNIT_TESTING

#define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format( \
L#attr L"=%s", VerifyOutputTraits<TextAttribute>::ToString(attr).GetBuffer())))
L## #attr L"=%s", VerifyOutputTraits<TextAttribute>::ToString(attr).GetBuffer())))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L#foo used to turn it into a L"foo" string, no matter what kind of literal foo was.
With standard conform macros this doesn't work anymore and we have to cast foo to a string using #foo and then concatenate it with L which forms L## #foo.

{ \
std::vector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> name##List; \
_##name##Map = winrt::single_threaded_map<enumType, winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>(); \
auto enumMapping##name = winrt::Microsoft::Terminal::Settings::Model::EnumMappings::enumMappingsName(); \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only suggest turning on white space suppressing in the GitHub diff viewer (append ?w=1 to the current url).

In standard conform macros ## can only be used to concatenate valid symbols together. You can't concatenate with ::. This change fixes the macro, but also ensures that local variables are eagerly released to the allocator by using a do-while scope.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious: why use do { ... } while(0); instead of just { ... }? Wouldn't that accomplish the same thing of adding a scope so that the variabels are released?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The do-while loop has the advantage that it cannot be used in any other statement, for instance within the conditional statement of a while loop or if condition. It forces the programmer to treat the macro as a regular statement that has no return value and that prevents additional misuse.

return sub && isProfilesDefaultsOrigin(sub.SourceProfile());
};

#define DUPLICATE_SETTING_MACRO(settingName) \
Copy link
Member Author

@lhecker lhecker Jul 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These macros were both invalid. Since I had to touch them anyways I fixed their COM overhead as a "drive by". We now use generic lambdas to abstract away as much work as possible from the macro. This doesn't just make debugging and reading easier (the macro looks a lot less scary without the diff), but also reduces code sizes after compilation, since the argument to our generic lambdas will always be the same type.

TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage),
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance),
TraceLoggingStruct(14, "wilResult", "wilResult"),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the strict macros, trailing commas in a macro are now forbidden. These can occur with variadic macros like

#define FOO(...) foo(123, __VA_ARGS__);

If you don't pass any arguments to FOO it'll generate a trailing comma, which isn't valid C++ code. One might think trailing commas should be supported in C++, because why not, but they aren't. Instead there's a hackjob called __VA_OPT__ which lets you write

#define FOO(...) foo(123 __VA_OPT__(,) __VA_ARGS__);

Since MSVC doesn't support the official __VA_OPT__, we have to write ## __VA_ARGS__ from now on, which isn't legit macro syntax, but it works despite using /Zc:preprocessor.


In this case we don't control TraceLoggingStruct, which doesn't use the ## __VA_ARGS__ trick.
As such we have to add a third argument (the "comment") to any TraceLoggingWrite parameters from now on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that I can accept this. Thanks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also set it to the empty string explicitly if we want to save on the .rodata segment. That's what used to happen with the previous non-conformant mode anyways (technically).

VERIFY_SUCCEEDED(StringCchCopy(szBuf, ARRAYSIZE(szBuf), L"(ev: "));

WEX::Common::NoThrowString str;
str.Append(L"(ev: ");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not needed. I did it before I realized I had to upgrade the entire TAEF package to make it work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine if you keep it in my opinion.

src/inc/til/string.h Outdated Show resolved Hide resolved
ghost pushed a commit that referenced this pull request Jul 12, 2021
Replaces `KeyModifiers` with the pretty much equivalent
`VirtualKeyModifiers` enum in winrt.

After doing this I noticed #10593 which changes the KeyChords a lot, but
it seems these PRs are still compatible

The issue also mentions replacing Vkey with
`Windows::System::VirtualKey`, but I chose not to because that enum only
includes a subset of the keys terminal supports here (no VK_OEM_* keys)

## Validation Steps Performed
Changed key bind in config, and confirmed it still works after
restarting terminal

Closes #877
Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, all of this looks good to me. I think the only thing I found was the duplicate copyright line haha.

That said, this seems like it's a bit too big in scope. I think it'd be nice if you split this into 3 PRs:

  1. Enable /Zc:preprocessor (Variadic Macro thing)
  2. (based off 1)
    1. Clean up KeyChordSerialization
    2. Add unit tests to til/string

Alternatively, I would be ok with you merging this PR without a squash, then just add a few more details on each commit/endeavor/scenario in the PR body.

@DHowett generally has more opinions regarding the repos commit history haha. Thoughts?

{ \
std::vector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> name##List; \
_##name##Map = winrt::single_threaded_map<enumType, winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>(); \
auto enumMapping##name = winrt::Microsoft::Terminal::Settings::Model::EnumMappings::enumMappingsName(); \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious: why use do { ... } while(0); instead of just { ... }? Wouldn't that accomplish the same thing of adding a scope so that the variabels are released?

Comment on lines -75 to +78
<AdditionalOptions>%(AdditionalOptions) /permissive- /bigobj /Zc:twoPhase-</AdditionalOptions>
<DisableSpecificWarnings>28204;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ConformanceMode>true</ConformanceMode>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
<AdditionalOptions>%(AdditionalOptions) /bigobj /Zc:twoPhase-</AdditionalOptions>
<DisableSpecificWarnings>5104;5105;28204;%(DisableSpecificWarnings)</DisableSpecificWarnings>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine to me, but somebody with way more knowledge of our build system should double check that this is ok.

Copy link
Member Author

@lhecker lhecker Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the warnings are:

  • C5104: found 'L#foo' in macro replacement list, did you mean 'L""#foo'?
    Which occurs in WRL, which we can't immediately fix. I suggest we migrate everything that uses WRL to WIL over time.
  • C5105: macro expansion producing 'defined' has undefined behavior
    This occurs in winbase.h, and is caused by Windows headers using conditional expressions inside definitions. They first declare something like #define FOO (_WIN32_WINNT >= 0x0502) and then use it as #if FOO, which isn't valid C/C++.

src/cascadia/UnitTests_Remoting/RemotingTests.cpp Outdated Show resolved Hide resolved
Comment on lines 1 to 2
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops

Comment on lines 14 to 17
constexpr std::wstring_view CTRL_KEY{ L"ctrl" };
constexpr std::wstring_view SHIFT_KEY{ L"shift" };
constexpr std::wstring_view ALT_KEY{ L"alt" };
constexpr std::wstring_view WIN_KEY{ L"win" };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't these need to be static?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because constexpr doesn't make any sense whatsoever. If you put a constexpr in global scope it's behaving as if it was static automatically. I can add static for consistency.

@DHowett
Copy link
Member

DHowett commented Jul 13, 2021

I'd left a comment on one of the commits, but I am not sure it shows up on the PR. Perhaps email?

@lhecker
Copy link
Member Author

lhecker commented Jul 13, 2021

@DHowett Yes I saw it and fixed the issue. It was about the SCW (?) macro change being wrong which I then reverted.

@lhecker lhecker force-pushed the dev/lhecker/7539-key-bindings branch from 79c0f42 to 9360050 Compare July 13, 2021 21:48
@lhecker lhecker changed the title Clean up KeyChordSerialization Enable /Zc:preprocessor Jul 13, 2021
std::sort(begin(name##List), end(name##List), EnumEntryComparator<enumType>()); \
_##name##List = winrt::single_threaded_observable_vector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry>(std::move(name##List));
#define INITIALIZE_BINDABLE_ENUM_SETTING(name, enumMappingsName, enumType, resourceSectionAndType, resourceProperty) \
do \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for taking the opportunity to fix this!

com_ptr<DeadPeasant> tombstone;
tombstone.attach(new DeadPeasant());
m->_peasants[peasantID] = *tombstone;
m->_peasants[peasantID] = *winrt::make_self<DeadPeasant>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically *make_self<T>() should be equivalent to make<T>() 😄

type _##name{ __VA_ARGS__ }; \
void _set##name(const type& value) \
{ \
const_cast<type&>(_##name) = value; \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh hey! an old implementation detail we didn't need any more.

TRIVIA: The storage for an "observable" property used to be marked const so that members of the class could not set it without calling _setX which forced them to send a notification every time they changed it.

<ConformanceMode>true</ConformanceMode>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
<AdditionalOptions>%(AdditionalOptions) /bigobj /Zc:twoPhase-</AdditionalOptions>
<DisableSpecificWarnings>5104;5105;28204;%(DisableSpecificWarnings)</DisableSpecificWarnings>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are fine. They're reports about non-conforming macros that we have to suppress because we turned on the conforming preprocessor.

TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage),
TraceLoggingLevel(WINEVENT_LEVEL_ERROR),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance),
TraceLoggingStruct(14, "wilResult", "wilResult"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that I can accept this. Thanks.

VERIFY_SUCCEEDED(StringCchCopy(szBuf, ARRAYSIZE(szBuf), L"(ev: "));

WEX::Common::NoThrowString str;
str.Append(L"(ev: ");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine if you keep it in my opinion.

@lhecker lhecker added Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Product-Terminal The new Windows Terminal. AutoMerge Marked for automatic merge by the bot when requirements are met labels Jul 13, 2021
@ghost
Copy link

ghost commented Jul 13, 2021

Hello @lhecker!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 32fbd4c into main Jul 13, 2021
@ghost ghost deleted the dev/lhecker/7539-key-bindings branch July 13, 2021 23:00
DHowett pushed a commit that referenced this pull request Aug 25, 2021
This commit is a preparation for upcoming changes to KeyChordSerialization for #7539 and #10203.
In order to support variadic macros, /Zc:preprocessor was enabled, which required changing unrelated parts of the project.

* [x] I work here
* [x] Tests added/passed

* Project still compiles ✔️

(cherry picked from commit 32fbd4c)
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. AutoMerge Marked for automatic merge by the bot when requirements are met Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants