https://github.com/zwuis created https://github.com/llvm/llvm-project/pull/89713
clang don't check whether the operand of the & operator is enclosed in parantheses when pointer to member is formed in unevaluated context, for example: ```cpp struct foo { int val; }; int main() { decltype(&(foo::val)) ptr; } ``` `decltype(&(foo::val))` should be invalid, but clang accepts it. This PR fixes this issue. Fixes #40906. >From f6fd1e5e5f42b3c72cb5aeaf9e6d4e91d5424bee Mon Sep 17 00:00:00 2001 From: YanzuoLiu <zw...@outlook.com> Date: Tue, 23 Apr 2024 14:56:12 +0800 Subject: [PATCH] Add missing check when making pointer to member --- clang/lib/Sema/SemaExpr.cpp | 11 +++++++++++ .../CXX/expr/expr.unary/expr.unary.op/p3.cpp | 18 +++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5c861467bc1023..824667fb722365 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14644,6 +14644,17 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { return QualType(); } + // C++11 [expr.unary.op] p4: + // A pointer to member is only formed when an explicit & is used and + // its operand is a qualified-id not enclosed in parentheses. + if (isa<ParenExpr>(OrigOp.get())) { + // `op->getEndLoc()` is the last part of the qualified-id. + // For example, "baz" in "foo::bar::baz". + Diag(op->getEndLoc(), diag::err_invalid_non_static_member_use) + << dcl->getDeclName() << op->getSourceRange(); + return QualType(); + } + while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()) Ctx = Ctx->getParent(); diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp index 08ab0ca56fb632..73d850a6839da7 100644 --- a/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only %s -verify -// expected-no-diagnostics namespace rdar10544564 { // Check that we don't attempt to use an overloaded operator& when @@ -27,3 +26,20 @@ namespace rdar10544564 { X (Y::*func_mem_ptr1)() = &Y::memfunc1; X (Y::*func_mem_ptr2)() = &Y::memfunc2; } + +namespace test2 { + struct A { + int val; + void func() {} + }; + + void test() { + decltype(&(A::val)) ptr1; // expected-error {{invalid use of non-static data member 'val'}} + int A::* ptr2 = &(A::val); // expected-error {{invalid use of non-static data member 'val'}} + + // FIXME: Error messages in these cases are less than clear, we can do + // better. + int size = sizeof(&(A::func)); // expected-error {{call to non-static member function without an object argument}} + void (A::* ptr3)() = &(A::func); // expected-error {{call to non-static member function without an object argument}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits