compnerd created this revision. compnerd added a reviewer: aaron.ballman. compnerd added a project: clang. Herald added a project: All. compnerd requested review of this revision.
The itanium ABI represents the PMF as a pair of pointers. As such the structure cannot be passed through a single register. Diagnose such cases in the frontend rather than trying to generate IR to perform this operation. Fixes: 59033 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D138514 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaStmtAsm.cpp clang/test/Sema/gnu-asm-pmf.cpp Index: clang/test/Sema/gnu-asm-pmf.cpp =================================================================== --- /dev/null +++ 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())); +} Index: clang/lib/Sema/SemaStmtAsm.cpp =================================================================== --- clang/lib/Sema/SemaStmtAsm.cpp +++ clang/lib/Sema/SemaStmtAsm.cpp @@ -377,6 +377,16 @@ Expr *InputExpr = Exprs[i]; + if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) + if (const auto *UO = dyn_cast<UnaryOperator>(InputExpr)) + if (UO->getOpcode() == UO_AddrOf) + if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) + if (const auto *CMD = dyn_cast<CXXMethodDecl>(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(); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ 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">;
Index: clang/test/Sema/gnu-asm-pmf.cpp =================================================================== --- /dev/null +++ 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())); +} Index: clang/lib/Sema/SemaStmtAsm.cpp =================================================================== --- clang/lib/Sema/SemaStmtAsm.cpp +++ clang/lib/Sema/SemaStmtAsm.cpp @@ -377,6 +377,16 @@ Expr *InputExpr = Exprs[i]; + if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) + if (const auto *UO = dyn_cast<UnaryOperator>(InputExpr)) + if (UO->getOpcode() == UO_AddrOf) + if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) + if (const auto *CMD = dyn_cast<CXXMethodDecl>(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(); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ 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">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits