Quantcast
Channel: C++ Team Blog
Viewing all 1541 articles
Browse latest View live

Smarter Member List Filtering for C++ 

$
0
0

We are always looking for ways to make you more productive while coding in Visual Studio. In Visual Studio 2019 version 16.2, we have created a smarter, more relevant Member List. Specifically, we now apply method filtering based on type qualifiers. To illustrate this, consider the following example: 

You have two vectors, but one is constWhen we invoke the member list on the non-const vector, we see the option for push_back. However, when we invoke the member list on the const vector, Visual Studio now knows not to display any non-const members on a const object: 

 

Even More Filtering 

If you wish to benefit further from Member List and completion filtering, try out Predictive IntelliSense. As an experimental feature, Predictive IntelliSense is disabled by default, but can be enabled under Tools > Options > Text Editor > C/C++ > Experimental. Or simply type “predictive” in the (Ctrl + Q) Search Bar. Currently, Predictive IntelliSense filters by type when you’re in an argument or assignment position. In the example below, i is of type int, so Predictive IntelliSense only shows int items in the completion list. 

Note: If you ever wish to unfilter the completion list, just click the green “+” symbol in the bottom left of the list. 

Talk to Us!  

If you have feedback on Member List filtering in Visual Studio, we would love to hear from you. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems with Visual Studio or MSVC or have a suggestion, you can use the Report a Problem tool in Visual Studio or head over to Visual Studio Developer Community. You can also find us on Twitter @VisualC and follow me @nickuhlenhuth.  

 

The post Smarter Member List Filtering for C++  appeared first on C++ Team Blog.


C++ Productivity Improvements in Visual Studio 2019 Preview 2

$
0
0

Visual Studio 2019 Preview 2 contains a host of productivity features, including some new quick fixes and code navigation improvements:

The Quick Actions menu can be used to select the quick fixes referenced below. You can hover over a squiggle and click the lightbulb that appears or open the menu with Alt + Enter.

Quick Fix: Add missing #include

Have you ever forgotten which header to reference from the C++ Standard Library to use a particular function or symbol? Now, Visual Studio will figure that out for you and offer to fix it:
When you use a type or function defined in a different header, and that header was not #included in the file, Visual Studio squiggles the symbol in red. Now, when you hover over the squiggle, you will be shown an option to automatially add the missing #include.

But this feature doesn’t just find standard library headers. It can tell you about missing headers from your codebase too:
The add missing #include quick fix even works for non-STL headers included in your codebase, so you don't have to remember where you declared everything all the time.

Quick Fix: NULL to nullptr

An automatic quick fix for the NULL->nullptr code analysis warning (C26477: USE_NULLPTR_NOT_CONSTANT) is available via the lightbulb menu on relevant lines, enabled by default in the “C++ Core Check Type Rules,” “C++ Core Check Rules,” and “Microsoft All Rules” rulesets.
It is generally bad practice to use the "NULL" macro in modern C++ code, so Visual Studio will place a squiggle under NULLs. When you hover over such a squiggle, Visual Studio will over to replace it with a nullptr for you.
You’ll be able to see a preview of the change for the fix and can choose to confirm it if it looks good. The code will be fixed automatically and green squiggle removed.

Quick Fix: Add missing semicolon

A common pitfall for students learning C++ is remembering to add the semicolon at the end of a statement. Visual Studio will now identify this issue and offer to fix it.
Visual Studio offers to add missing semicolons to your code where needed. Just hover over the squiggle that appears and choose the option to fix it in the menu.

Quick Fix: Resolve missing namespace or scope

Visual Studio will offer to add a “using namespace” statement to your code if one is missing, or alternatively, offer to qualify the symbol’s scope directly with the scope operator:
When you forget to qualify a type or function with the namespace it comes from, Visual Studio will offer to fill in the missing namespace, along with the scope operator, in the code. Alternatively, you can let Visual Studio insert a "using namespace" statement above the code.
Note: we are currently tracking a bug with the quick fix to add “using namespace” that may cause it to not work correctly – we expect to resolve it in a future update.

Quick Fix: Replace bad indirection operands (* to & and & to *)

Did you ever forget to dereference a pointer and manage to reference it directly instead? Or perhaps you meant to refer to the pointer and not what it points to? This quick action offers to fix such issues:
Visual Studio will offer to correct errors arising from using a * insteaof a & in your code (and vice versa). Hover over the squiggle and choose the corresponding fix to resolve the issue.

Quick Info on closing brace

You can now see a Quick Info tooltip when you hover over a closing brace, giving you some information about the starting line of the code block.
When you hover over a closing brace in Visual Studio, context will be provided about the starting line of the code block.

Peek Header / Code File

Visual Studio already had a feature to toggle between a header and a source C++ file, commonly invoked via Ctrl + K, Ctrl + O, or the right-click context menu in the editor. Now, you can also peek at the other file without leaving your current one with Peek Header / Code File (Ctrl + K, Ctrl + J):
You can peek at the header of a C++ source file with Ctrl + K, Ctrl + J. You can also peek at the source file of a header the same way.

Go to Document on #include

F12 is often used to go to the definition of a code symbol. Now you can also do it on #include directives to open the corresponding file. In the right-click context menu, this is referred to as Go to Document:
You can now press F12 on a #include directive to go to that file in Visual Studio.

Other productivity features to check out

We have several more C++ productivity improvements in Preview 2, covered in separate blog posts:

We want your feedback

We’d love for you to download Visual Studio 2019 and give it a try. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter problems with Visual Studio or MSVC, or have a suggestion for us, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

In-editor code analysis in Visual Studio 2019 Preview 2

$
0
0

The C++ team has been working to refresh the Code Analysis experience inside Visual Studio. Last year, we blogged about some in-progress features in this area. We’re happy to announce that in Visual Studio 2019 Preview 2, we’ve integrated code analysis directly into the editor, improved upon previously experimental features, and enabled this as the default experience.

In-editor warnings & background analysis

Code analysis now runs automatically in the background, and warnings display as green squiggles in-editor. Analysis re-runs every time you open a file in the editor and when you save your changes.

If you wish to disable – or re-enable – this feature, you can do so via the Tools > Options > Text Editor > C++ > Experimental > Code Analysis menu, where you’ll also be able to toggle squiggles displaying in-editor or the entire new C++ Code Analysis/Error List experience.

Squiggle display improvements

We’ve also made a few improvements to the display style of in-editor warnings. Squiggles are now only displayed underneath the code segment that is relevant to the warning. If we cannot find the appropriate code segment, we fall back to the Visual Studio 2017 behavior of showing the squiggle for the entire line.

Visual Studio 2017

Visual Studio 2019

We’ve also made performance improvements, especially for source files with many C++ code analysis warnings. Latency from when the file is analyzed until green squiggles appear has been greatly improved, and we’ve also enhanced the overall UI performance during code analysis squiggle display.

Light bulb suggestions & quick fixes

We’ve begun adding light bulb suggestions to provide automatic fixes for warnings. Please see the C++ Productivity Improvements in Visual Studio 2019 Preview 2 blog post for more information.

Send us feedback

Thank you to everyone who helps make Visual Studio a better experience for all. Your feedback is critical in ensuring we can deliver the best Code Analysis experience. We’d love for you to download Visual Studio 2019 Preview 2, give it a try, and let us know how it’s working for you in the comments below or via email (visualcpp@microsoft.com). If you encounter problems or have a suggestion, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion or via Visual Studio Developer Community. You can also find us on Twitter @VisualC.

Introducing the New CMake Project Settings UI

$
0
0

Visual Studio 2019 Preview 2 introduces a new CMake Project Settings Editor to help you more easily configure your CMake projects in Visual Studio. The editor provides an alternative to modifying the CMakeSettings.json file directly and allows you to create and manage your CMake configurations.  

If you’re just getting started with CMake in Visual Studio, head over to our CMake Support in Visual Studio introductory page

The new CMake Project Settings Editor

The goal of this editor is to simplify the experience of configuring a CMake project by grouping and promoting commonly used settings, hiding advanced settings, and making it easier to edit CMake variables. This is the first preview of this new UI so we will continue to improve it based on your feedback.  

Open the editor

The CMake Project Settings Editor opens by default when you select “Manage Configurations…” from the configuration drop-down menu at the top of the screen.  

Open the CMake Project Settings Editor by selecting "Manage Connections..." from the configuration drop-down menu at the top of the screen.

You can also right-click on CMakeSettings.json in the Solution Explorer and select “Edit CMake Settings” from the context menu. If you prefer to manage your configurations directly from the CMakeSettings.json file, you can click the link to “Edit JSON” in the top right-hand corner of the editor.  

Configurations sidebar

The left side of the editor contains a configurations sidebar where you can easily toggle between your existing configurations, add a new configuration, and remove configurations. You can also now clone an existing configuration so that the new configuration inherits all properties set by the original. 

The configurations sidebar is on the left side of the editor.

Sections of the editor

The editor contains four sections: General, Command Arguments, CMake Variables and Cache, and Advanced. The General, Command Arguments, and Advanced sections provide a user interface for properties exposed in the CMakeSettings.json file. The Advanced section is hidden by default and can be expanded by clicking the link to “Show advanced settings” at the bottom of the editor.  

The CMake Variables and Cache section provides a new way for you to edit CMake variables. You can click “Save and Generate CMake Cache to Load Variables” to generate the CMake cache and populate a table with all the CMake cache variables available for you to edit. Advanced variables (per the CMake GUI) are hidden by default. You can check “Show Advanced Variables” to show all cache variables or use the search functionality to filter CMake variables by name. 

The CMake Variables and Cache section provides a new way for you to edit CMake variables.

You can change the value of any CMake variable by editing the “Value” column of the table. Modified variables are automatically saved to CMakeSettings.json 

Linux configurations

The CMake Project Settings Editor also provides support for Linux configurations. If you are targeting a remote Linux machine, the editor will expose properties specific to a remote build and link to the Connection Manager, where you can add and remove connections to remote machines.  

CMake Settings support for Linux configurations.

Give us your feedback!

We’d love for you to download Visual Studio 2019 and give it a try. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems with Visual Studio or MSVC or have a suggestion please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp). 

Concurrency Code Analysis in Visual Studio 2019

$
0
0

Concurrency Code Analysis in Visual Studio 2019

The battle against concurrency bugs poses a serious challenge to C++ developers. The problem is exacerbated by the advent of multi-core and many-core architectures. To cope with the increasing complexity of multithreaded software, it is essential to employ better tools and processes to help developers adhere to proper locking discipline. In this blog post, we’ll walk through a completely rejuvenated Concurrency Code Analysis toolset we are shipping with Visual Studio 2019 Preview 2.

A perilous landscape

The most popular concurrent programming paradigm in use today is based on threads and locks. Many developers in the industry have invested heavily in multithreaded software. Unfortunately, developing and maintaining multithreaded software is difficult due to a lack of mature multi-threaded software development kits.

Developers routinely face a dilemma in how to use synchronization. Too much may result in deadlocks and sluggish performance. Too little may lead to race conditions and data inconsistency. Worse yet, the Win32 threading model introduces additional pitfalls. Unlike in managed code, lock acquire and lock release operations are not required to be syntactically scoped in C/C++. Applications therefore are vulnerable to mismatched locking errors. Some Win32 APIs have subtle synchronization side effects. For example, the popular “SendMessage” call may induce hangs among UI threads if not used carefully. Because concurrency errors are intermittent, they are among the hardest to catch during testing. When encountered, they are difficult to reproduce and diagnose. Therefore, it is highly beneficial to apply effective multi-threading programming guidelines and tools as early as possible in the engineering process.

Importance of locking disciplines

