llvm / llvm-project

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

code compiles (and segfaults) with gcc, but does not compile with clang #46982

Open llvmbot opened 4 years ago

llvmbot commented 4 years ago
Bugzilla Link 47638
Version 10.0
OS Linux
Reporter LLVM Bugzilla Contributor
CC @dwblaikie,@efriedma-quic,@zygoloid

Extended Description

struct S
{
  auto f()
  {
    return [](){};
  }

  template <typename U = S>
  using FP = decltype(&U::f);
};

int main()
{
  (S().*S::FP<>())();

  return 0;
}

https://wandbox.org/permlink/ZjerOK6U3svPXXfE

This code will compile (and segfault) with gcc 10.1, but will not compile with clang 10.0.0. I think it's valid code. Playing with parentheses did not work for me.

prog.cc:15:7: error: invalid use of pointer to member type after .*
 (S().*S::FP<>())();
      ^
1 error generated.
ec04fc15-fa35-46f2-80e1-5d271f2ef708 commented 4 years ago

Weird!

We have a special case diagnostic in Sema that rejects exactly this, dating back years:

  if (isa<CXXScalarValueInitExpr>(RHS.get()->IgnoreParens())) {                         
    // Diagnose use of pointer-to-member type which when used as                        
    // the functional cast in a pointer-to-member expression.                           
    Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;                          
     return QualType();                                                                 
  }                                                                                     

Added here: https://github.com/llvm/llvm-project/commit/1bc0f9affc20474dbf86842e2f38b00c844207c6

... as a refactoring of a diagnostic added here: https://github.com/llvm/llvm-project/commit/9a14b84ac559e85672ce9c463eba7bf23ba4b6a2

... to work around a bug in IR generation, as far as I can see.

Presumably we can downgrade this to a warning now :)

efriedma-quic commented 4 years ago

Simplifies to:

struct S {};
using FP = int S::*;
int main()
{
  return S().*FP();
}

Somehow the parser isn't treating FP() as an expression.

Endilll commented 1 year ago

Still an error on post-17 trunk: https://godbolt.org/z/fPqxKdddx

llvmbot commented 1 year ago

@llvm/issue-subscribers-c-1