[clang] [clang][analyzer] Add StoreToImmutable checker (PR #150417)
Endre Fülöp via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 28 06:17:56 PDT 2025
https://github.com/gamesh411 updated https://github.com/llvm/llvm-project/pull/150417
>From 0630d81e544319a1a18798996760775d4a13f7ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.com>
Date: Thu, 24 Jul 2025 14:49:14 +0200
Subject: [PATCH 1/4] [clang][analyzer] Add StoreToImmutable checker
This adds alpha.core.StoreToImmutable, a new alpha checker that detects
writes
to immutable memory regions, implementing part of SEI CERT Rule ENV30-C.
The
original proposal only handled global const variables, but this
implementation
extends it to detect writes to:
- Global const variables
- Local const variables
- String literals
- Const parameters and struct members
- Const arrays and pointers to const data
This checker is the continuation of the work started by @zukatsinadze.
Discussion: https://reviews.llvm.org/D124244
---
clang/docs/analyzer/checkers.rst | 17 ++
.../checkers/storetoimmutable_example.cpp | 30 ++++
.../clang/StaticAnalyzer/Checkers/Checkers.td | 5 +
.../Core/PathSensitive/MemRegion.h | 2 +-
.../StaticAnalyzer/Checkers/CMakeLists.txt | 1 +
.../Checkers/StoreToImmutableChecker.cpp | 146 +++++++++++++++
.../Analysis/store-to-immutable-basic.cpp | 166 ++++++++++++++++++
7 files changed, 366 insertions(+), 1 deletion(-)
create mode 100644 clang/docs/analyzer/checkers/storetoimmutable_example.cpp
create mode 100644 clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp
create mode 100644 clang/test/Analysis/store-to-immutable-basic.cpp
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 26c5028e04955..a00e9d81ba208 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -3077,6 +3077,23 @@ Either the comparison is useless or there is division by zero.
if (x == 0) { } // warn
}
+.. _alpha-core-StoreToImmutable:
+
+alpha.core.StoreToImmutable (C, C++)
+""""""""""""""""""""""""""""""""""""
+Check for writes to immutable memory regions. This implements part of SEI CERT Rule ENV30-C.
+
+This checker detects attempts to write to memory regions that are marked as immutable,
+including const variables, string literals, and other const-qualified memory.
+
+.. literalinclude:: checkers/storetoimmutable_example.cpp
+ :language: cpp
+
+**Solution**
+
+Avoid writing to const-qualified memory regions. If you need to modify the data,
+remove the const qualifier from the original declaration or use a mutable copy.
+
alpha.cplusplus
^^^^^^^^^^^^^^^
diff --git a/clang/docs/analyzer/checkers/storetoimmutable_example.cpp b/clang/docs/analyzer/checkers/storetoimmutable_example.cpp
new file mode 100644
index 0000000000000..e1a0683ff91e4
--- /dev/null
+++ b/clang/docs/analyzer/checkers/storetoimmutable_example.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.StoreToImmutable %s
+
+// Global const variable
+const int global_const = 42;
+
+void test_global_const() {
+ *(int *)&global_const = 100; // warn: Writing to immutable memory
+}
+
+// String literal
+void test_string_literal() {
+ char *str = (char *)"hello";
+ str[0] = 'H'; // warn: Writing to immutable memory
+}
+
+// Const parameter
+void test_const_param(const int param) {
+ *(int *)¶m = 100; // warn: Writing to immutable memory
+}
+
+// Const struct member
+struct TestStruct {
+ const int x;
+ int y;
+};
+
+void test_const_member() {
+ TestStruct s = {1, 2};
+ *(int *)&s.x = 10; // warn: Writing to immutable memory
+}
\ No newline at end of file
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 2234143004b6f..8799f1d15b0b6 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -306,6 +306,11 @@ def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
Dependencies<[StackAddrEscapeBase]>,
Documentation<HasDocumentation>;
+def StoreToImmutableChecker : Checker<"StoreToImmutable">,
+ HelpText<"Check for writes to immutable memory regions. "
+ "This implements part of SEI CERT Rule ENV30-C.">,
+ Documentation<HasDocumentation>;
+
def PthreadLockBase : Checker<"PthreadLockBase">,
HelpText<"Helper registering multiple checks.">,
Documentation<NotDocumented>,
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 89d306fb94046..0f7bab6839703 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -819,7 +819,7 @@ class SymbolicRegion : public SubRegion {
s->getType()->isReferenceType() ||
s->getType()->isBlockPointerType());
assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg) ||
- isa<GlobalSystemSpaceRegion>(sreg));
+ isa<GlobalSystemSpaceRegion>(sreg) || isa<GlobalImmutableSpaceRegion>(sreg));
}
public:
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 22dd3f0374849..78360418a8b81 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -104,6 +104,7 @@ add_clang_library(clangStaticAnalyzerCheckers
SmartPtrChecker.cpp
SmartPtrModeling.cpp
StackAddrEscapeChecker.cpp
+ StoreToImmutableChecker.cpp
StdLibraryFunctionsChecker.cpp
StdVariantChecker.cpp
STLAlgorithmModeling.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp
new file mode 100644
index 0000000000000..a853e2e3f9c4a
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp
@@ -0,0 +1,146 @@
+//=== StoreToImmutableChecker.cpp - Store to immutable memory checker -*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines StoreToImmutableChecker, a checker that detects writes
+// to immutable memory regions. This implements part of SEI CERT Rule ENV30-C.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class StoreToImmutableChecker : public Checker<check::Bind> {
+ const BugType BT{this, "Write to immutable memory", "CERT Environment (ENV)"};
+
+public:
+ void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const;
+
+private:
+ bool isConstVariable(const MemRegion *MR, CheckerContext &C) const;
+ bool isConstQualifiedType(const MemRegion *MR, CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+bool StoreToImmutableChecker::isConstVariable(const MemRegion *MR,
+ CheckerContext &C) const {
+ // Check if the region is in the global immutable space
+ const MemSpaceRegion *MS = MR->getMemorySpace(C.getState());
+ if (isa<GlobalImmutableSpaceRegion>(MS))
+ return true;
+
+ // Check if this is a VarRegion with a const-qualified type
+ if (const VarRegion *VR = dyn_cast<VarRegion>(MR)) {
+ const VarDecl *VD = VR->getDecl();
+ if (VD && VD->getType().isConstQualified())
+ return true;
+ }
+
+ // Check if this is a ParamVarRegion with a const-qualified type
+ if (const ParamVarRegion *PVR = dyn_cast<ParamVarRegion>(MR)) {
+ const ParmVarDecl *PVD = PVR->getDecl();
+ if (PVD && PVD->getType().isConstQualified())
+ return true;
+ }
+
+ // Check if this is a FieldRegion with a const-qualified type
+ if (const FieldRegion *FR = dyn_cast<FieldRegion>(MR)) {
+ const FieldDecl *FD = FR->getDecl();
+ if (FD && FD->getType().isConstQualified())
+ return true;
+ }
+
+ // Check if this is a StringRegion (string literals are const)
+ if (isa<StringRegion>(MR))
+ return true;
+
+ // Check if this is a SymbolicRegion with a const-qualified pointee type
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) {
+ QualType PointeeType = SR->getPointeeStaticType();
+ if (PointeeType.isConstQualified())
+ return true;
+ }
+
+ // Check if this is an ElementRegion accessing a const array
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(MR)) {
+ return isConstQualifiedType(ER->getSuperRegion(), C);
+ }
+
+ return false;
+}
+
+bool StoreToImmutableChecker::isConstQualifiedType(const MemRegion *MR,
+ CheckerContext &C) const {
+ // Check if the region has a const-qualified type
+ if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR)) {
+ QualType Ty = TVR->getValueType();
+ return Ty.isConstQualified();
+ }
+ return false;
+}
+
+void StoreToImmutableChecker::checkBind(SVal Loc, SVal Val, const Stmt *S,
+ CheckerContext &C) const {
+ // We are only interested in stores to memory regions
+ const MemRegion *MR = Loc.getAsRegion();
+ if (!MR)
+ return;
+
+ // Skip variable declarations and initializations - we only want to catch
+ // actual writes
+ if (isa<DeclStmt>(S) || isa<DeclRefExpr>(S))
+ return;
+
+ // Check if the region corresponds to a const variable
+ if (!isConstVariable(MR, C))
+ return;
+
+ const SourceManager &SM = C.getSourceManager();
+ // Skip if this is a system macro (likely from system headers)
+ if (SM.isInSystemMacro(S->getBeginLoc()))
+ return;
+
+ // Generate the bug report
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
+
+ constexpr llvm::StringLiteral Msg =
+ "Writing to immutable memory is undefined behavior. "
+ "This memory region is marked as immutable and should not be modified.";
+
+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
+ R->addRange(S->getSourceRange());
+
+ // If the location that is being written to has a declaration, place a note.
+ if (const DeclRegion *DR = dyn_cast<DeclRegion>(MR)) {
+ R->addNote("Memory region is in immutable space",
+ PathDiagnosticLocation::create(DR->getDecl(), SM));
+ }
+
+ // For this checker, we are only interested in the value being written, no
+ // need to mark the value being assigned interesting.
+
+ C.emitReport(std::move(R));
+}
+
+void ento::registerStoreToImmutableChecker(CheckerManager &mgr) {
+ mgr.registerChecker<StoreToImmutableChecker>();
+}
+
+bool ento::shouldRegisterStoreToImmutableChecker(const CheckerManager &mgr) {
+ return true;
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/store-to-immutable-basic.cpp b/clang/test/Analysis/store-to-immutable-basic.cpp
new file mode 100644
index 0000000000000..2b28b933e97b4
--- /dev/null
+++ b/clang/test/Analysis/store-to-immutable-basic.cpp
@@ -0,0 +1,166 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.StoreToImmutable -verify %s
+
+// Test basic functionality of StoreToImmutable checker
+// This tests direct writes to immutable regions without function modeling
+
+// Direct write to a const global variable
+const int global_const = 42; // expected-note {{Memory region is in immutable space}}
+
+void test_direct_write_to_const_global() {
+ // This should trigger a warning about writing to immutable memory
+ *(int*)&global_const = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write through a pointer to const memory
+void test_write_through_const_pointer() {
+ const int local_const = 10; // expected-note {{Memory region is in immutable space}}
+ int *ptr = (int*)&local_const;
+ *ptr = 20; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to string literal (should be in immutable space)
+void test_write_to_string_literal() {
+ char *str = (char*)"hello";
+ str[0] = 'H'; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const array
+void test_write_to_const_array() {
+ const int arr[5] = {1, 2, 3, 4, 5};
+ int *ptr = (int*)arr;
+ ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const struct member
+struct TestStruct {
+ const int x; // expected-note 2{{Memory region is in immutable space}}
+ int y;
+};
+
+void test_write_to_const_struct_member() {
+ TestStruct s = {1, 2};
+ int *ptr = (int*)&s.x;
+ *ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const global array
+const int global_array[3] = {1, 2, 3};
+
+void test_write_to_const_global_array() {
+ int *ptr = (int*)global_array;
+ ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const global struct
+const TestStruct global_struct = {1, 2};
+
+void test_write_to_const_global_struct() {
+ int *ptr = (int*)&global_struct.x;
+ *ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const parameter
+void test_write_to_const_param(const int param) { // expected-note {{Memory region is in immutable space}}
+ *(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const reference parameter
+void test_write_to_const_ref_param(const int ¶m) {
+ *(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const pointer parameter
+void test_write_to_const_ptr_param(const int *param) {
+ *(int*)param = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const array parameter
+void test_write_to_const_array_param(const int arr[5]) {
+ *(int*)arr = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const struct parameter
+struct ParamStruct {
+ const int z; // expected-note 3{{Memory region is in immutable space}}
+ int w;
+};
+
+void test_write_to_const_struct_param(const ParamStruct s) {
+ *(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const struct reference parameter
+void test_write_to_const_struct_ref_param(const ParamStruct &s) {
+ *(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+// Write to const struct pointer parameter
+void test_write_to_const_struct_ptr_param(const ParamStruct *s) {
+ *(int*)&s->z = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+//===--- NEGATIVE TEST CASES ---===//
+// These tests should NOT trigger warnings
+
+// Write to non-const variable (should not warn)
+void test_write_to_nonconst() {
+ int non_const = 42;
+ *(int*)&non_const = 100; // No warning expected
+}
+
+// Write to non-const global variable (should not warn)
+int global_non_const = 42;
+
+void test_write_to_nonconst_global() {
+ *(int*)&global_non_const = 100; // No warning expected
+}
+
+// Write to non-const struct member (should not warn)
+struct NonConstStruct {
+ int x;
+ int y;
+};
+
+void test_write_to_nonconst_struct_member() {
+ NonConstStruct s = {1, 2};
+ *(int*)&s.x = 100; // No warning expected
+}
+
+// Write to non-const parameter (should not warn)
+void test_write_to_nonconst_param(int param) {
+ *(int*)¶m = 100; // No warning expected
+}
+
+// Normal assignment to non-const variable (should not warn)
+void test_normal_assignment() {
+ int x = 42;
+ x = 100; // No warning expected
+}
+
+// Write to non-const data through const pointer (should not warn - underlying memory is non-const)
+void test_const_ptr_to_nonconst_data() {
+ int data = 42;
+ const int *ptr = &data;
+ *(int*)ptr = 100; // No warning expected
+}
+
+// Write to non-const data through const reference (should not warn - underlying memory is non-const)
+void test_const_ref_to_nonconst_data() {
+ int data = 42;
+ const int &ref = data;
+ *(int*)&ref = 100; // No warning expected
+}
\ No newline at end of file
>From fa3f84f2dd3efb811d9c5fa006714279503f1d22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.com>
Date: Fri, 25 Jul 2025 03:21:19 +0200
Subject: [PATCH 2/4] Apply review suggestiongs by @steakhal
---
.../Core/PathSensitive/MemRegion.h | 2 +-
.../Checkers/StoreToImmutableChecker.cpp | 18 +-
.../test/Analysis/store-to-immutable-basic.c | 138 +++++++++++++++
.../Analysis/store-to-immutable-basic.cpp | 157 ++----------------
4 files changed, 156 insertions(+), 159 deletions(-)
create mode 100644 clang/test/Analysis/store-to-immutable-basic.c
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 0f7bab6839703..89d306fb94046 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -819,7 +819,7 @@ class SymbolicRegion : public SubRegion {
s->getType()->isReferenceType() ||
s->getType()->isBlockPointerType());
assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg) ||
- isa<GlobalSystemSpaceRegion>(sreg) || isa<GlobalImmutableSpaceRegion>(sreg));
+ isa<GlobalSystemSpaceRegion>(sreg));
}
public:
diff --git a/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp
index a853e2e3f9c4a..73c75b74451f1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StoreToImmutableChecker.cpp
@@ -1,5 +1,4 @@
-//=== StoreToImmutableChecker.cpp - Store to immutable memory checker -*- C++
-//-*-===//
+//=== StoreToImmutableChecker.cpp - Store to immutable memory ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -49,13 +48,6 @@ bool StoreToImmutableChecker::isConstVariable(const MemRegion *MR,
return true;
}
- // Check if this is a ParamVarRegion with a const-qualified type
- if (const ParamVarRegion *PVR = dyn_cast<ParamVarRegion>(MR)) {
- const ParmVarDecl *PVD = PVR->getDecl();
- if (PVD && PVD->getType().isConstQualified())
- return true;
- }
-
// Check if this is a FieldRegion with a const-qualified type
if (const FieldRegion *FR = dyn_cast<FieldRegion>(MR)) {
const FieldDecl *FD = FR->getDecl();
@@ -63,10 +55,6 @@ bool StoreToImmutableChecker::isConstVariable(const MemRegion *MR,
return true;
}
- // Check if this is a StringRegion (string literals are const)
- if (isa<StringRegion>(MR))
- return true;
-
// Check if this is a SymbolicRegion with a const-qualified pointee type
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) {
QualType PointeeType = SR->getPointeeStaticType();
@@ -101,7 +89,7 @@ void StoreToImmutableChecker::checkBind(SVal Loc, SVal Val, const Stmt *S,
// Skip variable declarations and initializations - we only want to catch
// actual writes
- if (isa<DeclStmt>(S) || isa<DeclRefExpr>(S))
+ if (isa<DeclStmt, DeclRefExpr>(S))
return;
// Check if the region corresponds to a const variable
@@ -143,4 +131,4 @@ void ento::registerStoreToImmutableChecker(CheckerManager &mgr) {
bool ento::shouldRegisterStoreToImmutableChecker(const CheckerManager &mgr) {
return true;
-}
\ No newline at end of file
+}
diff --git a/clang/test/Analysis/store-to-immutable-basic.c b/clang/test/Analysis/store-to-immutable-basic.c
new file mode 100644
index 0000000000000..eee4388c2446c
--- /dev/null
+++ b/clang/test/Analysis/store-to-immutable-basic.c
@@ -0,0 +1,138 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.StoreToImmutable -verify %s
+
+// Test basic functionality of StoreToImmutable checker for the C programming language.
+
+const int tentative_global_const; // expected-note {{Memory region is in immutable space}}
+
+void test_direct_write_to_tentative_const_global() {
+ *(int*)&tentative_global_const = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+const int global_const = 42; // expected-note {{Memory region is in immutable space}}
+
+void test_direct_write_to_const_global() {
+ // This should trigger a warning about writing to immutable memory
+ *(int*)&global_const = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_write_through_const_pointer() {
+ const int local_const = 10; // expected-note {{Memory region is in immutable space}}
+ int *ptr = (int*)&local_const;
+ *ptr = 20; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_write_to_const_array() {
+ const int arr[5] = {1, 2, 3, 4, 5};
+ int *ptr = (int*)arr;
+ ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+struct TestStruct {
+ const int x; // expected-note 2 {{Memory region is in immutable space}}
+ int y;
+};
+
+void test_write_to_const_struct_member() {
+ struct TestStruct s = {1, 2};
+ int *ptr = (int*)&s.x;
+ *ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+const int global_array[3] = {1, 2, 3};
+
+void test_write_to_const_global_array() {
+ int *ptr = (int*)global_array;
+ ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+
+}
+
+const struct TestStruct global_struct = {1, 2};
+
+void test_write_to_const_global_struct() {
+ int *ptr = (int*)&global_struct.x;
+ *ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_write_to_const_param(const int param) { // expected-note {{Memory region is in immutable space}}
+ *(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_write_to_const_ptr_param(const int *param) {
+ *(int*)param = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_write_to_const_array_param(const int arr[5]) {
+ *(int*)arr = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+struct ParamStruct {
+ const int z; // expected-note 2 {{Memory region is in immutable space}}
+ int w;
+};
+
+void test_write_to_const_struct_param(const struct ParamStruct s) {
+ *(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+
+}
+
+void test_write_to_const_struct_ptr_param(const struct ParamStruct *s) {
+ *(int*)&s->z = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_write_to_nonconst() {
+ int non_const = 42;
+ *(int*)&non_const = 100; // No warning expected
+}
+
+int global_non_const = 42;
+
+void test_write_to_nonconst_global() {
+ *(int*)&global_non_const = 100; // No warning expected
+}
+
+struct NonConstStruct {
+ int x;
+ int y;
+};
+
+void test_write_to_nonconst_struct_member() {
+ struct NonConstStruct s = {1, 2};
+ *(int*)&s.x = 100; // No warning expected
+}
+
+void test_write_to_nonconst_param(int param) {
+ *(int*)¶m = 100; // No warning expected
+}
+
+void test_normal_assignment() {
+ int x = 42;
+ x = 100; // No warning expected
+}
+
+void test_const_ptr_to_nonconst_data() {
+ int data = 42;
+ const int *ptr = &data;
+ *(int*)ptr = 100; // No warning expected
+}
+
+void test_const_ptr_to_const_data() {
+ const int data = 42; // expected-note {{Memory region is in immutable space}}
+ const int *ptr = &data;
+ *(int*)ptr = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+
+
diff --git a/clang/test/Analysis/store-to-immutable-basic.cpp b/clang/test/Analysis/store-to-immutable-basic.cpp
index 2b28b933e97b4..5014ad66ceb7b 100644
--- a/clang/test/Analysis/store-to-immutable-basic.cpp
+++ b/clang/test/Analysis/store-to-immutable-basic.cpp
@@ -1,166 +1,37 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.StoreToImmutable -verify %s
-// Test basic functionality of StoreToImmutable checker
-// This tests direct writes to immutable regions without function modeling
+// Test the inteaction of the StoreToImmutable checker with C++ references.
-// Direct write to a const global variable
-const int global_const = 42; // expected-note {{Memory region is in immutable space}}
-
-void test_direct_write_to_const_global() {
- // This should trigger a warning about writing to immutable memory
- *(int*)&global_const = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write through a pointer to const memory
-void test_write_through_const_pointer() {
- const int local_const = 10; // expected-note {{Memory region is in immutable space}}
- int *ptr = (int*)&local_const;
- *ptr = 20; // expected-warning {{Writing to immutable memory is undefined behavior}}
+void test_write_to_const_ref_param(const int ¶m) {
+ *(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
// expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
-// Write to string literal (should be in immutable space)
void test_write_to_string_literal() {
char *str = (char*)"hello";
- str[0] = 'H'; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const array
-void test_write_to_const_array() {
- const int arr[5] = {1, 2, 3, 4, 5};
- int *ptr = (int*)arr;
- ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const struct member
-struct TestStruct {
- const int x; // expected-note 2{{Memory region is in immutable space}}
- int y;
-};
-
-void test_write_to_const_struct_member() {
- TestStruct s = {1, 2};
- int *ptr = (int*)&s.x;
- *ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const global array
-const int global_array[3] = {1, 2, 3};
-
-void test_write_to_const_global_array() {
- int *ptr = (int*)global_array;
- ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const global struct
-const TestStruct global_struct = {1, 2};
-
-void test_write_to_const_global_struct() {
- int *ptr = (int*)&global_struct.x;
- *ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const parameter
-void test_write_to_const_param(const int param) { // expected-note {{Memory region is in immutable space}}
- *(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const reference parameter
-void test_write_to_const_ref_param(const int ¶m) {
- *(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const pointer parameter
-void test_write_to_const_ptr_param(const int *param) {
- *(int*)param = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const array parameter
-void test_write_to_const_array_param(const int arr[5]) {
- *(int*)arr = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ str[0] = 'H'; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
// expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
-// Write to const struct parameter
struct ParamStruct {
- const int z; // expected-note 3{{Memory region is in immutable space}}
+ const int z; // expected-note {{Memory region is in immutable space}}
int w;
};
-void test_write_to_const_struct_param(const ParamStruct s) {
- *(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-// Write to const struct reference parameter
void test_write_to_const_struct_ref_param(const ParamStruct &s) {
- *(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
+ *(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
// expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
-// Write to const struct pointer parameter
-void test_write_to_const_struct_ptr_param(const ParamStruct *s) {
- *(int*)&s->z = 100; // expected-warning {{Writing to immutable memory is undefined behavior}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-//===--- NEGATIVE TEST CASES ---===//
-// These tests should NOT trigger warnings
-
-// Write to non-const variable (should not warn)
-void test_write_to_nonconst() {
- int non_const = 42;
- *(int*)&non_const = 100; // No warning expected
-}
-
-// Write to non-const global variable (should not warn)
-int global_non_const = 42;
-
-void test_write_to_nonconst_global() {
- *(int*)&global_non_const = 100; // No warning expected
-}
-
-// Write to non-const struct member (should not warn)
-struct NonConstStruct {
- int x;
- int y;
-};
-
-void test_write_to_nonconst_struct_member() {
- NonConstStruct s = {1, 2};
- *(int*)&s.x = 100; // No warning expected
-}
-
-// Write to non-const parameter (should not warn)
-void test_write_to_nonconst_param(int param) {
- *(int*)¶m = 100; // No warning expected
-}
-
-// Normal assignment to non-const variable (should not warn)
-void test_normal_assignment() {
- int x = 42;
- x = 100; // No warning expected
-}
-
-// Write to non-const data through const pointer (should not warn - underlying memory is non-const)
-void test_const_ptr_to_nonconst_data() {
- int data = 42;
- const int *ptr = &data;
- *(int*)ptr = 100; // No warning expected
-}
-
-// Write to non-const data through const reference (should not warn - underlying memory is non-const)
void test_const_ref_to_nonconst_data() {
int data = 42;
const int &ref = data;
*(int*)&ref = 100; // No warning expected
-}
\ No newline at end of file
+}
+
+void test_const_ref_to_const_data() {
+ const int data = 42; // expected-note {{Memory region is in immutable space}}
+ const int &ref = data;
+ *(int*)&ref = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+ // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
>From b022182d0eb0f2f5b15d81440e216972ae49bef2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.com>
Date: Mon, 28 Jul 2025 13:56:50 +0200
Subject: [PATCH 3/4] [review-fix] fix test files
add fixme comments
add const reference test case
remove duplicate expected-notes and analyzer-output=text
---
.../test/Analysis/store-to-immutable-basic.c | 20 +------------------
.../Analysis/store-to-immutable-basic.cpp | 18 ++++++++++++-----
2 files changed, 14 insertions(+), 24 deletions(-)
diff --git a/clang/test/Analysis/store-to-immutable-basic.c b/clang/test/Analysis/store-to-immutable-basic.c
index eee4388c2446c..f098f7fefa28c 100644
--- a/clang/test/Analysis/store-to-immutable-basic.c
+++ b/clang/test/Analysis/store-to-immutable-basic.c
@@ -6,7 +6,6 @@ const int tentative_global_const; // expected-note {{Memory region is in immutab
void test_direct_write_to_tentative_const_global() {
*(int*)&tentative_global_const = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
const int global_const = 42; // expected-note {{Memory region is in immutable space}}
@@ -14,21 +13,18 @@ const int global_const = 42; // expected-note {{Memory region is in immutable sp
void test_direct_write_to_const_global() {
// This should trigger a warning about writing to immutable memory
*(int*)&global_const = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_write_through_const_pointer() {
const int local_const = 10; // expected-note {{Memory region is in immutable space}}
int *ptr = (int*)&local_const;
*ptr = 20; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_write_to_const_array() {
const int arr[5] = {1, 2, 3, 4, 5};
int *ptr = (int*)arr;
ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
struct TestStruct {
@@ -40,7 +36,6 @@ void test_write_to_const_struct_member() {
struct TestStruct s = {1, 2};
int *ptr = (int*)&s.x;
*ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
const int global_array[3] = {1, 2, 3};
@@ -48,8 +43,6 @@ const int global_array[3] = {1, 2, 3};
void test_write_to_const_global_array() {
int *ptr = (int*)global_array;
ptr[0] = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-
}
const struct TestStruct global_struct = {1, 2};
@@ -57,22 +50,18 @@ const struct TestStruct global_struct = {1, 2};
void test_write_to_const_global_struct() {
int *ptr = (int*)&global_struct.x;
*ptr = 10; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_write_to_const_param(const int param) { // expected-note {{Memory region is in immutable space}}
*(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_write_to_const_ptr_param(const int *param) {
*(int*)param = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_write_to_const_array_param(const int arr[5]) {
*(int*)arr = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
struct ParamStruct {
@@ -82,13 +71,10 @@ struct ParamStruct {
void test_write_to_const_struct_param(const struct ParamStruct s) {
*(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-
}
void test_write_to_const_struct_ptr_param(const struct ParamStruct *s) {
*(int*)&s->z = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_write_to_nonconst() {
@@ -131,8 +117,4 @@ void test_const_ptr_to_const_data() {
const int data = 42; // expected-note {{Memory region is in immutable space}}
const int *ptr = &data;
*(int*)ptr = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
-}
-
-
-
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/store-to-immutable-basic.cpp b/clang/test/Analysis/store-to-immutable-basic.cpp
index 5014ad66ceb7b..4bfc59c075ed0 100644
--- a/clang/test/Analysis/store-to-immutable-basic.cpp
+++ b/clang/test/Analysis/store-to-immutable-basic.cpp
@@ -1,16 +1,14 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.StoreToImmutable -verify %s
-// Test the inteaction of the StoreToImmutable checker with C++ references.
void test_write_to_const_ref_param(const int ¶m) {
*(int*)¶m = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
+// FIXME: This should warn in C mode too.
void test_write_to_string_literal() {
char *str = (char*)"hello";
str[0] = 'H'; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
struct ParamStruct {
@@ -20,7 +18,6 @@ struct ParamStruct {
void test_write_to_const_struct_ref_param(const ParamStruct &s) {
*(int*)&s.z = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
void test_const_ref_to_nonconst_data() {
@@ -33,5 +30,16 @@ void test_const_ref_to_const_data() {
const int data = 42; // expected-note {{Memory region is in immutable space}}
const int &ref = data;
*(int*)&ref = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
- // expected-note at -1 {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
+
+void test_ref_to_nonconst_data() {
+ int data = 42;
+ int &ref = data;
+ ref = 100; // No warning expected
+}
+
+void test_ref_to_const_data() {
+ const int data = 42; // expected-note {{Memory region is in immutable space}}
+ int &ref = *(int*)&data;
+ ref = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
\ No newline at end of file
>From 5190ee0538e081ba1dce269c7ac3d3aea8cbc4b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.com>
Date: Mon, 28 Jul 2025 15:17:42 +0200
Subject: [PATCH 4/4] [review-fix] add test case for complex memory hierarchy
---
.../test/Analysis/store-to-immutable-basic.cpp | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/clang/test/Analysis/store-to-immutable-basic.cpp b/clang/test/Analysis/store-to-immutable-basic.cpp
index 4bfc59c075ed0..ab0841096d9a1 100644
--- a/clang/test/Analysis/store-to-immutable-basic.cpp
+++ b/clang/test/Analysis/store-to-immutable-basic.cpp
@@ -42,4 +42,22 @@ void test_ref_to_const_data() {
const int data = 42; // expected-note {{Memory region is in immutable space}}
int &ref = *(int*)&data;
ref = 100; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+struct MultipleLayerStruct {
+ MultipleLayerStruct();
+ const int data; // expected-note {{Memory region is in immutable space}}
+ const int buf[10];
+};
+
+MultipleLayerStruct MLS[10]; // mutable global
+
+void test_multiple_layer_struct_array_member() {
+ int *p = (int*)&MLS[2].data;
+ *p = 4; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
+}
+
+void test_multiple_layer_struct_array_array_member() {
+ int *p = (int*)&MLS[2].buf[3];
+ *p = 4; // expected-warning {{Writing to immutable memory is undefined behavior. This memory region is marked as immutable and should not be modified}}
}
\ No newline at end of file
More information about the cfe-commits
mailing list