Because one generally cannot control all corner cases induced by thread interleaving, it is essential to adhere to certain locking disciplines when writing multithreaded programs. For example, following a lock order while acquiring multiple locks or using std::lock() consistently helps to avoid deadlocks; acquiring the proper guarding lock before accessing a shared resource helps to prevent race conditions. However, these seemingly simple locking rules are surprisingly hard to follow in practice.

A fundamental limitation in today’s programming languages is that they do not directly support specifications for concurrency requirements. Programmers can only rely on informal documentation to express their intention regarding lock usage. Thus, developers have a clear need for pragmatic tools that help them confidently apply locking rules.

Concurrency Toolset

To address the deficiency of C/C++ in concurrency support, we had shipped an initial version of concurrency analyzer back in Visual Studio 2012, with promising initial results. This tool had a basic understanding of the most common Win32 locking APIs and concurrency related annotations.

In Visual Studio 2019 Preview 2, we are excited to announce a completely rejuvenated set of concurrency checks to meet the needs of modern C++ programmers. The toolset comprises a local intra-procedural lock analyzer with built-in understanding of common Win32 locking primitives and APIs, RAII locking patterns, and STL locks.

Getting started

The concurrency checks are integrated as part of the code analysis toolset in Visual Studio. The default “Microsoft Native Recommended Ruleset” for the project comprises the following rules from the concurrency analyzer. This means, whenever you run code analysis in your project, these checks are automatically executed. These checks are also automatically executed as part of the background code analysis runs for your project. For each rule, you can click on the link to learn more about the rule and its enforcement with clear examples.

  • C26100: Race condition. Variable should be protected by a lock.
  • C26101: Failing to use interlocked operation properly for a variable.
  • C26110: Caller failing to acquire a lock before calling a function which expects the lock to be acquired prior to being called.
  • C26111: Caller failing to release a lock before calling a function which expects the lock to be released prior to being called.
  • C26112: Caller cannot hold any lock before calling a function which expects no locks be held prior to being called.
  • C26115: Failing to release a lock in a function. This introduces an orphaned lock.
  • C26116: Failing to acquire a lock in a function, which is expected to acquire the lock.
  • C26117: Releasing an unheld lock in a function.
  • C26140: Undefined lock kind specified on the lock.

If you want to try out the full set of rules from this checker, there’s a ruleset just for that. You must right click on Project > Properties > Code Analysis > General > Rulesets > Select “Concurrency Check Rules”.

Screenshot of the Code Analysis properties page that shows the ConcurrencyCheck Rules ruleset selected.

You can learn more about each rule enforced by the checker by searching for rule numbers in the ranges C26100 – C26199 in our Code Analysis for C/C++ warning document.

Concurrency toolset in action

The initial version of concurrency toolset was capable of finding concurrency related issues like race conditions, locking side effects, and potential deadlocks in mostly C-like code.

The tool had in-built understanding of standard Win32 locking APIs. For custom functions with locking side effects, the tool understood a number of concurrency related annotations. These annotations allowed the programmer to express locking behavior. Here are some examples of concurrency related annotations.

  • _Acquires_lock_(lock): Function acquires the lock object “lock”.
  • _Releases_lock_(lock): Function releases the lock object “lock”.
  • _Requires_lock_held_(lock): Lock object “lock” must be acquired before entering this function.
  • _Guarded_by_(lock) data: “data” must always be protected by lock object “lock”.
  • _Post_same_lock(lock1, lock2): “lock1” and “lock2” are aliases.

For a complete set of concurrency related annotations, please see this article Annotating Locking Behavior.

The rejuvenated version of the toolset builds on the strengths of the initial version by extending its analysis capabilities to modern C++ code. For example, it now understands STL locks and RAII patterns without having to add any annotations.

Now that we have talked about how the checker works and how you can enable them in your project, let’s look at some real-world examples.

Example 1

Can you spot an issue with this code1 ?

struct RequestProcessor {​
    CRITICAL_SECTION cs_;​
    std::map<int, Request*> cache_;​
​
    bool HandleRequest(int Id, Request* request) {​
        EnterCriticalSection(&cs_);​
        if (cache_.find(Id) != cache_.end()) ​
            return false;    ​
        cache_[Id] = request;                    ​
        LeaveCriticalSection(&cs_);   ​
    }​
    void DumpRequestStatistics() {​
        for (auto& r : cache_) ​
            std::cout << "name: " << r.second->name << std::endl;​
    }​
};​

1 If you have seen this talk given by Anna Gringauze in CppCon 2018, this code may seem familiar to you.

Let’s summarize what’s going on here:

  1. In function HandleRequest, we acquire lock cs on line 6. However, we return early from line 8 without ever releasing the lock.
  2. In function HandleRequest, we see that cache_ access must be protected by lock cs. However, in a different function, DumpStatistics, we access cache_ without acquiring any lock.

