[clang] [Clang][Sema] Diagnose invalid 'pure'/'const' attributes on writes (PR #217817)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 21 06:38:51 PDT 2026
================
@@ -284,6 +284,76 @@ static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
return foundRecursion;
}
+namespace {
+/// Walks a 'pure'/'const' function body looking for stores through pointer
+/// or reference parameters, and stores to global or static-local variables.
+/// This is a syntactic heuristic, not a proof: it only catches direct writes
+/// reachable via straightforward lvalue expressions in the function's own
+/// body. It intentionally does not attempt interprocedural analysis (that's
+/// undecidable in general), locally-allocated memory escaping, or writes
+/// mediated through a level of indirection the visitor doesn't unwrap.
+class PureConstWriteChecker : public DynamicRecursiveASTVisitor {
+public:
+ PureConstWriteChecker(Sema &sema, const FunctionDecl *functionDecl,
+ bool isConstAttr)
+ : S(sema), FD(functionDecl), IsConstAttr(isConstAttr) {}
+
+ bool VisitBinaryOperator(BinaryOperator *BO) override {
+ if (BO->isAssignmentOp() || BO->isCompoundAssignmentOp())
+ checkLvalue(BO->getLHS());
+
+ return true;
+ }
+
+private:
+ Sema &S;
+ const FunctionDecl *FD;
+ bool IsConstAttr;
+
+ void checkLvalue(const Expr *E) {
+ E = E->IgnoreParenImpCasts();
+ if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
+ if (UO->getOpcode() == UO_Deref) {
+ checkPointerBase(UO->getSubExpr());
+ return;
+ }
+ }
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
----------------
AhmedKamel10 wrote:
I've refactored both DRE and VD checks to use early returns.
https://github.com/llvm/llvm-project/pull/217817
More information about the cfe-commits
mailing list