From 707cc06e1570b5966efcd6a9124191c80fa7a754 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 9 Dec 2022 16:58:15 +0000 Subject: [PATCH] Sema: diagnose PMFs passed through registers to inline assembly 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 Differential Revision: https://reviews.llvm.org/D13851 Reviewed By: aaron.ballman --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Sema/SemaStmtAsm.cpp | 5 ++ clang/test/Sema/gnu-asm-pmf.cpp | 49 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 clang/test/Sema/gnu-asm-pmf.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 734cffd01c22..0bbd1f6be4e2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8845,6 +8845,9 @@ def warn_redefine_extname_not_applied : Warning< // inline asm. let CategoryName = "Inline Assembly Issue" in { + def err_asm_pmf_through_constraint_not_permitted + : Error<"cannot pass a pointer-to-member through register-constrained " + "inline assembly parameter">; 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 index d19f4d6c7835..06fc0ec79866 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -377,6 +377,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, Expr *InputExpr = Exprs[i]; + if (InputExpr->getType()->isMemberPointerType()) + return StmtError(Diag(InputExpr->getBeginLoc(), + diag::err_asm_pmf_through_constraint_not_permitted) + << 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 index 000000000000..30677c85696d --- /dev/null +++ b/clang/test/Sema/gnu-asm-pmf.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++2b -fsyntax-only %s -verify +// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -std=c++2b -fsyntax-only %s -verify + +struct S { + void operator()(); +}; + +struct T { + virtual void operator()(); +}; + +struct U { + static void operator()(); +}; + +struct V: virtual T { + virtual void f(); +}; + +struct W : virtual V { + int i; +}; + +struct X { + __UINTPTR_TYPE__ ptr; + __UINTPTR_TYPE__ adj; +}; + +auto L = [](){}; + +void f() { + auto pmf = &S::operator(); + + __asm__ __volatile__ ("" : : "r"(&decltype(L)::operator())); + // expected-error@-1{{cannot pass a pointer-to-member through register-constrained inline assembly parameter}} + __asm__ __volatile__ ("" : : "r"(&S::operator())); + // expected-error@-1{{cannot pass a pointer-to-member through register-constrained inline assembly parameter}} + __asm__ __volatile__ ("" : : "r"(&T::operator())); + // expected-error@-1{{cannot pass a pointer-to-member through register-constrained inline assembly parameter}} + __asm__ __volatile__ ("" : : "r"(pmf)); + // expected-error@-1{{cannot pass a pointer-to-member through register-constrained inline assembly parameter}} + __asm__ __volatile__ ("" : : "r"(&W::f)); + // expected-error@-1{{cannot pass a pointer-to-member through register-constrained inline assembly parameter}} + __asm__ __volatile__ ("" : : "r"(&W::i)); + // expected-error@-1{{cannot pass a pointer-to-member through register-constrained inline assembly parameter}} + + __asm__ __volatile__ ("" : : "r"(X{0,0})); + __asm__ __volatile__ ("" : : "r"(&U::operator())); +}