If you run code analysis on this example, you’ll get a warning in method HandleRequest, where it will complain about the leaked critical section (issue #1):

This shows the leaked critical section warning from the concurrency analyzer.

Next, if you add the _Guarded_by_ annotation on the field cache_ and select ruleset “Concurrency Check Rules”, you’ll get an additional warning in method DumpRequestStatistics for the possible race condition (issue #2):

This shows the potential race condition warning from the concurrency analyzer.

Example 2

Let’s look at a more modern example. Can you spot an issue with this code1 ?

struct RequestProcessor2 {​
    std::mutex​ m_;
    std::map<int, Request*> cache_;​
​
    void HandleRequest(int Id, Request* request) {​
        std::lock_guard grab(m_);
        if (cache_.find(Id) != cache_.end()) ​
            return;    ​
        cache_[Id] = request;                    ​
    }​
    void DumpRequestStatistics() {​
        for (auto& r : cache_) ​
            std::cout << "name: " << r.second->name << std::endl;​
    }​
};

As expected, we don’t get any warning in HandleRequest in the above implementation using std::lock_guard. However, we still get a warning in DumpRequestStatistics function:

This shows the potential race condition warning from the concurrency analyzer.

There are a couple of interesting things going on behind the scenes here. First, the checker understands the locking nature of std::mutex. Second, it understands that std::lock_guard holds the mutex and releases it during destruction when its scope ends.

This example demonstrates some of the capabilities of the rejuvenated concurrency checker and its understanding of STL locks and RAII patterns.

Give us feedback

We’d love to hear from you about your experience of using the new concurrency checks. Remember to switch to “Concurrency Check Rules” for your project to explore the full capabilities of the toolset. If there are specific concurrency patterns you’d like us to detect at compile time, please let us know.

If you have suggestions or problems with this check — or any Visual Studio feature — either Report a Problem or post on Developer Community. We’re also on Twitter at @VisualC.

New Code Analysis Checks in Visual Studio 2019: use-after-move and coroutine

$
0
0

New Code Analysis Checks in Visual Studio 2019: use-after-move and coroutine

Visual Studio 2019 Preview 2 is an exciting release for the C++ code analysis team. In this release, we shipped a new set of experimental rules that help you catch bugs in your codebase, namely: use-after-move and coroutine checks. This article provides an overview of the new rules and how you can enable them in your project.

Use-after-move check

C++11 introduced move semantics to help write performant code by replacing some expensive copy operations with cheaper move operations. With the new capabilities of the language, however, we have new ways to make mistakes. It’s important to have the tools to help find and fix these errors.

To understand what these errors are, let’s look at the following code example:

MyType m;
consume(std::move(m));
m.method();

Calling consume will move the internal representation of m. According to the standard, the move constructor must leave m in a valid state so it can be safely destroyed. However, we can’t rely on what that state is. We shouldn’t call any methods on m that have preconditions, but we can safely reassign m, since the assignment operator does not have a precondition on the left-hand side. Therefore, the code above is likely to contain latent bugs. The use after move check is intended to find exactly such code, when we are using a moved-from object in a possibly unintended way.

There are several interesting things happening in the above example:

  • std::move does not actually move m. It’s only cast to a rvalue reference. The actual move happens inside the function consume.
  • The analysis is not inter-procedural, so we will flag the code above even if consume is not actually moving m. This is intentional, since we shouldn’t be using rvalue references when moving is not involved – it’s plain confusing. We recommend rewriting such code in a cleaner way.
  • The check is path sensitive, so it will follow the flow of execution and avoid warning on code like the one below.
    Y y;
    if (condition)
      consume(std::move(y));
    if (!condition)
      y.method();

In our analysis, we basically track what’s happening with the objects.

  • If we reassign a moved-from object it is no longer moved from.
  • Calling a clear function on a container will also cleanse the “moved-from”ness from the container.
  • We even understand what “swap” does, and the code example below works as intended:
    Y y1, y2;
    consume(std::move(y1));
    std::swap(y1, y2);
    y1.method();   // No warning, this is a valid object due to the swap above.
    y2.method();   // Warning, y2 is moved-from.

Coroutine related checks

Coroutines are not standardized yet but they are well on track to become standard. They are the generalizations of procedures and provide us with a useful tool to deal with some concurrency related problems.

In C++, we need to think about the lifetimes of our objects. While this can be a challenging problem on its own, in concurrent programs, it becomes even harder.

The code example below is error prone. Can you spot the problem?

std::future async_coro(int &counter)
{
  Data d = co_await get_data();
  ++counter;
}

This code is safe on its own, but it’s extremely easy to misuse. Let’s look at a potential caller of this function:

int c;
async_coro(c);

The source of the problem is that async_coro is suspended when get_data is called. While it is suspended, the flow of control will return to the caller and the lifetime of the variable c will end. By the time async_coro is resumed the argument reference will point to dangling memory.

To solve this problem, we should either take the argument by value or allocate the integer on the heap and use a shared pointer so its lifetime will not end too early.

A slightly modified version of the code is safe, and we will not warn:

std::future async_coro(int &counter)
{
  ++counter;
  Data d = co_await get_data();
}

Here, we’ll only use the counter before suspending the coroutine. Therefore, there are no lifetime issues in this code. While we don’t warn for the above snippet, we recommend against writing clever code utilizing this behavior since it’s more prone to errors as the code evolves. One might introduce a new use of the argument after the coroutine was suspended.

Let’s look at a more involved example:

int x = 5;
auto bad = [x]() -> std::future {
  co_await coroutine();
  printf("%d\n", x);
};
bad();

In the code above, we capture a variable by value. However, the closure object which contains the captured variable is allocated on the stack. When we call the lambda bad, it will eventually be suspended. At that time, the control flow will return to the caller and the lifetime of captured x will end. By the time the body of the lambda is resumed, the closure object is already gone. Usually, it’s error prone to use captures and coroutines together. We will warn for such usages.

Since coroutines are not part of the standard yet, the semantics of these examples might change in the future. However, the currently implemented version in both Clang and MSVC follows the model described above.

Finally, consider the following code:

generator mutex_acquiring_generator(std::mutex& m) {
  std::lock_guard grab(m);
  co_yield 1;
}

In this snippet, we yield a value while holding a lock. Yielding a value will suspend the coroutine. We can’t be sure how long the coroutine will remain suspended. There’s a chance we will hold the lock for a very long time. To have good performance and avoid deadlocks, we want to keep our critical sections short. We will warn for the code above to help with potential concurrency related problems.

Enabling the new checks in the IDE

Now that we have talked about the new checks, it’s time to see them in action. The section below describes the step-by-step instructions for how to enable the new checks in your project for Preview 2 builds.

To enable these checks, we go through two basic steps. First, we select the appropriate ruleset and second, we run code analysis on our file/project.

Use after free

  1. Select: Project > Properties > Code Analysis > General > C++ Core Check Experimental Rules.
    Screenshot of the Code Analysis properties page that shows the C++ Core Check Experimental Rules ruleset selected.
  2. Run code analysis on the source code by right clicking on File > Analyze > Run code analysis on file.
  3. Observe warning C26800 in the code snippet below:
    Screenshot showing "use of a moved from object" warning

Coroutine related checks

  1. Select: Project > Properties > Code Analysis > General > Concurrency Rules.Screenshot of the Code Analysis properties page that shows the Concurrency Rules ruleset selected.
  2. Run code analysis on the source code by right clicking on File > Analyze > Run code analysis on file.
  3. Observe warning C26810 in the code snippet below:Screenshot showing a warning that the lifetime of a captured variable might end before a coroutine is resumed.
  4. Observe warning C26811 in the code snippet below:Screenshot showing a warning that the lifetime of a variable might end before the coroutine is resumed.
  5. Observe warning C26138 in the code snippet below:Screenshot shows a warning that we are suspending a coroutine while holding a lock.

Wrap Up

We’d love to hear from you about your experience of using these new checks in your codebase, and also for you to tell us what sorts of checks you’d like to see from us in the future releases of VS. If you have suggestions or problems with these checks — or any Visual Studio feature — either Report a Problem or post on Developer Community and let us know. We’re also on Twitter at @VisualC.

Visual Studio Code C/C++ extension: January 2019 Update

$
0
0

The January 2019 update of the Visual Studio Code C++ extension is now available. This release includes many new features and bug fixes including documentation comments support, improved #include autocomplete performance, better member function completion, and many IntelliSense bug fixes. For a full list of this release’s improvements, check out our release notes on Github.

Documentation Comments

We added support for documentation comments for hover, completion, and signature help. You can now see documentation comments in tooltips. Let’s look at a simple box_sample.cpp program that defines a “Box” object with various dimensions.

Class box with lenght, width, height. Function volume that takes in lenght, width, height and returns length * width * height. Main that creates a new Box package and sets length to 2.0, width to 2.0, and height to 4.0. Prints package.volume.

The comment associated with a class or member function is shown in a tooltip when you hover over a place where the class or member function is used. For example, we can see the “Box object” comment in our main function where we create a Box instance:

Hovering over Box provides a tooltip with the comment for the Box member function

#include Autocomplete

This update improves #include autocomplete performance. It now shows individual folders instead of entire paths, thus fixing previous performance issues. When you autocomplete the #include recommendation. In the example below, we modified our original box_sample.cpp program where we place the Box object definition in a separate header file within the “Objects” folder. Now, when we go into our main box_sample.cpp file and see our #include auto-complete suggestion, we see the “Objects” folder auto-complete recommendation.

#include provides an autocomplete suggestion for the Objects folder which contains the box.h header file

Improved Member Function Completion

With improved member function completion, the selected completion is committed after a parenthesis “(“ is entered. This removes the need to accept an autocompletion (using tab, enter, or click) and type the parenthesis. You will now receive the suggested text along with parentheses and the cursor in the middle for a simpler editing experience. Here’s a look at how this works with the “volume” member function for our Box object:

The volume member function in main is completed when you type just "vo" and a "("

This also works for class and member function templates after you type a “<” completion character.

Note that if you accept the autocompletion using tab, enter, or click, we do not currently auto-add the parenthesis.

IntelliSense Bug Fixes

As per customer feedback, we’re continuing to work on bug fixes for IntelliSense. This release we’ve made some IntelliSense fixes including error squiggle improvements, process crash fixes, and increased stability.

You can see additional details of the issues we fixed in our release notes on GitHub.

Tell Us What You Think

Download the C/C++ extension for Visual Studio Code, give it a try, and let us know what you think. If you run into any issues, or have any suggestions, please report them on the Issues section of our GitHub repository. Join our Insiders program to get early builds of our extension.

Please also take our quick survey to help us shape this extension to meet your needs. We can be reached via the comments below or via email (visualcpp@microsoft.com). You can also find us on Twitter (@VisualC).

C++ Binary Compatibility and Pain-Free Upgrades to Visual Studio 2019

$
0
0

Visual Studio 2019 pushes the boundaries of individual and team productivity. We hope that you will find these new capabilities compelling and start your upgrade to Visual Studio 2019 soon.

As you are considering this upgrade, rest assured that Visual Studio 2019 makes it distinctively easy to move your codebase from previous versions of Visual Studio. This post captures the reasons why your upgrade to Visual Studio 2019 will be pain-free.

Side-by-side Visual Studio Installations

You can install the latest version of Visual Studio on a computer that already has an earlier version installed and continue to use both versions in parallel with no interference. This is a great way to try Visual Studio 2019 or adopt it for some of your projects. The Visual Studio Installer will let you manage installations of Visual Studio 2017 and 2019 from a central UI.

Visual Studio Installer image showing VS 2017 and VS 2019 installed side-by-side

MSVC v140 (VS 2015.3) and MSVC v141 (VS 2017) Toolsets in the Visual Studio 2019 IDE

Even if you are not ready yet to move your project to the latest toolset (MSVC v142), you can still load your project in the Visual Studio 2019 IDE and continue to use your current older toolset.

Loading your existing C++ projects into the IDE will not upgrade/change your project files. This way, your projects also load in the previous version of the IDE in case you need to go back or you have teammates that have not yet upgraded to VS 2019 (this functionality is also known as project round-tripping).

Toolsets from older VS installations on your box are visible as platform toolsets in the latest IDE. And if you are starting fresh with only VS 2019 installed on your machine, it is very easy to acquire these older toolsets directly from the Visual Studio Installer by customizing the C++ Desktop workload (with the Individual Components tab listing all the options).

VS Installer Individual Components tab showing the full list of C++ components available in VS 2019

New v142 toolset now available

Within the Visual Studio 2019 wave (previews, its general availability, and future updates), we plan to continue evolving our C++ compilers and libraries with

  • new C++20 features,
  • faster build throughput, and
  • even better codegen optimizations.

The MSVC v142 toolset is now available and it already brings several incentives for you to migrate.

VC Runtime in the latest MSVC v142 toolset is binary compatible with v140 and v141

We heard it loud and clear that a major reason contributing to MSVC v141’s fast adoption today is its binary compatibility with MSVC v140. This allowed you to migrate your own code to the v141 toolset at your own pace, without having to wait for any of your 3rd party library dependencies to migrate first.

We want to keep the momentum going and make sure that you have a similarly successful adoption experience with MSVC v142 too. This is why we’re announcing today that our team is committed to provide binary compatibility for MSVC v142 with both MSVC v141 and v140.

This means that if you compile all your code with the v142 toolset but still have one or more libraries that are built with the v140 or v141 toolset, linking all of it together (with the latest linker) will work as expected. To make this possible, VC Runtime does not change its major version in VS 2019 and remains backward compatible with previous VC Runtime versions.

C:\source\repos\TimerApp\Debug>dumpbin TimerApp2019.exe /IMPORTS | findstr .dll
mfc140ud.dll
KERNEL32.dll
USER32.dll
GDI32.dll
COMCTL32.dll
OLEAUT32.dll
gdiplus.dll
VCRUNTIME140D.dll
ucrtbased.dll
       2EE _seh_filter_dll

When you mix binaries built with different supported versions of the MSVC toolset, there is a version requirement for the VCRedist that you redistribute with your app. Specifically, the VCRedist can’t be older than any of the toolset versions used to build your app.

Hundreds of C++ libraries on Vcpkg are available regardless of the toolset you’re using

If you are using Vcpkg today with VS 2015 or VS 2017 for one or more of your open-source dependencies, you will be happy to learn that these libraries (close to 900 at the time of this writing) can now be compiled with the MSVC v142 toolset and are available for consumption in Visual Studio 2019 projects.

If you are just getting started with Vcpkg, no worries – Vcpkg is an open-source project from Microsoft to help simplify the acquisition and building of open-source C++ libraries on Windows, Linux, and Mac.

Because v142 is binary compatible with v141 and v140, all the packages you’ve already installed will also continue to work in VS 2019 without recompilation; however, we do recommend recompiling when you can so that you can enjoy the new compiler optimizations we’ve added to v142!

If you have VS 2019 Preview installed side-by-side with an older version of VS (e.g. VS 2017), Vcpkg will prefer the stable release, so you will need to set Vcpkg’s triplet variable VCPKG_PLATFORM_TOOLSET to v142 to use the latest MSVC toolset.

MSVC compiler version changes to 19.2x (from 19.1x in MSVC v141)

Last but not least, the compiler part of the MSVC v142 toolset changes its version to 19.20 – only a minor version increment compared with MSVC v141.

VS editor with Quick Info showing that _MSC_VER macro equals 1920
Note that feature-test macros are supported in the MSVC compiler and STL starting with MSVC v141 and they should be the preferred option to enable your code to support multiple MSVC versions.

Call to action

Please download Visual Studio 2019 today and let us know what you think. Our goal is to make your transition to VS 2019 as easy as possible so, as always, we are very interested in your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com).
If you encounter other problems with Visual Studio or MSVC or have a suggestion please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter at @VisualC.


What’s New in CMake – Visual Studio 2019 Preview 2

$
0
0

We have made a bunch of improvements to Visual Studio’s CMake support in the latest preview of the IDE. Many of these changes are taking the first steps to close the gap between working with solutions generated by CMake and the IDE’s native support. Please try out the preview and let us know what you think.

If you are new to CMake in Visual Studio, check out how to get started.

CMake Menu Reorganization

One of the first things you might notice when you open your CMake projects in Visual Studio 2019 Preview 2 is that the CMake menu has disappeared. Don’t worry, nothing is wrong. We just reorganized these items into the existing Project, Build, Debug, and Test menus. For instance, the Project menu now looks like this:

New Project menu with CMake Settings and cache control.

The CMake settings and cache control entries have been moved from the CMake menu to the project menu. Items related to Build, Debug, and Test have been moved accordingly. We hope this reorganization is more intuitive to new users and users who have been using Visual Studio for a long time.

CMake Settings Editor

We received a lot of feedback about the CMakeSettings.json since we first shipped CMake support in Visual Studio. To simplify configuring CMake projects, we have added a graphical editor for CMake Settings.

CMake Settings editor.

You can learn more about the editor here. We would love to hear your feedback about what works well and what doesn’t for your projects. Please try it out and let us know.

Vcpkg Integration

If you have installed vcpkg, CMake projects opened in Visual Studio will automatically integrate the vcpkg toolchain file. This means you don’t have to do any additional configuration to use vcpkg with your CMake projects. This support works for both local vcpkg installations and vcpkg installations on remote machines that you are targeting. This behavior is disabled automatically when you specify any other toolchain in your CMake Settings configuration.

If you are interested in learning more about vcpkg and CMake, stay tuned. A more detailed post about using vcpkg with CMake is coming to the blog soon.

Easier CMake Toolchain Customization

If you use custom CMake toolchain files, configuring your projects just got a little bit easier. Previously, you had to manually specify CMake toolchain files with the “cmakeArgs” parameter in CMakeSettings.json. Now, instead of adding “-DCMAKE_TOOLCHAIN_FILE=…” to the command line you can simply add a “cmakeToolchain” parameter to your configuration in CMake Settings.

The IDE will warn you if you attempt to specify more than one toolchain file.

Automatic Installation of CMake on Linux Targets

Visual Studio’s Linux support for CMake projects requires a recent version of CMake to be installed on the target machine. Often, the version offered by a distribution’s default package manager is not recent enough to support all the IDE’s features. Previously, the only way to work around this was to build CMake from source or install more recent pre-built binaries manually. This was especially painful for users who targeted many Linux machines.

The latest preview of Visual Studio can automatically install a user local copy of CMake on remote Linux machines that don’t have a recent (or any) version of CMake installed. If a compatible version of CMake isn’t detected the first time you build your project, you will see an info-bar asking if you want to install CMake. With one click you will be ready to build and debug on the remote machine.

Support for Just My Code

Visual Studio 2019 Preview 2 also adds Just My Code support for CMake projects. If you are building for Windows using the MSVC compiler your CMake projects will now enable Just my Code support in the compiler and linker automatically.

To debug with Just my Code, make sure the feature is enabled in Tools > Options > Debugging > General.

Tools > Options > Debugger > General, "Enable Just My Code."

For now, you will need to use the version of CMake that ships with Visual Studio to get this functionality. This feature will be available for all installations of CMake in an upcoming version. If you need to suppress this behavior for any reason you can modify your CMakeLists to remove the “/JMC” flag from “CMAKE_CXX_FLAGS”.

Warnings for Misconfigured CMake Settings

A common source of user feedback and confusion has been the results of choosing incompatible settings for a CMake project’s configuration in CMakeSettings.json. For instance:

  • Using a 32-bit generator with a 64-bit configuration.
  • Using the wrong kind of verbosity syntax in “buildCommandArgs” for the chosen generator.

Warnings for misconfigured CMake Settings.

These misconfigurations are now called out explicitly by the IDE instead of causing CMake configuration failures that can often be difficult to diagnose.

Better Build Feedback and CMake Configure Verbosity

CMake project build and configuration progress is now better integrated into the IDE’s UI. You will see build progress in the status bar when using the Ninja and MSBuild generators.

You also now have more control over the verbosity of messages from CMake during configure. By default, most messages will be suppressed unless there is an error. You can see all messages by enabling this feature in Tools > Options > CMake.

Tools > Options > CMake > General, "Enable verbose CMake diagnostic output."

Send Us Feedback

Your feedback is a critical part of ensuring that we can deliver the best CMake experience.  We would love to know how Visual Studio 2019 Preview is working for you. If you have any feedback specific to CMake Tools, please reach out to cmake@microsoft.com. For general issues please Report a Problem.

Using VS Code for C++ development with containers

$
0
0

This post builds on using multi-stage containers for C++ development. That post showed how to use a single Dockerfile to describe a build stage and a deployment stage resulting in a container optimized for deployment. It did not show you how to use a containers with your development environment. Here we will show how to use those containers with VS Code. The source for this article is the same as that of the previous article: the findfaces GitHub repo.

Creating a container for use with VS Code

VS Code has the capability to target a remote system for debugging. Couple that with a custom build task for compiling in your container and you will have an interactive containerized C++ development environment.

We’ll need to change our container definition a bit to enable using it with VS Code. These instructions are based on some base container definitions that David Ducatel has provided in this GitHub repo. What we’re doing here is taking those techniques and applying them to our own container definition. Let’s look at another Dockerfile for use with VS Code, Dockerfile.vs.

FROM findfaces/build

LABEL description="Container for use with VS"

RUN apk update && apk add --no-cache \
    gdb openssh rsync zip

RUN echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \
    echo 'PermitEmptyPasswords yes' >> /etc/ssh/sshd_config && \
    echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config && \
    ssh-keygen -A

EXPOSE 22 
CMD ["/usr/sbin/sshd", "-D"]

In the FROM statement we’re basing this definition on the local image we created earlier in our multi-stage build. That container already has all our basic development prerequisites, but for VS Code usage we need a few more things enumerated above. Notably, we need SSH for communication with VS Code for debugging which is configured in the RUN command. As we are enabling root login, this container definition is not appropriate for anything other than local development. The entry point for this container is SSH specified in the CMD line. Building this container is simple.

docker build -t findfaces/vs -f Dockerfile.vs .

We need to specify a bit more to run a container based on this image so VS Code can debug processes in it.

docker run -d -p 12345:22 --security-opt seccomp:unconfined -v c:/source/repos/findfaces/src:/source --name findfacesvscode findfaces/vs

One of the new parameters we haven’t covered before is –security-opt. As debugging requires running privileged operations, we’re running the container in unconfined mode. The other new parameter we’re using is -v, which creates a bind mount that maps our local file system into the container. This is so that when we edit files on our host those changes are available in the container without having to rebuild the image or copy them into the running container. If you look at Docker’s documentation, you’ll find that volumes are usually preferred over bind mounts today. However, sharing source code with a container is considered a good use of a bind mount. Note that our build container copied our src directory to /src. Therefore in this container definition we will use interactively we are mapping our local src directory to /source so it doesn’t conflict with what is already present in the build container.

Building C++ in a container with VS Code

First, let’s configure our build task. This task has already been created in tasks.json under the .vscode folder in the repo we’re using with this post. To configure it in a new project, press Ctrl+Shift+B and follow the prompts until you get to “other”. Our configured build task appears as follows.

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "ssh",
            "args": [
                "root@localhost",
                "-p",
                "34568",
                "/source/build.sh"
            ],
            "problemMatcher": [
                "$gcc"
            ]
        }
    ]
}

