================
@@ -642,6 +645,30 @@ bool isLoop(const Stmt *S) {
          isa<CXXForRangeStmt>(S);
 }
 
+// Strips E down to the Decl whose storage it ultimately refers to, chaining
+// through parens, casts, and member/array-element access (e.g. `a.b[i]`
+// resolves to `a`). Mutating any part of such a chain requires the base
+// Decl itself to be non-const if the chain is through value members/
+// elements (e.g. `a.b = 1` mutates `a`'s own storage); for a chain through a
+// pointer or reference, the base Decl's own binding usually isn't actually
+// touched (e.g. `p->b = 1` only mutates `*p`, not `p` itself), but treating
+// it as if it were is conservative and safe, just occasionally overcautious.
+// Returns null if E isn't ultimately grounded in a variable this way (e.g.
+// it's a temporary or a call result).
+const Decl *underlyingDecl(const Expr *E) {
+  E = E->IgnoreParenCasts();
+  if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+    return DRE->getDecl();
+  if (const auto *ME = dyn_cast<MemberExpr>(E))
+    return underlyingDecl(ME->getBase());
+  if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
+    return underlyingDecl(ASE->getBase());
+  if (const auto *BO = dyn_cast<BinaryOperator>(E))
+    if (BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI)
+      return underlyingDecl(BO->getLHS());
+  return nullptr;
----------------
ArcsinX wrote:

Do we need to handle `UnaryOperator` here? E.g. `*x = 1`.

https://github.com/llvm/llvm-project/pull/225666
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to