llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.03k stars 11.57k forks source link

`/permissive-` and Implicit conversion of integral constant expressions to null pointer #50924

Open llvmbot opened 3 years ago

llvmbot commented 3 years ago
Bugzilla Link 51582
Version 12.0
OS Windows NT
Attachments Bad overload chosen, -Wnon-literal-null-conversion
Reporter LLVM Bugzilla Contributor
CC @zygoloid

Extended Description

From

https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160&viewFallbackFrom=vs-2019#implicit-conversion-of-integral-constant-expressions-to-null-pointer

The MSVC compiler now implements CWG Issue 903 in conformance mode (/permissive-). This rule disallows implicit conversion of integral constant expressions (except for the integer literal '0') to null pointer constants.

The attached snippet, built with clang 12.0.1 for windows outputs

  CTOR two
  CTOR three

And so does Visual Studio with /permissive With /permissive- Visual Studio gets it right.

clang says:

warning: expression which evaluates to zero treated as a null pointer
constant of type 'int *const'
[-Wnon-literal-null-conversion]

If I remove constexpr the warning goes away, and we get correct behaviour.

shafik commented 2 months ago

CC @AaronBallman

AaronBallman commented 2 months ago

Slightly simplified example:

#include <initializer_list>

extern "C" int puts(const char *);

static constexpr unsigned PSI_NOT_INSTRUMENTED = 0;

typedef unsigned int PSI_memory_key;

template <typename Element_type>
class P {
  public:

  typedef const Element_type *const_iterator; 

  explicit P(PSI_memory_key key) : m_key(key) { 
    puts("CTOR one");
  }

  P(PSI_memory_key key, const_iterator, const_iterator) : m_key(key) {
    puts("CTOR two");
  }

  P(std::initializer_list<Element_type> elems)
      : P(PSI_NOT_INSTRUMENTED, elems.begin(), elems.end()) {
    puts("CTOR three");
  }

 private:
    PSI_memory_key m_key;
};

int main() {
  P<int *> array{PSI_NOT_INSTRUMENTED};
  return 0;
}

Live demo: https://godbolt.org/z/bE5466zb9

AaronBallman commented 2 months ago

I think we'll need to introduce a new flag to Clang to let users pick which behavior to be compatible with under -fms-compatibility because this is compatible either way, depending on the /permssive[-] flag passed to cl. We could then make clang-cl set this flag when passed /permissive[-], but folks using clang -fms-compatibility would still have to opt into/out of the behavior explicitly.

CC @zmodem @rnk for opinions on how we might want to handle permissive flags and -fms-compatibility more broadly.

llvmbot commented 2 months ago

@llvm/issue-subscribers-clang-frontend

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [51582](https://llvm.org/bz51582) | | Version | 12.0 | | OS | Windows NT | | Attachments | [Bad overload chosen, -Wnon-literal-null-conversion](https://user-images.githubusercontent.com/60944935/143762460-b8f97254-8304-4dc1-a230-1cf2ca4f8106.gz) | | Reporter | LLVM Bugzilla Contributor | | CC | @zygoloid | ## Extended Description From https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160&viewFallbackFrom=vs-2019#implicit-conversion-of-integral-constant-expressions-to-null-pointer > The MSVC compiler now implements CWG Issue 903 in conformance mode > (/permissive-). This rule disallows implicit conversion of integral > constant expressions (except for the integer literal '0') to null > pointer constants. The attached snippet, built with clang 12.0.1 for windows outputs ``` CTOR two CTOR three ``` And so does Visual Studio with `/permissive` With `/permissive-` Visual Studio gets it right. clang says: ``` warning: expression which evaluates to zero treated as a null pointer constant of type 'int *const' [-Wnon-literal-null-conversion] ``` If I remove `constexpr` the warning goes away, and we get correct behaviour.