The “label” value tells VS Code this is our build task and the type that we’re running a command in the shell. The command here is ssh (which is available on Windows 10). The arguments are passing the parameters to ssh to login to the container with the correct port and run a script. The content of that script reads as follows.

cd /source/output && \
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=/tmp/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-linux-musl && \
make

You can see that this script just invokes CMake in our output directory, then builds our project. The trick is that we are invoking this via ssh in our container. After this is set up, you can run a build at any time from within VS Code, as long as your container is running.

Debugging C++ in a container with VS Code

To bring up the Debug view click the Debug icon in the Activity Bar. Tasks.json has already been created in the .vscode folder of the repo for this post. To create one in a new project, select the configure icon and follow the prompts to choose any configuration. The configuration we need is not one of the default options, so once you have your tasks.json select Add Configuration and choose C/C++: (gdb) Pipe Launch. The Pipe Launch configuration starts a tunnel, usually SSH, to connect to a remote machine and pipe debug commands through.

You’ll want to modify the following options in the generated Pipe Launch configuration.

            "program": "/source/output/findfaces",
            "args": [],
            "stopAtEntry": true,
            "cwd": "/source/out",

The above parameters in the configuration specify the program to launch on the remote system, any arguments, whether to stop at entry, and what the current working directory on the remote is. The next block shows how to start the pipe.

            "pipeTransport": {
                "debuggerPath": "/usr/bin/gdb",
                "pipeProgram": "C:/Windows/system32/OpenSSH/ssh.exe",
                "pipeArgs": [
                    "root@localhost",
                    "-p",
                    "34568"
                ],
                "pipeCwd": ""
            },

You’ll note here that “pipeProgram” is not just “ssh”, the full path to the executable is required. The path in the example above is the full path to ssh on Windows, it will be different on other systems. The pipe arguments are just the parameters to pass to ssh to start the remote connection. The debugger path option is the default and is correct for this example.
We need to add one new parameter at the end of the configuration.

            "sourceFileMap": {
                "/source": "c:/source/repos/findfaces/src"
            }

This option tells the debugger to map /source on the remote to our local path so that our sources our properly found.

Hit F5 to start debugging in the container. The provided launch.json is configured to break on entry so you can immediately see it is working.

IntelliSense for C++ with a container

There are a couple of ways you can setup IntelliSense for use with your C++ code intended for use in a container. Throughout this series of posts we have been using vcpkg to get our libraries. If you use vcpkg on your host system, and have acquired the same libraries using it, then your IntelliSense should work for your libraries.

System headers are another thing. If you are working on Mac or Linux perhaps they are close enough that you are not concerned with configuring this. If you are on Windows, or you want your IntelliSense to exactly match your target system, you will need to get your headers onto your local machine. While your container is running, you can use scp to accomplish this (which is available on Windows 10). Create a directory where you want to save your headers, navigate there in your shell, and run the following command.

scp -r -P 12345 root@localhost:/usr/include .

To get the remote vcpkg headers you can similarly do the following.

scp -r -P 12345 root@localhost:/tmp/vcpkg/installed/x64-linux-musl/include .

As an alternative to scp, you can also use Docker directly to get your headers. For this command the container need not be running.

docker cp -L findfacesvs:/usr/include .

Now you can configure your C++ IntelliSense to use those locations.

Keeping up with your containers

When you are done with your development simply stop the container.

docker stop findfacesvscode

The next time you need it spin it back up.

docker start findfacesvscode

And of course, you need to rerun your multi-stage build to populate your runtime container with your changes.

docker build -t findfaces/run .

Remember that in this example we have our output configured under our source directory on the host. That directory will be copied into the build container if you don’t delete it (which you don’t want), so delete the output directory contents before rebuilding your containers (or adjust your scripts to avoid this issue).

What next

We plan to continue our exploration of containers in future posts. Looking forward, we will introduce a helper container that provides a proxy for our service and to deploy our containers to Azure. We will also revisit this application using Windows containers in the future.

Give us feedback

We’d love to hear from you about what you’d like to see covered in the future about containers. We’re excited to see more people in the C++ community start producing their own content about using C++ with containers. Despite the huge potential for C++ in the cloud with containers, there is very little material out there today.

If you could spare a few minutes to take our C++ cloud and container development survey, it will help us focus on topics that are important to you on the blog and in the form of product improvements.

As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems or have a suggestion for Visual Studio please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC).

 

 

Visual Studio 2019 Preview 2 Blog Rollup

$
0
0

Visual Studio 2019 Preview 2 was a huge release for us, so we’ve written a host of articles to explore the changes in more detail. For the short version, see the Visual Studio 2019 Preview 2 Release Notes.

We’d love for you to download Visual Studio 2019 Preview, give it a try, and let us know how it’s working for you in the comments below or via email (visualcpp@microsoft.com). If you encounter problems or have a suggestion, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion or via Visual Studio Developer Community. You can also find us on Twitter @VisualC.

Cppp 2019 Trip Report

$
0
0

Summary

CPPP is a new C++ conference in Paris, France. Its first iteration ran for a single day with three parallel tracks, drawing in 160 attendees.

The conference great on all fronts: the speakers & talks were varied and high-quality, the venue was right next to the Eiffel Tower and had plenty of space, the food was tasty and varied (shoutout to the cream filled pastries), and the day went smoothly with strong communication from the organisers (Joel Falcou and Fred Tingaud).

The three tracks were themed on roughly beginner, intermediate, and expert content, where the beginner track was in French and the other two were in English.

My Talk

C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\Content.MSO\9588AC77.tmp

Photo by @Winwardo

My talk was named “Tools to Ease Cross-Platform C++ Development”. I tried something a bit different from other cross-platform talks we’ve given, in that I tried to develop a cross-platform application live rather than demoing different features one-by-one.

I wrote a whole Brainfuck-to-x64 compiler in Visual Studio during the talk which targeted Windows and Linux (through the WSL configuration in VS) and used Vcpkg to fulfill a dependency on fmtlib. The compiler worked first time as well! You can find the code and slides on GitHub.

 

Talks I Attended

Kate Gregory – Emotional Code

C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\Content.MSO\4056049D.tmp

Photo by @branaby

After some pastries and an introduction from the organisers, we began with a keynote from Kate Gregory on Emotional Code. This was the third time I’d seen a version of this talk live (once at C++ on Sea and again at ACCUConf), but it was still very enjoyable this time round and had some new content to make it worthwhile.

As programmers, we can be under the belief that code is neutral and emotionless, but Kate argues that this is not the case, and that the code you write can reflect a lot about the environment in which you work. I find this talk illuminating each time I watch it, I’d recommend giving it a try and thinking about how your work situation can be improved to make your code better. Kate is also one of those speakers who I could watch talk about her teapot collection (I don’t know if she has a teapot collection) and not get bored, so if nothing else you’ll have a good way to pass an hour.

Mock Interviews

