https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/94159
>From 6dec67c1fe9b64881a7b4f97f2341b2fdf7db48b Mon Sep 17 00:00:00 2001 From: Rajveer <rajveer.develo...@icloud.com> Date: Sun, 2 Jun 2024 18:33:37 +0530 Subject: [PATCH] [clang] Fix-it hint for `++this` -> `++*this` when deref is modifiable Resolves #93066 --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Sema/SemaExpr.cpp | 18 ++++++++++-- clang/test/Sema/debug-93066.cpp | 28 +++++++++++++++++++ clang/test/Sema/exprs.c | 2 ++ clang/test/Sema/va_arg_x86_32.c | 1 + clang/test/SemaObjCXX/sel-address.mm | 1 + 6 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 clang/test/Sema/debug-93066.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 270b0a1e01307..0ad0a80c21521 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8777,6 +8777,9 @@ def err_typecheck_incomplete_type_not_modifiable_lvalue : Error< def err_typecheck_lvalue_casts_not_supported : Error< "assignment to cast is illegal, lvalue casts are not supported">; +def note_typecheck_expression_not_modifiable_lvalue : Note< + "add '*' to dereference it">; + def err_typecheck_duplicate_vector_components_not_mlvalue : Error< "vector is not assignable (contains duplicate components)">; def err_block_decl_ref_not_modifiable_lvalue : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ff9c5ead36dcf..62da33e64bf7b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13367,6 +13367,8 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E, if (!DiagnosticEmitted) { S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstVariable << VD << VD->getType(); + S.Diag(Loc, diag::note_typecheck_expression_not_modifiable_lvalue) + << E->getSourceRange(); DiagnosticEmitted = true; } S.Diag(VD->getLocation(), diag::note_typecheck_assign_const) @@ -13587,10 +13589,22 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { SourceRange Assign; if (Loc != OrigLoc) Assign = SourceRange(OrigLoc, OrigLoc); - if (NeedType) + if (NeedType) { S.Diag(Loc, DiagID) << E->getType() << E->getSourceRange() << Assign; - else + } else { + ExprResult Deref; + { + Sema::TentativeAnalysisScope Trap(S); + Deref = S.ActOnUnaryOp(S.getCurScope(), Loc, tok::star, E); + } S.Diag(Loc, DiagID) << E->getSourceRange() << Assign; + if (Deref.isUsable() && + Deref.get()->isModifiableLvalue(S.Context, &Loc) == Expr::MLV_Valid) { + S.Diag(Loc, diag::note_typecheck_expression_not_modifiable_lvalue) + << E->getSourceRange() << Assign; + FixItHint::CreateInsertion(E->getBeginLoc(), "++*this"); + } + } return true; } diff --git a/clang/test/Sema/debug-93066.cpp b/clang/test/Sema/debug-93066.cpp new file mode 100644 index 0000000000000..e0bd87fb810ef --- /dev/null +++ b/clang/test/Sema/debug-93066.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s + +struct S { + void f() { + ++this; // expected-error {{expression is not assignable}} + // expected-note@-1 {{add '*' to dereference it}} + } + + void g() const { + ++this; // expected-error {{expression is not assignable}} + } +}; + +void f(int* a, int* const b, const int* const c, __UINTPTR_TYPE__ d) { + (int*)d = 4; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} + // expected-note@-1 {{add '*' to dereference it}} + + ++a; + ++b; // expected-error {{cannot assign to variable 'b' with const-qualified type 'int *const'}} + // expected-note@-1 {{add '*' to dereference it}} + // expected-note@* {{variable 'b' declared const here}} + ++c; // expected-error {{cannot assign to variable 'c' with const-qualified type 'const int *const'}} + // expected-note@-1 {{add '*' to dereference it}} + // expected-note@* {{variable 'c' declared const here}} + + reinterpret_cast<int*>(42) += 3; // expected-error {{expression is not assignable}} + // expected-note@-1 {{add '*' to dereference it}} +} diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c index 3203d961dd0a4..a5b7268f4f527 100644 --- a/clang/test/Sema/exprs.c +++ b/clang/test/Sema/exprs.c @@ -65,8 +65,10 @@ void test4(void) { void test5(int *X, float *P) { (float*)X = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} + // expected-note@-1 {{add '*' to dereference it}} #define FOO ((float*) X) FOO = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} + // expected-note@-1 {{add '*' to dereference it}} } void test6(void) { diff --git a/clang/test/Sema/va_arg_x86_32.c b/clang/test/Sema/va_arg_x86_32.c index 86a6a8881f54b..55d21f787a6f0 100644 --- a/clang/test/Sema/va_arg_x86_32.c +++ b/clang/test/Sema/va_arg_x86_32.c @@ -2,5 +2,6 @@ int a(void) { __builtin_va_arg((char*)0, int); // expected-error {{expression is not assignable}} + // expected-note@-1 {{add '*' to dereference it}} __builtin_va_arg((void*){0}, int); // expected-error {{first argument to 'va_arg' is of type 'void *'}} } diff --git a/clang/test/SemaObjCXX/sel-address.mm b/clang/test/SemaObjCXX/sel-address.mm index e5661af341691..4f9b985989e00 100644 --- a/clang/test/SemaObjCXX/sel-address.mm +++ b/clang/test/SemaObjCXX/sel-address.mm @@ -10,6 +10,7 @@ void h() { SEL* ps = &s; @selector(dealloc) = s; // expected-error {{expression is not assignable}} + // expected-note@-1 {{add '*' to dereference it}} SEL* ps2 = &@selector(dealloc); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits