diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8842,6 +8842,8 @@ // inline asm. let CategoryName = "Inline Assembly Issue" in { + def err_asm_pmf_in_input + : Error<"cannot pass pointer-to-member through a register on this ABI">; def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">; def err_asm_invalid_output_constraint : Error< "invalid output constraint '%0' in asm">; diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -377,6 +377,16 @@ Expr *InputExpr = Exprs[i]; + if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) + if (const auto *UO = dyn_cast(InputExpr)) + if (UO->getOpcode() == UO_AddrOf) + if (const auto *DRE = dyn_cast(UO->getSubExpr())) + if (const auto *CMD = dyn_cast(DRE->getDecl())) + if (CMD->isInstance()) + return StmtError(Diag(InputExpr->getBeginLoc(), + diag::err_asm_pmf_in_input) + << InputExpr->getSourceRange()); + // Referring to parameters is not allowed in naked functions. if (CheckNakedParmReference(InputExpr, *this)) return StmtError(); diff --git a/clang/test/Sema/gnu-asm-pmf.cpp b/clang/test/Sema/gnu-asm-pmf.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Sema/gnu-asm-pmf.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++2b -fsyntax-only -verify %s -DMICROSOFT_ABI +// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -std=c++2b -fsyntax-only -verify %s -DITANIUM_ABI + +#if defined(MICROSOFT_ABI) +// expected-no-diagnostics +#endif + +struct S { + void operator()() {} +}; + +struct T { + virtual void operator()() {} +}; + +struct U { + static void operator()() {} +}; + +auto L = [](){}; + +void f() { + __asm__ __volatile__ ("" : : "r"(&decltype(L)::operator())); +#if defined(ITANIUM_ABI) + // expected-error@-2{{cannot pass pointer-to-member through a register on this ABI}} +#endif + __asm__ __volatile__ ("" : : "r"(&S::operator())); +#if defined(ITANIUM_ABI) + // expected-error@-2{{cannot pass pointer-to-member through a register on this ABI}} +#endif + __asm__ __volatile__ ("" : : "r"(&T::operator())); +#if defined(ITANIUM_ABI) + // expected-error@-2{{cannot pass pointer-to-member through a register on this ABI}} +#endif + __asm__ __volatile__ ("" : : "r"(U::operator())); +}