I gave my talk after Kate’s, after which I napped on a couch to recover somewhat before helping out with the mock interviews. I and some other experienced interviewers had a series of 20 min talks with people looking to improve their interview skills. This session wasn’t very well attended, but I think those who came found it very valuable. Having run a similar event at CppCon, I think these are wonderful opportunities for people to get in some practice before trying to get jobs, so I’d highly recommend looking out for them when you’re at an event.

Patricia Aas – Anatomy of an Exploit

C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\Content.MSO\7FE2DDB3.tmp

Photo by @a_bigillu

Patricia’s talks are always energetic and engaging, with beautiful slides and keen insights. This one was no different, even if I was exhausted by this point of the day and got told off for nodding off in the front row (sorry Patricia!).

This was an introduction into how code exploits work by breaking the program out of the world of normal behaviour and into the upside-down of The Weird, then how execution is controlled in this bizarre state. It’s is a great first step into the technical details of software vulnerabilities, so give it a watch if you’re interested in learning about this area.

Ben Deane – Identifying Monoids: Exploiting Compositional Structure in Code

C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\Content.MSO\88B21539.tmp

Photo by @hankadusikova

I was particularly interested in seeing this talk, since it’s essentially a one-hour answer to a question I asked Ben in one of his CppCon 2018 talks. I wasn’t disappointed.

The core of Ben’s presentation was that identifying monoids (a set along with a binary operation which is closed and associative, e.g. the set of integers under integer addition) in your types allows you to:

  1. Expose the underlying structures in your code
  2. Exploit these structures to make your types and operations more clear and composable

He took a very practical code-based approach, so the talk is very accessible for people who have found some of the mathematical underpinnings which he’s talking about difficult to understand.

Next Year

Next year it will run for two days and I expect a stronger turnout due to the success of its first run. I’d highly recommend going along and hope to see you there!

The post Cppp 2019 Trip Report appeared first on C++ Team Blog.

Simplify Your Code With Rocket Science: C++20’s Spaceship Operator

$
0
0

This post is part of a regular series of posts where the C++ product team here at Microsoft and other guests answer questions we have received from customers. The questions can be about anything C++ related: MSVC toolset, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc. Today’s post is by Cameron DaCamara.

C++20 adds a new operator, affectionately dubbed the “spaceship” operator: <=>. There was a post awhile back by our very own Simon Brand detailing some information regarding this new operator along with some conceptual information about what it is and does.  The goal of this post is to explore some concrete applications of this strange new operator and its associated counterpart, the operator== (yes it has been changed, for the better!), all while providing some guidelines for its use in everyday code.

Comparisons

It is not an uncommon thing to see code like the following:

struct IntWrapper {
  int value;
  constexpr IntWrapper(int value): value{value} { }
  bool operator==(const IntWrapper& rhs) const { return value == rhs.value; }
  bool operator!=(const IntWrapper& rhs) const { return !(*this == rhs);    }
  bool operator<(const IntWrapper& rhs)  const { return value < rhs.value;  }
  bool operator<=(const IntWrapper& rhs) const { return !(rhs < *this);     }
  bool operator>(const IntWrapper& rhs)  const { return rhs < *this;        }
  bool operator>=(const IntWrapper& rhs) const { return !(*this < rhs);     }
};

Note: eagle-eyed readers will notice this is actually even less verbose than it should be in pre-C++20 code because these functions should actually all be nonmember friends, more about that later.

That is a lot of boilerplate code to write just to make sure that my type is comparable to something of the same type. Well, OK, we deal with it for awhile. Then comes someone who writes this:

constexpr bool is_lt(const IntWrapper& a, const IntWrapper& b) {
  return a < b;
}
int main() {
  static_assert(is_lt(0, 1));
}

The first thing you will notice is that this program will not compile.


error C3615: constexpr function 'is_lt' cannot result in a constant expression

Ah! The problem is that we forgot constexpr on our comparison function, drat! So one goes and adds constexpr to all of the comparison operators. A few days later someone goes and adds a is_gt helper but notices all of the comparison operators do not have an exception specification and goes through the same tedious process of adding noexcept to each of the 5 overloads.

This is where C++20’s new spaceship operator steps in to help us out. Let’s see how the original IntWrapper can be written in a C++20 world:

#include <compare>
struct IntWrapper {
  int value;
  constexpr IntWrapper(int value): value{value} { }
  auto operator<=>(const IntWrapper&) const = default;
};

The first difference you may notice is the new inclusion of <compare>. The <compare> header is responsible for populating the compiler with all of the comparison category types necessary for the spaceship operator to return a type appropriate for our defaulted function. In the snippet above, the return type auto will be deduced to std::strong_ordering.

Not only did we remove 5 superfluous lines, but we don’t even have to define anything, the compiler does it for us! Our is_lt remains unchanged and just works while still being constexpr even though we didn’t explicitly specify that in our defaulted operator<=>. That’s well and good but some people may be scratching their heads as to why is_lt is allowed to still compile even though it does not even use the spaceship operator at all. Let’s explore the answer to this question.

Rewriting Expressions

In C++20, the compiler is introduced to a new concept referred to “rewritten” expressions. The spaceship operator, along with operator==, are among the first two candidates subject to rewritten expressions. For a more concrete example of expression rewriting, let us break down the example provided in is_lt.

During overload resolution the compiler is going to select from a set of viable candidates, all of which match the operator we are looking for. The candidate gathering process is changed very slightly for the case of relational and equivalency operations where the compiler must also gather special rewritten and synthesized candidates ([over.match.oper]/3.4).

For our expression a < b the standard states that we can search the type of a for an operator<=> or a namespace scope function operator<=> which accepts its type. So the compiler does and it finds that, in fact, a‘s type does contain IntWrapper::operator<=>. The compiler is then allowed to use that operator and rewrite the expression a < b as (a <=> b) < 0. That rewritten expression is then used as a candidate for normal overload resolution.

You may find yourself asking why this rewritten expression is valid and correct. The correctness of the expression actually stems from the semantics the spaceship operator provides. The <=> is a three-way comparison which implies that you get not just a binary result, but an ordering (in most cases) and if you have an ordering you can express that ordering in terms of any relational operations. A quick example, the expression 4 <=> 5 in C++20 will give you back the result std::strong_ordering::less. The std::strong_ordering::less result implies that 4 is not only different from 5 but it is strictly less than that value, this makes applying the operation (4 <=> 5) < 0 correct and exactly accurate to describe our result.

Using the information above the compiler can take any generalized relational operator (i.e. <, >, etc.) and rewrite it in terms of the spaceship operator. In the standard the rewritten expression is often referred to as (a <=> b) @ 0 where the @ represents any relational operation.

Synthesizing Expressions

Readers may have noticed the subtle mention of “synthesized” expressions above and they play a part in this operator rewriting process as well. Consider a different predicate function:

constexpr bool is_gt_42(const IntWrapper& a) {
  return 42 < a;
}

If we use our original definition for IntWrapper this code will not compile.

error C2677: binary '<': no global operator found which takes type 'const IntWrapper' (or there is no acceptable conversion)

This makes sense in pre-C++20 land, and the way to solve this problem would be to add some extra friend functions to IntWrapper which take a left-hand side of int. If you try to build that sample with a C++20 compiler and our C++20 definition of IntWrapper you might notice that it, again, “just works”—another head scratcher. Let’s examine why the code above is still allowed to compile in C++20.

During overload resolution the compiler will also gather what the standard refers to as “synthesized” candidates, or a rewritten expression with the order of the parameters reversed. In the example above the compiler will try to use the rewritten expression (42 <=> a) < 0 but it will find that there is no conversion from IntWrapper to int to satisfy the left-hand side so that rewritten expression is dropped. The compiler also conjures up the “synthesized” expression 0 < (a <=> 42) and finds that there is a conversion from int to IntWrapper through its converting constructor so this candidate is used.

The goal of the synthesized expressions are to avoid the mess of needing to write the boilerplate of friend functions to fill in gaps where your object could be converted from other types. Synthesized expressions are generalized to 0 @ (b <=> a).

More Complex Types

The compiler-generated spaceship operator doesn’t stop at single members of classes, it will generate a correct set of comparisons for all of the sub-objects within your types:

struct Basics {
  int i;
  char c;
  float f;
  double d;
  auto operator<=>(const Basics&) const = default;
};

struct Arrays {
  int ai[1];
  char ac[2];
  float af[3];
  double ad[2][2];
  auto operator<=>(const Arrays&) const = default;
};

struct Bases : Basics, Arrays {
  auto operator<=>(const Bases&) const = default;
};

int main() {
  constexpr Bases a = { { 0, 'c', 1.f, 1. },
                        { { 1 }, { 'a', 'b' }, { 1.f, 2.f, 3.f }, { { 1., 2. }, { 3., 4. } } } };
  constexpr Bases b = { { 0, 'c', 1.f, 1. },
                        { { 1 }, { 'a', 'b' }, { 1.f, 2.f, 3.f }, { { 1., 2. }, { 3., 4. } } } };
  static_assert(a == b);
  static_assert(!(a != b));
  static_assert(!(a < b));
  static_assert(a <= b);
  static_assert(!(a > b));
  static_assert(a >= b);
}

The compiler knows how to expand members of classes that are arrays into their lists of sub-objects and compare them recursively. Of course, if you wanted to write the bodies of these functions yourself you still get the benefit of the compiler rewriting expressions for you.

Looks Like a Duck, Swims Like a Duck, and Quacks Like operator==

Some very smart people on the standardization committee noticed that the spaceship operator will always perform a lexicographic comparison of elements no matter what. Unconditionally performing lexicographic comparisons can lead to inefficient generated code with the equality operator in particular.

The canonical example is comparing two strings. If you have the string "foobar" and you compare it to the string "foo" using == one would expect that operation to be nearly constant. The efficient string comparison algorithm is thus:

  • First compare the size of the two strings, if the sizes differ return false, otherwise
  • step through each element of the two strings in unison and compare until one differs or the end is reached, return the result.

Under spaceship operator rules we need to start with the deep comparison on each element first until we find the one that is different. In the our example of "foobar" and "foo" only when comparing 'b' to '\0' do you finally return false.

To combat this there was a paper, P1185R2 which details a way for the compiler to rewrite and generate operator== independently of the spaceship operator. Our IntWrapper could be written as follows:

#include <compare>
struct IntWrapper {
  int value;
  constexpr IntWrapper(int value): value{value} { }
  auto operator<=>(const IntWrapper&) const = default;
  bool operator==(const IntWrapper&) const = default;
};

Just one more step… however, there’s good news; you don’t actually need to write the code above, because simply writing auto operator<=>(const IntWrapper&) const = default is enough for the compiler to implicitly generate the separate—and more efficient—operator== for you!

The compiler applies a slightly altered “rewrite” rule specific to == and != wherein these operators are rewritten in terms of operator== and not operator<=>. This means that != also benefits from the optimization, too.

Old Code Won’t Break

At this point you might be thinking, OK if the compiler is allowed to perform this operator rewriting business what happens when I try to outsmart the compiler:

struct IntWrapper {
  int value;
  constexpr IntWrapper(int value): value{value} { }
  auto operator<=>(const IntWrapper&) const = default;
  bool operator<(const IntWrapper& rhs) const { return value < rhs.value; }
};
constexpr bool is_lt(const IntWrapper& a, const IntWrapper& b) {
  return a < b;
}

The answer here is, you didn’t. The overload resolution model in C++ has this arena where all of the candidates do battle, and in this specific battle we have 3 candidates:

    • IntWrapper::operator<(const IntWrapper& a, const IntWrapper& b)
    • IntWrapper::operator<=>(const IntWrapper& a, const IntWrapper& b)

