Skip to content

Commit 867643d

Browse files
authored
Merge branch 'master' into mb-ide
2 parents 1f61f05 + ee7e4f3 commit 867643d

File tree

1 file changed

+238
-1
lines changed

1 file changed

+238
-1
lines changed

docs/cpp-conformance-improvements-2017.md

Lines changed: 238 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ translation.priority.ht:
2929
---
3030

3131
# C++ conformance improvements in [!INCLUDE[vs_dev15_md](misc/includes/vs_dev15_md.md)]
32-
32+
For improvements in Update Version 15.3, see [Bug fixes in Visual Studio Update Version 15.3](#update_153).
3333
## New language features
3434
With support for generalized constexpr and NSDMI for aggregates, the compiler is now complete for features added in the C++14 Standard. Note that the compiler still lacks a few features from the C++11 and C++98 Standards. See [Visual C++ Language Conformance](visual-cpp-language-conformance.md) for a table that shows the current state of the compiler.
3535

@@ -349,5 +349,242 @@ void f(ClassLibrary1::Class1 ^r1, ClassLibrary1::Class2 ^r2)
349349
}
350350
```
351351

352+
## <a name="update_153"></a> Visual Studio 2017 Update Version 15.3
353+
### Calls to deleted member templates
354+
In previous versions of Visual Studio, the compiler in some cases would fail to emit an error for ill-formed calls to a deleted member template which would’ve potentially caused crashes at runtime. The following code now produces C2280, "'int S<int>::f<int>(void)': attempting to reference a deleted function":
355+
```cpp
356+
template<typename T>
357+
struct S {
358+
template<typename U> static int f() = delete;
359+
};
360+
361+
void g()
362+
{
363+
decltype(S<int>::f<int>()) i; // this should fail
364+
}
365+
```
366+
To fix the error, declare i as `int`.
367+
368+
### Pre-condition checks for type traits
369+
Visual Studio 2017 Update Version 15.3 improves pre-condition checks for type-traits to more strictly follow the standard. One such check is for assignable. The following code produces C2139 in Update Version 15.3:
370+
371+
```cpp
372+
struct S;
373+
enum E;
374+
375+
static_assert(!__is_assignable(S, S), "fail"); // this is allowed in VS2017 RTM, but should fail
376+
static_assert(__is_convertible_to(E, E), "fail"); // this is allowed in VS2017 RTM, but should fail
377+
```
378+
379+
### New compiler warning and runtime checks on native-to-managed marshaling
380+
Calling from managed functions to native functions requires marshalling. The CLR performs the marshaling but it doesn't understand C++ semantics. If you pass a native object by value, CLR will either call the object's copy-constructor or use BitBlt, which may cause undefined behavior at runtime.
381+
382+
Now the compiler will emit a warning if it can know at compile time that a native object with deleted copy ctor is passed between native and managed boundary by value. For those cases in which the compiler doesn't know at compile time, it will inject a runtime check so that the program will call std::terminate immediately when an ill-formed marshalling occurs. In Update Version 15.3, the following code produces C4606 "
383+
'A': passing argument by value across native and managed boundary requires valid copy constructor. Otherwise the runtime behavior is undefined".
384+
```cpp
385+
class A
386+
{
387+
public:
388+
A() : p_(new int) {}
389+
~A() { delete p_; }
390+
391+
A(A const &) = delete;
392+
A(A &&rhs) {
393+
p_ = rhs.p_;
394+
}
395+
396+
private:
397+
int *p_;
398+
};
399+
400+
#pragma unmanaged
401+
402+
void f(A a)
403+
{
404+
}
405+
406+
#pragma managed
407+
408+
int main()
409+
{
410+
f(A()); // This call from managed to native requires marshalling. The CLR doesn't understand C++ and uses BitBlt, which will result in a double-free later.
411+
}
412+
```
413+
To fix the error, remove the `#pragma managed` directive to mark the caller as native and avoid marshalling.
414+
415+
### Experimental API warning for WinRT
416+
WinRT APIs that are released for experimentation and feedback will be decorated with `Windows.Foundation.Metadata.ExperimentalAttribute`. In Update Version 15.3, the compiler will produce warning C4698 when it encounters the attribute. A few APIs in previous versions of the Windows SDK have already been decorated with the attribute, and calls to these APIs will start triggering this compiler warning. Newer Windows SDKs will have the attribute removed from all shipped types, but if you are using an older SDK, you'll need to suppress these warnings for all calls to shipped types.
417+
The following code produces warning C4698: "'Windows::Storage::IApplicationDataStatics2::GetForUserAsync' is for evaluation purposes only and is subject to change or removal in future updates":
418+
```cpp
419+
Windows::Storage::IApplicationDataStatics2::GetForUserAsync()
420+
```
421+
422+
To disable the warning, add a #pragma:
423+
424+
```cpp
425+
#pragma warning(push)
426+
#pragma warning(disable:4698)
427+
428+
Windows::Storage::IApplicationDataStatics2::GetForUserAsync()
429+
430+
#pragma warning(pop)
431+
```
432+
### Out-of-line definition of a template member function
433+
Update Version 15.3 produces an error when it encounters an out-of-line definition of a template member function that was not declared in the class. The following code now produces error C2039: 'f': is not a member of 'S':
434+
435+
```cpp
436+
struct S {};
437+
438+
template <typename T>
439+
void S::f(T t) {}
440+
```
441+
442+
To fix the error, add a declaration to the class:
443+
444+
```cpp
445+
struct S {
446+
template <typename T>
447+
void f(T t);
448+
};
449+
template <typename T>
450+
void S::f(T t) {}
451+
```
452+
453+
### Attempting to take the address of "this" pointer
454+
In C++ 'this' is an prvalue of type pointer to X. You cannot take the address of 'this' or bind it to an lvalue reference. In previous versions of Visual Studio, the compiler would allow you to circumvent this restriction by performing a cast. In Update Version 15.3, the compiler produces error C2664.
455+
456+
### Conversion to an inaccessible base class
457+
Update Version 15.3 produces an error when you attempt to convert a type to a base class which is inaccessible. The compiler now raises
458+
"error C2243: 'type cast': conversion from 'D *' to 'B *' exists, but is inaccessible". The following code is ill-formed and can potentially cause a crash at runtime. The compiler now produces C2243 when it encounters code like this:
459+
460+
```cpp
461+
#include <memory>
462+
463+
class B { };
464+
class D : B { }; // should be public B { };
465+
466+
void f()
467+
{
468+
std::unique_ptr<B>(new D());
469+
}
470+
```
471+
### Default arguments are not allowed on out of line definitions of member functions
472+
Default arguments are not allowed on out-of-line definitions of member functions in template classes. The compiler will issue a warning under /permissive, and a hard error under /permissive-
473+
In previous versions of Visual Studio, the following ill-formed code could potentially cause a runtime crash. Update Version 15.3 produces warning C5034: 'A<T>::f': an out-of-line definition of a member of a class template cannot have default arguments:
474+
```cpp
475+
476+
template <typename T>
477+
struct A {
478+
T f(T t, bool b = false);
479+
};
480+
481+
template <typename T>
482+
T A<T>::f(T t, bool b = false)
483+
{
484+
...
485+
}
486+
```
487+
To fix the error, remove the "= false" default argument.
488+
489+
### Use of offsetof with compound member designator
490+
In Update Version 15.3, using offsetof(T, m) where m is a "compound member designator" will result in a warning when you compile with the /Wall option. The following code is ill-formed and could potentially cause crash at runtime. Update Version 15.3 produces "warning C4841: non-standard extension used: compound member designator in offseto":
491+
492+
```cpp
493+
494+
struct A {
495+
int arr[10];
496+
};
497+
498+
// warning C4841: non-standard extension used: compound member designator in offsetof
499+
constexpr auto off = offsetof(A, arr[2]);
500+
```
501+
To fix the code, either disable the warning with a pragma or change the code to not use offsetof:
502+
503+
```cpp
504+
#pragma warning(push)
505+
#pragma warning(disable: 4841)
506+
constexpr auto off = offsetof(A, arr[2]);
507+
#pragma warning(pop)
508+
```
509+
510+
### Using offsetof with static data member or member function
511+
In Update Version 15.3, using offsetof(T, m) where m refers to a static data member or a member function will result in an error. The following code produces "error C4597: undefined behavior: offsetof applied to member function 'foo'" and "error C4597: undefined behavior: offsetof applied to static data member 'bar'":
512+
```cpp
513+
514+
#include <cstddef>
515+
516+
struct A {
517+
int foo() { return 10; }
518+
static constexpr int bar = 0;
519+
};
520+
521+
constexpr auto off = offsetof(A, foo);
522+
Constexpr auto off2 = offsetof(A, bar);
523+
```
524+
525+
This code is ill-formed and could potentially cause crash at runtime. To fix the error, change the code to no longer invoke undefined behavior. This is non-portable code that is disallowed by the C++ standard.
526+
527+
### New warning on declspec attributes
528+
In Update Version 15.3, the compiler no longer ignores attributes if __declspec(…) is applied before extern "C" linkage specification. Previously, the compiler would ignore the attritbute, which could have runtime implications. When the `/Wall /WX` option is set, the following code produces "warning C4768: __declspec attributes before linkage specification are ignored":
529+
530+
```cpp
531+
532+
__declspec(noinline) extern "C" HRESULT __stdcall
533+
```
534+
535+
To fix the warning, put extern "C" first:
536+
537+
```cpp
538+
extern "C" __declspec(noinline) HRESULT __stdcall
539+
```
540+
541+
### decltype and calls to deleted destructors
542+
In previous versions of Visual Studio, the compiler did not detect when a call to a deleted destructor occurred in the context of the expression associated with 'decltype'. In Update Version 15.3, the following code produces "error C2280: 'A<T>::~A(void)': attempting to reference a deleted function":
543+
544+
```cpp
545+
template<typename T>
546+
struct A
547+
{
548+
~A() = delete;
549+
};
550+
551+
template<typename T>
552+
auto f() -> A<T>;
553+
554+
template<typename T>
555+
auto g(T) -> decltype((f<T>()));
556+
557+
void h()
558+
{
559+
g(42);
560+
}
561+
```
562+
### Unitialized const variables
563+
Visual Studio 2017 RTW release had a regression in which the C++ compiler would not issue a diagnostic if a 'const' variable was not initialized. This regression has been fixed in Visual Studio 2017 Update 1. The following code now produces "warning C4132: 'Value': const object should be initialized":
564+
565+
```cpp
566+
const int Value;
567+
```
568+
To fix the error, assign a value to `Value`.
569+
570+
### Empty declarations
571+
Visual Studio 2017 Update Version 15.3 now warns on empty declarions for all types, not just built-in types. The following code now produces a level 2 C4091 warning for all four declarations:
572+
573+
```cpp
574+
struct A {};
575+
template <typename> struct B {};
576+
enum C { c1, c2, c3 };
577+
578+
int; // warning C4091 : '' : ignored on left of 'int' when no variable is declared
579+
A; // warning C4091 : '' : ignored on left of 'main::A' when no variable is declared
580+
B<int>; // warning C4091 : '' : ignored on left of 'B<int>' when no variable is declared
581+
C; // warning C4091 : '' : ignored on left of 'C' when no variable is declared
582+
```
583+
584+
To remove the warnings, simply comment-out or remove the empty declarations. In cases where the un-named object is intended to have a side effect (such as RAII) it should be given a name.
585+
586+
The warning is excluded under /Wv:18 and is on by default under warning level W2.
587+
588+
352589
## See Also
353590
[Visual C++ Language Conformance](visual-cpp-language-conformance.md)

0 commit comments

Comments
 (0)