https://github.com/juanvazquez created 
https://github.com/llvm/llvm-project/pull/178432

The default_constructed_after_move attribute can be applied to a class to 
indicate that, when an object of this type is moved from, it is guaranteed to 
be in the same state as a default-constructed object.

This attribute can be interpreted by static analyzers that warn about potential 
uses of an object after it is moved. For types with this attribute, analyzers 
can assume that accessing a moved object is as safe as accessing a 
default-constructed object.

A typical use case is to annotate smart pointer classes, which often guarantee 
that a pointer is null, and hence in a default-constructed state, after the 
move.

The plan is to use it with clang-tidy's bugprone-use-after-move check next.

>From 1ead85f430a49b3154bf46856d3c9d3fcf050857 Mon Sep 17 00:00:00 2001
From: Juan Vazquez <[email protected]>
Date: Wed, 28 Jan 2026 15:09:54 +0100
Subject: [PATCH] [clang] Add clang::default_constructed_after_move attribute

The default_constructed_after_move attribute can be applied to a class to
indicate that, when an object of this type is moved from, it is guaranteed to
be in the same state as a default-constructed object.

This attribute can be interpreted by static analyzers that warn
about potential uses of an object after it is moved. For types
with this attribute, analyzers can assume that accessing a moved object
is as safe as accessing a default-constructed object.

A typical use case is to annotate smart pointer classes, which often guarantee
that a pointer is null, and hence in a default-constructed state, after the
move.

The plan is to use it with clang-tidy's bugprone-use-after-move check next.
---
 clang/include/clang/Basic/Attr.td             |  7 ++++
 clang/include/clang/Basic/AttrDocs.td         | 18 ++++++++++
 .../attr-default-constructed-after-move.cpp   | 35 +++++++++++++++++++
 3 files changed, 60 insertions(+)
 create mode 100644 clang/test/SemaCXX/attr-default-constructed-after-move.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 2335168e4510c..e9f0bf273a42a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4799,6 +4799,13 @@ def Reinitializes : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def DefaultConstructedAfterMove : InheritableAttr {
+  let Spellings = [Clang<"default_constructed_after_move", 0>];
+  let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
+  let Documentation = [DefaultConstructedAfterMoveDocs];
+  let SimpleHandler = 1;
+}
+
 def NoDestroy : InheritableAttr {
   let Spellings = [Clang<"no_destroy", 0>];
   let Subjects = SubjectList<[Var]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 6e2c73f924352..24c7c872a0d77 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7152,6 +7152,24 @@ a container class:
   }];
 }
 
+def DefaultConstructedAfterMoveDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+The ``default_constructed_after_move`` attribute can be applied to a class to
+indicate that, when an object of this type is moved from, it is guaranteed to
+be in the same state as a default-constructed object.
+
+This attribute can be interpreted by static analyzers that warn
+about potential uses of an object after it is moved. For types
+with this attribute, analyzers can assume that accessing a moved object
+is as safe as accessing a default-constructed object.
+
+A typical use case is to annotate smart pointer classes, which often guarantee
+that a pointer is null, and hence in a default-constructed state, after the
+move.
+}];
+}
+
 def AlwaysDestroyDocs : Documentation {
   let Category = DocCatVariable;
   let Content = [{
diff --git a/clang/test/SemaCXX/attr-default-constructed-after-move.cpp 
b/clang/test/SemaCXX/attr-default-constructed-after-move.cpp
new file mode 100644
index 0000000000000..2bedf579c0f02
--- /dev/null
+++ b/clang/test/SemaCXX/attr-default-constructed-after-move.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+[[clang::default_constructed_after_move]] int a; // expected-error 
{{'clang::default_constructed_after_move' attribute only applies to classes}}
+
+[[clang::default_constructed_after_move]] void f(); // expected-error {{only 
applies to}}
+
+enum [[clang::default_constructed_after_move]] E { A, B }; // expected-error 
{{only applies to}}
+
+void foo( [[clang::default_constructed_after_move]] int param); // 
expected-error {{only applies to}}
+
+struct MyStruct {
+  [[clang::default_constructed_after_move]] int member; // expected-error 
{{only applies to}}
+};
+
+class [[clang::default_constructed_after_move]] C {
+public:
+  C();
+  C(C &&);
+  C &operator=(C &&);
+};
+
+C [[clang::default_constructed_after_move]] c_var; // expected-error 
{{'clang::default_constructed_after_move' attribute cannot be applied to types}}
+
+struct [[clang::default_constructed_after_move]] S {
+  S();
+  S(S &&);
+  S &operator=(S &&);
+};
+
+union [[clang::default_constructed_after_move]] U {
+  int a;
+  float b;
+  U(U &&);
+  U &operator=(U &&);
+};

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

Reply via email to