(rewritten)

    • IntWrapper::operator<=>(const IntWrapper& b, const IntWrapper& a)

(synthesized)

If we accepted the overload resolution rules in C++17 the result of that call would have been ambiguous, but the C++20 overload resolution rules were changed to allow the compiler to resolve this situation to the most logical overload.

There is a phase of overload resolution where the compiler must perform a series tiebreakers. In C++20, there is a new tiebreaker that states we must prefer overloads that are not rewritten or synthesized, this makes our overload IntWrapper::operator< the best candidate and resolves the ambiguity. This same machinery prevents synthesized candidates from stomping on regular rewritten expressions.

Closing Thoughts

The spaceship operator is a welcomed addition to C++ and it is one of the features that will simplify and help you to write less code, and, sometimes, less is more. So buckle up with C++20’s spaceship operator!

We urge you to go out and try the spaceship operator, it’s available right now in Visual Studio 2019 under /std:c++latest! As a note, the changes introduced through P1185R2 will be available in Visual Studio 2019 version 16.2. Please keep in mind that the spaceship operator is part of C++20 and is subject to some changes up until such a time that C++20 is finalized.

As always, we welcome your feedback. Feel free to send any comments through e-mail at visualcpp@microsoft.com, through Twitter @visualc, or Facebook at Microsoft Visual Cpp. Also, feel free to follow me on Twitter @starfreakclone.

If you encounter other problems with MSVC in VS 2019 please let us know via the Report a Problem option, either from the installer or the Visual Studio IDE itself. For suggestions or bug reports, let us know through DevComm.

The post Simplify Your Code With Rocket Science: C++20’s Spaceship Operator appeared first on C++ Team Blog.

Clang/LLVM Support for MSBuild Projects

$
0
0

Visual Studio 2019 version 16.2 Preview 3 includes built-in Clang/LLVM support for MSBuild projects. In our last release, we announced support for Clang/LLVM for CMake. In the latest Preview of Visual Studio, we have extended that support to also include MSBuild projects. While in most cases we recommend using the MSVC compiler, we are committed to making Visual Studio one of the most comprehensive IDEs on Windows. You may want to use Clang instead if you are developing cross platform code, especially if it already depends on Clang or GCC extensions. You can now use Clang/LLVM to target both Windows and Linux using MSBuild just like you can with CMake projects. We’ve also updated our included version of Clang to 8.0.0. Please download the latest Preview to try it out and let us know how it works.

Installing the Clang Tools for Visual Studio

You can install the Clang tools for Windows by selecting “C++ Clang Tools for Windows” as part of the “Desktop development with C++” workload. It is not installed by default, but if you have installed it before, Clang will automatically be updated to 8.0.0 when you install the latest Preview.

Install the “C++ Clang tools for Windows” component with the “Desktop development with C++” workload.

If you want to use your own Clang compiler with Windows instead of the bundled one, you can do that too. Navigate to “Individual Components” and select “C++ Clang-cl for v142 build tools.” You will only be able to use recent versions of Clang (8.0.0 or later) with the Microsoft STL though. We strongly recommend using the bundled compiler as it will be kept up to date as the STL is updated.

Or just install the tooling with “C++ Clang-cl for v142 build tools” under “Individual Components.”

To use Clang with Linux projects, just install the “Linux development” workload. You won’t need to select any more components. The remote machine or WSL will need to have Clang installed. Just install Clang from your distribution’s package manager or from LLVM’s download page.

Use Clang with Windows MSBuild Projects

You can use Clang with most MSBuild projects that target Windows. To get started, create a new C++ project or open an existing one. Then, you can change the platform toolset to “LLVM (clang-cl)”:Select the “LLVM (clang-cl)” Platform Toolset under Configuration Properties > General.

If this toolset doesn’t appear, it likely isn’t installed – see above for installation instructions.

Visual Studio uses the clang-cl frontend with MSBuild on Windows so the properties for Clang will be the same as MSVC based projects. Some compiler options are not supported by clang-cl (e.g. Just My Code) and will be not be shown in the Property Pages when you are using Clang.

Use Clang with Linux MSBuild Projects

Using Clang with Linux projects is also as simple as selecting the appropriate platform toolset. For Linux projects, there are two toolsets to choose from. One for using Clang with a WSL instance on the local machine and another for using Clang on a remote machine:

For Linux projects, Visual Studio uses the Clang GCC-compatible frontend. The project properties and nearly all compiler flags are identical.

Custom Clang Installations and Compiler Arguments

You can also use a custom installation of Clang. On Windows, by default, the built-in version of Clang from the installer will always be used. On Linux, the first installation of Clang found on the PATH will be used. However, you can override this behavior on either platform by setting defining a property in your project file:

<LLVMInstallDir>PATH_TO_LLVM</LLVMInstallDir>

To do this, you will need to unload your project and edit it. You can add this to any project configurations that you would like to use your custom installation of Clang. Keep in mind, the Microsoft STL is only compatible with very recent versions of Clang: 8.0.0 as of this post.

If you need to use a Clang compile or link flag that isn’t supported by the project property pages, you can do that in the project properties under Configuration Properties > C/C++ or Linker > Command Line. Consider opening a feedback ticket if you find yourself using a particular option this way frequently. Based on demand, we may add it to the property pages.

Send us Feedback

Your feedback is a critical part of ensuring that we can deliver the best experience.  We would love to know how Visual Studio 2019 version 16.2 Preview 3 is working for you. If you find any issues or have a suggestion, the best way to reach out to us is to Report a Problem.

The post Clang/LLVM Support for MSBuild Projects appeared first on C++ Team Blog.

Vcpkg: 2019.06 Update

$
0
0

The 2019.06 update of vcpkg, a tool that helps you manage C and C++ libraries on Windows, Linux, and MacOS, is now available. This is the first time we’ve created a vcpkg release on our GitHub repository. This update is designed to bring you a summary of the new functionality and improvements made to vcpkg over about a month’s time. The 2019.06 update covers the month of June.

This release includes many new ports and triplet updates including overlay options, improvements for port contributors, and new documentation. For a full list of this release’s improvements, check out our release notes on GitHub.

Ports

There has been a substantial growth in vcpkg contributions over the past few months, with over 1,000 packages now available in the catalog. You can view the libraries available by either searching for a library name in the GitHub repo ports folder or using the vcpkg search command.

We added 44 new ports in the month of June. Some notable additions include: bdwgc, cJSON, greatest, immer, json-c, and zydis. These ports have 1K+ stars on their respective GitHub repos. You can view a full list of new ports in the [new ports section of our release notes]().

In addition to new ports, we updated 291 existing ports. A notable update to the release includes port ‘Homepages’.

Port Homepages

As part of our infrastructure work, you can now view the ‘Homepage’ for a port. This allows you to easily view a port’s official homepage via a link to the website. Let’s take the Abseil port for example. If you navigate to <vcpkg root>/ports/abseil/CONTROL, you will find the line “Homepage: https://github.com/abseil/abseil-cpp” which links to the official Abseil page.

Overlay Ports

The vcpkg command line interface allows you to easily search, install, and maintain your libraries. We added an –-overlay-ports option to allow you to override ports with alternate versions and create private ports.

Let’s look at an example where you are using OpenCV for your computer vision project. You would like to use vcpkg to acquire OpenCV and other packages. Your team is specifically using version 3.0 of OpenCV, but vcpkg offers version 3.4.3. Even though that version of OpenCV is not available in vcpkg, you can create a private port.

Let’s say you go ahead and create a private GitHub repo and check in the ports you want to preserve including OpenCV 3.0 and its specific dependent libraries that also may not be available in current vcpkg. You can then provide your team with the link to clone your private repo.

Locally, you create a custom ports directory and commit your changes:

~/vcpkg$ mkdir vcpkg-custom-ports
~/vcpkg$ cd vcpkg-custom-ports
~/vcpkg/vcpkg-custom-ports$ git init
~/vcpkg/vcpkg-custom-ports$ cp -r %VCPKG_ROOT%/ports/opencv .
~/vcpkg/vcpkg-custom-ports$ git add .
~/vcpkg/vcpkg-custom-ports$ git commit -m "[opencv] Add OpenCV 3.0 port"
~/vcpkg/vcpkg-custom-ports$ git remote add origin https://github.com/<My GitHub username>/vcpkg-custom-ports.git
~/vcpkg/vcpkg-custom-ports$ git push -u origin master

Now, you and your team can use version 3.0 of OpenCV for your projects with vcpkg using the following:

~/vcpkg/vcpkg-custom-ports$ git clone https://github.com/<My GitHub username>/vcpkg-custom-ports.git
~/vcpkg/vcpkg-custom-ports$ ./vcpkg update --overlay-ports=./vcpkg-custom-ports
~/vcpkg/vcpkg-custom-ports$ ./vcpkg upgrade --no-dry-run --overlay-ports=./vcpkg-custom-ports

Note that you may need to update vcpkg to use the most up-to-date command line options. You can update vcpkg on Windows via .\bootstrap-vcpkg.bat or on macOS /Linux via ./bootstrap-vcpkg.sh.

This allows you to upgrade your packages and preserve the older version of OpenCV that your project requires.

As shown in the example above, you can use --overlay-ports with the vcpkg installvcpkg updatevcpkg upgradevcpkg export, and vcpkg depend-info commands. Learn more in our overlay-ports documentation.

Note that while overlay ports can help with overriding port versions and creating private ports, this is part of our ongoing work to improve the usability of vcpkg when it comes to versioning. Stay tuned for a future post on best practices for versioning with vcpkg!

Triplets

Vcpkg provides many triplets (target environments) by default. This past month, we focused on increasing the number of ports available on Linux and creating port improvements for Linux and the Windows Subsystem for Linux (WSL). We now have 755 ports available for Linux and we updated over 150 ports for Linux and WSL.

Here is a current list of ports per triplet:

Triplet Ports Available
x64-osx 823
x64-linux 755
x64-windows 1006
x86-windows 977
x64-windows-static 895
arm64-windows 654
x64-uwp 532
arm-uwp 504

 

Don’t see a triplet you’d like? You can easily add your own triplets. Details on adding triplets can be found in our documentation.

Overlay Triplets

As part of our vcpkg command line updates, we also added an --overlay-triplets option. This option is especially helpful if you have custom triplet needs. You can use the option, similar to --overlay-ports, to override triplets with custom specifications and create custom triplets.

For example, a subset of Linux users require fully dynamic libraries, whereas the x64-linux triplet only builds static libraries. A custom triplet file based on the x64-linux triplet can be created to build dynamic libraries. To solve this problem:

First, create a folder to contain your custom triplets:

~/vcpkg$ mkdir ../custom-triplets

Then, create the custom triplet file:

~/vcpkg$ cp ./triplets/x64-linux.cmake ../custom-triplets/x64-linux-dynamic.cmake

And modify the custom-triplets/x64-linux-dynamic.cmake file to:

set(VCPKG_TARGET_ARCHITECTURE x64) 
set(VCPKG_CRT_LINKAGE dynamic) 
set(VCPKG_LIBRARY_LINKAGE dynamic) 
set(VCPKG_CMAKE_SYSTEM_NAME Linux)

* Note the change of VCPKG_LIBRARY_LINKAGE from static to dynamic.

Finally, use your custom triplet by passing the --overlay-triplets option:

~/vcpkg$ vcpkg install opencv:x64-linux-dynamic --overlay-triplets=../custom-triplets

Improvements for Port Contributors

We also made improvements to the vcpkg infrastructure including a public CI system, check features, and a ‘Homepage’ field for ports.

CI System

We now have public CI tests through Azure DevOps pipelines which are run for all PRs to the vcpkg GitHub repo. The CI system allows contributors to get direct, automatic access to failure logs for PRs on Linux, Windows, and Mac within minutes. For example:

PR with passing and failing checksGitHub badge with passing and failing checks

The checks will still include badges to indicate pass/fail as shown by the ‘x’ or ‘check mark’.

And if a check fails, you can now drill into the details:

PR check details in Azure DevOps

Going further into Azure DevOps, you can get more information in the Summary tab such as downloading a zip file of all the failure logs along with a quick description of relevant changes:

Failed check details in Summary page of Azure DevOps

We hope the new CI system will improve your experience submitting PRs to vcpkg!

Check Features

Vcpkg_check_features is a new portfile function that checks if one or more features are a part of a package installation. In vcpkg we use features to enable optional capabilities offered by libraries. A user requests vcpkg to install. For example:

~/vcpkg$ vcpkg install opencv[cuda]

The install command enables the optional CUDA support for OpenCV.

Vcpkg_check_featuressimplifies the portfile creation process for vcpkg contributors by shortening the syntax needed in the CMake portfile script. Previously, you needed to specify which features are included in the port:

if(<feature> IN_LIST FEATURES)
   set(<var> ON)else()&nbsp;&nbsp; 
   set(<var> OFF)
endif()

Now, you can simply write the following:

vcpkg_check_features(<feature> <output_variable>)

Learn more about using vcpkg_check_features in your portfiles in the vcpkg_check_features documentation.

‘Homepage’ Field for Ports

We also added an optional ‘Homepage’ field to CONTROL. This means that CONTROL files may now contain a ‘Homepage’ field which links to the port’s official website. The Homepage field is designed to help you more easily find the origin/location of the ports you are using.

Documentation

We also updated our documentation to reflect these new changes. Check out the following new docs for more information on some of the updates outlined in this post in addition to a couple other areas:

Thank you

Thank you to everyone who created vcpkg! We now have 639 total contributors. This release, we’d like to thank the following 24 contributors who made code changes in June:

cenit martinmoene
coryan martin-s
driver1998 mloskot
eao197 myd7349
evpobr Neumann-A
Farwaykorse past-due
hkaiser pravic
jasjuang SuperWig
josuegomes tarcila
jumpinjackie TartanLlama
lebdron ThadHouse
MarkIanHolland UnaNancyOwen

 

Tell Us What You Think

Install vcpkg, give it a try, and let us know what you think. If you run into any issues, or have any suggestions, please report them on the Issues section of our GitHub repository.

We can be reached via the comments below or via email (vcpkg@microsoft.com). You can also find our team – and me – on Twitter @VisualC and @tara_msft.

The post Vcpkg: 2019.06 Update appeared first on C++ Team Blog.


Inlining Decisions in Visual Studio

$
0
0

Introduction

My name is Terry Mahaffey and I work on the code generation team in MSVC. Lately I’ve been doing some work on our inliner and I wanted to give a brief introduction to it before later diving into some of the changes we’ll be shipping.

Inlining is perhaps the most important optimization a compiler performs. In addition to removing call overhead, an inline decision is most useful when it exposes additional optimization opportunities not present in either the caller or callee by themselves. For example:

int bar(int x) {
    int y = 1;
    while(--x) {
        y = y * 2;
    }
    return y;
}

int foo() {
    return bar(5);
}

It is a really good idea to inline bar into foo in this example; once that is done the compiler is able to evaluate the entire function, and the final code generation of foo will directly return 16.

Contrast that with this example:

int bar(int x) {
    int y = 1;
    while(--x) {
        y = y * 2;
    }
    return y;
}

int foo(int x) {
    return bar(x);
}

int baz(int y) {
    return bar(y);
}

int zoo(int z) {
    return bar(z);
}

Here it is less clear that inlining bar into foo, baz, and zoo is a win. Because the parameter passed in is not constant, the compiler won’t be able to figure out the final value in each case at compile time. Inlining does avoid the call overhead, but that must be weighed against the fact that the body of bar will appear at least 4 times in the final program increasing code size and hurting cache locality.

The goal of a good inliner is therefore to estimate the “benefit” from inlining at a call site and weigh it against the “cost” (typically measured in code growth). In addition, in MSVC we have a notion of a global budget where we’ll stop inlining regardless of additional benefit to prevent code growth explosion.

In Visual Studio we have been working on expanding the capability of our inliner to both be smarter about what we inline (be able to realize there are benefits in places we didn’t before) and more aggressive (raising the inlining budget, lowering the threshold). We’ll have more to say in upcoming blog posts. But for now, I wanted to give some context to our inliner in MSVC and what makes it different from inliners in other compilers.

We inline pre-optimized code

In contrast to other compilers, when MSVC inlines a call it actually inlines pre-optimized code by reading in the original unoptimized version of the function for that callee again, even though the callee usually has been compiled and optimized by this point. This also means that it makes (and repeats) inline decisions in each context a function might be called in, perhaps leading to different results. For example, consider a function f which calls g which calls h, where h is inlined into g. If g is inlined into f, h will not necessarily be inlined into f as well. A compiler which inlines post-optimized code (here, a version of g which already has h inlined into it) implicitly “replay” inline decisions made for callees.

We feel this is a strength, as it might not necessarily be best to replay the same inline decisions in each context. However, this has a big compile-time cost as frequently the same inline decisions are made and the same code is optimized over again. We’re currently exploring a middle option where we can replay some of the obvious post-optimized versions of functions.

We inline first

Inlining is the first optimization done by the compiler. So not only is the compiler inlining pre-optimized versions of callees, it is also inlining into a pre-optimized version of the caller. One consequence is it currently doesn’t realize there are some obvious optimization opportunities. Revisiting the first example the compiler does great at realizing bar should be inlined into foo, but if foo were changed to look like this:

int bar(int x) {
    int y = 1;
    while(--x) {
        y = y * 2;
    }
    return y;
}

int foo() {
    int x = 5;
    return bar(x+1);
}

The MSVC inliner would currently consider “x+1” as a non-constant parameter, and not apply a bonus inside the inline heuristic based on the parameter usage in bar.

Another consequence is that indirect and virtual calls which could have been converted to direct calls via constant propagation haven’t been optimized to do so yet, so we do not inline through them. So frequently you’ll see an indirect call to a small function converted to a direct call and emitted in the final binary as such, leaving the programmer to wonder why the compiler missed such an obviously good inlining opportunity. It’s an ordering issue; sometimes the optimizer performs the optimizations the inliner needs after the inliner has already run.

These are also issues we’d like to address in the near future by performing a limited set of optimizations before or during inlining.

A word about our implementation

The MSVC inliner, at a high level, looks like this:

  1. Identify all inline candidates (first set of legality checks)
  2. For each candidate,
    1. Read the body of the candidate, run a second series of legality checks
    2. Run a series of inlining heuristics
    3. If it looks like a good inline candidate, recursively inline into the candidate
    4. Run a final series of legality checks

First, note that it is a “depth first” inliner. Moving towards a breadth first approach is an area that is on the roadmap to explore in the future. There are advantages and disadvantages to each approach.

These legality checks and heuristics are a set of tables of function pointers we iterate over. If any legality check fails, inlining is aborted for that candidate. If any heuristic check succeeds, inlining moves forward.
The three legality steps occur first based on only what we know about the potential inlinee before reading it in, second after it has read in the inlinee, and finally after we’re recursively expanded into the callee.

Legality checks tend to speak to limitations in the inliner, typically corner cases which were never implemented. Things like arguments with complex user types passed by value, inlining across different user defined parts of a binary, inlining functions with try blocks, inlining functions with setjmp, a inlining depth check where we have a hard limit on how deep we inline, etc.

The heuristics are not all created equal. There is one heuristic in particular called “callgraph decision” which is what I consider the “real” inline decision maker. It is where all of the benefit estimating code around constant parameters described above is implemented. A call graph decision depends on bottom up compilation order, because certain information is gathered about the callee during it’s compilation (such as its use of its parameters) which is then used during inlining. There are other simple heuristics such as the inlinee being a forceinline function, a very small function, and a “simple decision” heuristic for cases where a call graph decision can’t be made.

This framework is flexible and easy to understand. Adding a new legality check or heuristic is as simple as adding an entry into a table. Profile Guided Optimization, or PGO, utilizes its own inlining decision engine based on profiling data, and it implements this simply by having its own entry in the table. Similarly, for instrumented builds PGO prefers no inlining occur to help gather the most accurate set of counts possible. PGO implements turning off inlining for instrumented builds by a simple legality check which always says “no”.

If you want to see this in action, run your build with the /d2inlinestats switch. This will print out a table of what legality checks failed and how often, as well as what heuristics are driving the successful inline instances.

Conclusion

I hope you found this helpful. Over the next few months I plan on writing a few more blog posts to give some pointers on how to open up the hood even more and get more visibility into what specifically is happening with our inliner, as well as talk about features we have in development to address some of the problems. And if there are any inlining topics you’d like to see addressed, please leave a message in the comments below!

We’d love for you to download Visual Studio 2019 and give it a try. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter problems with Visual Studio or MSVC, or have a suggestion for us, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

The post Inlining Decisions in Visual Studio appeared first on C++ Team Blog.

Visual Studio Code C/C++ Extension: July 2019 Update

$
0
0

The July 2019 update of the Visual Studio Code C/C++ extension is now available. This release includes many new features, including semantic colorization and improvements to the IntelliSense Configuration Settings Editor UI and IntelliSense cache. For a full list of this release’s improvements, check out our release notes on GitHub.

Semantic Colorization

Semantic colorization support has been one of the top asks on our GitHub repo for the past few years. We faced many challenges in creating support for semantic colorization for the C/C++ extension since there is no VS Code API for semantic source highlighting and no support for semantic colorization in the VS Code language server protocol. We also can’t access a theme’s colors programmatically, so this support was even more challenging to make possible. Luckily, we were able to devise a way to overcome these challenges by managing our own set of tokens and their ranges, using TextEditorDecorations, and directly parsing theme files and VS Code settings to determine which colors to apply. With that, we are excited to share semantic colorization support!

GitHub issue for semantic colorization with 108 upvotes since September 2016

Semantic colorization support provides colorization to tokens even when they are out of context, thus providing colorization beyond that of syntax. For example, if you use a variable name outside of the place in which the variable is declared, you will see colorization:

Box coloring in right side of screenshot where it is outside variable declaration

In the above example, we see our struct is now colorized when it is defined as ‘box’ and when it is used in our main function.

Themes

The colors can be mapped using the existing support for theming and color customization in VS Code. Documentation on Theming in VS Code can be found here. Colors are associated with TextMate scopes. You can read more about the C/C++ extension IntelliSense tokens and scopes in our colorization documentation.

Many of the tokens recognized by IntelliSense do not directly map to existing scopes in VS Code’s default C/C++ TextMate grammar, so those will not be colored by existing VS Code themes. You can customize your color settings in Visual Studio Code, however. There are two ways in which you can do this – via global settings or on a per-theme basis. Theme authors can also make use of these scopes when creating a new color theme.

Customize Colors in Global Setting

In your settings.json file you can customize the colors for all themes by overriding the tokenColorCustomizations setting:

"editor.tokenColorCustomizations": {
        "textMateRules": [
            {
                "scope": "entity.name.type",
                "settings": {
                    "foreground": "#FF0000",
                    "fontStyle": "italic bold underline"
                }
            }
        ]
    }

Customize Colors for a Theme

You can also customize colors on a per-theme basis. In this example, we override the Visual Studio Dark theme settings:

"editor.tokenColorCustomizations": {
        "[Visual Studio Dark]": {
            "textMateRules": [
                {
                    "scope": "entity.name.type",
                    "settings": {
                        "foreground": "#FF0000",
                        "fontStyle": "italic bold underline"
                    }
                }
            ]    
        }

 

We created templates to customize Visual Studio Dark and Visual Studio Light themes in our documentation for easier colorization customization.

IntelliSense Configuration settings editor UI

The goal of the settings editor UI is to provide an alternative interface to the c_cpp_properties.json file for configuring IntelliSense for the C/C++ extension. The interface is simple and clear, and thus makes IntelliSense configuration easier to understand. Based on your feedback, we made a few improvements to the IntelliSense Configuration settings editor UI.

Select, Edit, and Add Configurations

There are a variety of reasons you may benefit from multiple IntelliSense configurations. For example, you may be using debug and release builds. In this case, having IntelliSense configured for debugging and release can improve your editing experience when switching between build types. To more easily get started with multiple configurations, we added an option to select the configuration you’d like to work with:

Select a configuration

Further, you can edit the settings of the selected configuration:

Edit selected configuration

Finally, you can add configurations via the settings editor UI:

Add a configuration

select and edit the newly added configuration

List of Detected Compiler Paths

You can also now see a list of detected compiler paths in the UI under the “compiler path” dropdown text field.

Select from compiler path list

We hope these improvements to the IntelliSense Configuration settings editor UI will help you more easily configure IntelliSense with the C/C++ extension.

IntelliSense Cache

We introduced IntelliSense Caching in the C/C++ extension March 2019 update. The purpose of it is to cache header information to improve IntelliSense speed. We received a lot of feedback on the default size for IntelliSense caching via an issue filed in our GitHub repo. After a productive conversation, we devised a proposal for changes to the default path. We have improved this feature in the July 2019 update.

The Default Path

Previously, the default path for the IntelliSense cache was in the “.vscode” folder of the project workspace (${workspaceFolder}/.vscode). Changing the default path enables us to address concerns of the cache on source control for the workspace folder. Furthermore, since the cache size limit is applied to a cache location, having one location reduces the overall disk space usage of the cache.

Now, the default for the C_Cpp.intelliSenseCachePath setting is “~/.vscode-cpptools” on Linux and macOS and “%LocalAppData%/Microsoft/vscode-cpptools” on Windows.

Note, the extension will automatically remove any caches previously added to the ${workspaceFolder}/.vscode folder if you were using the old IntelliSense cache path default.

Tell Us What You Think

Download the C/C++ extension for Visual Studio Code, give it a try, and let us know what you think. If you run into any issues, or have any suggestions, please report them on the Issues section of our GitHub repository. Set the C_CppProperties.UpdateChannel in your Visual Studio Code settings to “Insiders” to get early builds of our extension.

We can be reached via the comments below or via email (visualcpp@microsoft.com). You can also find our team – and me – on Twitter (@VisualC or @tara_msft).

The post Visual Studio Code C/C++ Extension: July 2019 Update appeared first on C++ Team Blog.

Improved Linker Fundamentals in Visual Studio 2019

$
0
0

On the C++ team we’ve heard loud and clear from users that build times are a pain point. So we’ve continued our focus on improving the step, linking, that dominates F5 build times. Fast F5 build times, or iteration build times, are a key contributor to developer productivity and we felt that there was a large opportunity so we narrowed in on changes that we felt could move the needle 2x or more.  This is on top of the significant improvements we made to the tool chain to speed up link times in the VS 2019 16.0 release.   Let me give a teaser of the kinds of wins we were able to achieve.

Unreal Engine 4 Infiltrator demo link times.

 

This shows a 3.5X win in 16.2 vs. 15.9 for a /debug:full build of the release configuration of the UE4 infiltrator demo and a 1.6X win using /debug:fastlink.  This is a middle of the road win given the other workloads we measured.  The fastlink win in particular was a little weak.  So what did we do?  We went back to basics.

What did we do: Improved Fundamentals

Link.exe is responsible for combining a disparate and large set of data into the executable and PDB and is fundamentally a serial process (mostly). After our changes in VS2019 16.0 to reduce the size of the debug input, as well as improvements to our type hashing strategy, we went back to basics and improved our core data structure and algorithm implementations.  With this change all our internal data structures have been updated to give better cache performance and memory utilization, as well as implement aggressive memoization of intermediate data to eliminate redundant computation.  These changes are at the base of the linker and the entire C++ ecosystem and, happily, show wins across nearly all the scenarios we track.  Do you use /debug:full? It’s faster. Do you use /debug:fastlink? It’s faster too.  Additionally, recompile scenarios that use link /incremental also follow the trend and are faster as well.

A key objective with these changes, as with any changes we make to the MSVC toolset, was to maintain compatibility.  All of the changes we made preserved interoperability so if you have an older library or PDB that is binary compatible with VS everything will continue to work.

Show me the numbers

One of our key outcomes we wanted from this effort was to improve iteration build times for our largest inputs.  These typically are large dlls or exes that combine a large number of objs with static libs and other components. There are a lot of places where project sizes get big, but there were two main areas where we found good examples to analyze and improve.

Open Source Projects

There are several large OSS projects that we track for general correctness representative of long link times.  For each of the workloads below we looked through the builds and found the link command that took the most time, and then created a link repro for it. To model the single obj rebuild and link time each of these link repros were then run in isolation. The times below are for each of the individual link repros and show the comparison between VS 2017 15.9 and VS 2019 16.2 Preview 2 “all up”.  Note: the tables are split out into one for Debug time as well as one for Release with debug info time, also a description of /debug:fastlink is available on the VC blog.

Debug iteration builds time for Chrome.dll, clang.exe, mongod.exe mysqld.exe and UE4Game.exe

Release iteration builds time for chrome.dll, clang.exe, mongod.exe, mysqld.exe, and UE4Game.exe

These are the links to the source of the workloads we used in the above experiments.

  • Chrome (commit 2a88e68bd7498b185675098bcd0addf2c7b7808 ) * this is an older time stamp that still builds with MSVC.
  • Clang
  • MongoDB
  • MySQL
  • UE4Game (requires github signin and approval)

AAA Games

Many AAA games are great examples of large monolithic exes, and because we worked closely with some of the game studios working on AAA titles for Xbox One we can show numbers – but with the names removed.  “Beta” and “Charlie” are large games that showed long link times and are representative of large production C++ source bases.  These were some of our most challenging linker inputs.

 

AAA games /debug:full link times for large inhouse games.

As you can see from the graph the improvements can scale with the size of the input.  This can change depending on project specifics but we see this general trend across all the data.

Here’s the Summary

We did a major renovation and cleanup of the component that is the dominant part of the iteration build time.  These changes show wins in the 2X range for /debug:fastlink and /incremental, while /debug:full is typically 3X-6X and up.  (We’ve seen 10X wins on some workloads). These wins will show up in a wide variety of workloads and are fully compatible with other binaries produced by MSVC.

Is there any more?

Link times still dominate F5 and we’re still looking for ways to speed this up.  At this point we think that a lot of the low hanging fruit is plucked so we are focusing on how the toolchain as a whole manages intermediate build products and debug info.  So stay tuned for more.

Take it for a test drive

We’d love for you to download Visual Studio 2019 16.2 and give it a try. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter problems with Visual Studio or MSVC, or have a suggestion for us, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

 

The post Improved Linker Fundamentals in Visual Studio 2019 appeared first on C++ Team Blog.

MSVC Backend Updates in Visual Studio 2019 version 16.2

$
0
0

In Visual Studio 2019 version 16.2 we continue to improve the C++ backend with build throughput improvements and new and improved optimizations. These build on top of our MSVC backend improvements in Visual Studio 2019 version 16.0 which we previously announced. We will be following up on many of the improvements here with their own blog posts.

Build Throughput Improvements

  • Linker improvements speeding up iteration build times with debug info by 3x (or more) on large projects. (Numbers shown are for the Unreal Engine shipping configuration)

Graph showing 3.5x speedup over 15.9 on /debug:full and 1.6x speedup on /debug:fast

  • Link times also improved under /INCREMENTAL by 2x.

New and Improved Optimizations

Inliner Improvements
  • Small functions will be inlined more if it has a branch in it and is called from a branch in a loop.
Improved Code Generation and Optimization of Intrinsics
  • Removed the overhead of some common mathematical functions (
    std::isnan
    ,
    std::ldiv
    ,
    std::lldiv
    ) by replacing the function calls with inline assembly instructions.
  • For x86/x64 targets the optimizer will recognize some vector intrinsics working only on the lowest element and do optimizations on them including building FMA (fused multiply-add) and doing constant folding.
Vectorizer Improvements
  • Tiny reduction loops (smaller than 12 iterations) will be vectorized for
    /arch:AVX
      and up if the elements perfectly fit the vector size.
  • Improved the code sequence generated for loops with a pointer induction variable when the auto vectorization attempt on these loops fails.
New Analysis Passes
  • Improved analysis of control flow to remove more complicated instances of branches that are provably true/false.
  • Added a new flow-sensitive restrict pointer analysis. A restrict pointer will be handled differently in regions where it can escape, i.e. be accessed outside of the current scope, than regions where it is safe to use as “restrict” pointer.
General Optimizer Improvements
  • Enable copy elision in functions where multiple objects are returned by value.
  • Improved optimization of pointer subtractions when using LTCG compilation. A pointer subtraction includes a division, which can now be optimized away in certain cases.
  • Improved optimizations to generate and simplify FMA instructions for x86/x64 platforms. This includes enabling FMA for global variables with vector type.
  • Improved code generation for C++20’s spaceship operator, which is available under
    /std:c++latest
     : better constant propagation of known values used in comparisons (e.g.
    std::strong_ordering::less
     ), and compile-time computation of constant assembly instruction results.
  • Improved memset code generation by calling the faster CRT version where appropriate instead of expanding its definition inline. Loops that store a constant value that is formed of the same byte (e.g. 0xABABABAB) now also use the CRT version of memset.
  • Improved optimization to merge identical exception handling states, saving size for C++ programs. Note: This only works under FrameHandler4, which will become the default in Visual Studio 2019 version 16.3.

We’d love for you to download Visual Studio 2019 and give it a try. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter problems with Visual Studio or MSVC, or have a suggestion for us, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

 

The post MSVC Backend Updates in Visual Studio 2019 version 16.2 appeared first on C++ Team Blog.

Smarter Member List Filtering for C++ 

$
0
0

We are always looking for ways to make you more productive while coding in Visual Studio. In Visual Studio 2019 version 16.2, we have created a smarter, more relevant Member List. Specifically, we now apply method filtering based on type qualifiers. To illustrate this, consider the following example: 

You have two vectors, but one is constWhen we invoke the member list on the non-const vector, we see the option for push_back. However, when we invoke the member list on the const vector, Visual Studio now knows not to display any non-const members on a const object: 

 

Even More Filtering 

If you wish to benefit further from Member List and completion filtering, try out Predictive IntelliSense. As an experimental feature, Predictive IntelliSense is disabled by default, but can be enabled under Tools > Options > Text Editor > C/C++ > Experimental. Or simply type “predictive” in the (Ctrl + Q) Search Bar. Currently, Predictive IntelliSense filters by type when you’re in an argument or assignment position. In the example below, i is of type int, so Predictive IntelliSense only shows int items in the completion list. 

Note: If you ever wish to unfilter the completion list, just click the green “+” symbol in the bottom left of the list. 

Talk to Us!  

If you have feedback on Member List filtering in Visual Studio, we would love to hear from you. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems with Visual Studio or MSVC or have a suggestion, you can use the Report a Problem tool in Visual Studio or head over to Visual Studio Developer Community. You can also find us on Twitter @VisualC and follow me @nickuhlenhuth.  

 

The post Smarter Member List Filtering for C++  appeared first on C++ Team Blog.

Viewing all 1541 articles
Browse latest View live


Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>