https://github.com/pl98 updated https://github.com/llvm/llvm-project/pull/205426

>From 2e5a6b69599f26841454880379295104ceb5027f Mon Sep 17 00:00:00 2001
From: Phoebe Liang <[email protected]>
Date: Tue, 23 Jun 2026 16:33:23 -0400
Subject: [PATCH 1/2] [Clang][Sema] Guard type size queries on incomplete types
 in -Wunsafe-buffer-usage

When evaluating explicit pointer casts of container `.data()` invocations, skip 
querying pointee size if the source or destination pointee type is incomplete 
or dependent.

Previously, destination pointee types were checked using 
`getAsTagDecl()->isCompleteDefinition()`, which missed incomplete array types 
(`T[]`) and non-C++ tag declarations. Source pointee types were passed directly 
to `Ctx.getTypeSize()` without any completeness guard.
Querying `getTypeSize()` on incomplete types resulted in assertion
failures in debug builds and segmentation faults in release builds. This
change guards both source and destination types.
---
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 22 ++++++++++---------
 ...e-buffer-usage-warning-data-invocation.cpp | 20 +++++++++++++----
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 52fe7765c6c6a..70135d22e724d 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2508,27 +2508,29 @@ class UnsafeBufferUsageReporter : public 
UnsafeBufferUsageHandler {
         MsgParam = 5;
       } else if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Operation)) {
         QualType destType = ECE->getType();
-        bool destTypeComplete = true;
 
         if (!isa<PointerType>(destType))
           return;
         destType = destType.getTypePtr()->getPointeeType();
-        if (const auto *D = destType->getAsTagDecl())
-          destTypeComplete = D->isCompleteDefinition();
 
-        // If destination type is incomplete, it is unsafe to cast to anyway, 
no
-        // need to check its type:
-        if (destTypeComplete) {
+        // If destination type is incomplete or dependent, it is unsafe to cast
+        // to anyway, no need to check its type:
+        if (!destType->isIncompleteType() && !destType->isDependentType()) {
           const uint64_t dSize = Ctx.getTypeSize(destType);
           QualType srcType = ECE->getSubExpr()->getType();
 
           assert(srcType->isPointerType());
 
-          const uint64_t sSize =
-              Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());
+          QualType srcPointeeType = srcType.getTypePtr()->getPointeeType();
 
-          if (sSize >= dSize)
-            return;
+          // Check if source type is incomplete or dependent as well:
+          if (!srcPointeeType->isIncompleteType() &&
+              !srcPointeeType->isDependentType()) {
+            const uint64_t sSize = Ctx.getTypeSize(srcPointeeType);
+
+            if (sSize >= dSize)
+              return;
+          }
         }
         if (const auto *CE = dyn_cast<CXXMemberCallExpr>(
                 ECE->getSubExpr()->IgnoreParens())) {
diff --git 
a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp
index a6a334d247023..41ac0f12743bd 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp
@@ -174,10 +174,22 @@ A false_negatives(std::span<int> span_pt, span<A> span_A) 
{
 
 }
 
-void test_incomplete_type(std::span<char> S) {
-  (struct IncompleteStruct *)S.data(); // expected-warning{{unsafe invocation 
of 'data'}}
-  (class IncompleteClass *)S.data();   // expected-warning{{unsafe invocation 
of 'data'}}
-  (union IncompleteUnion *)S.data();   // expected-warning{{unsafe invocation 
of 'data'}}
+struct IncompleteStruct;
+class IncompleteClass;
+union IncompleteUnion;
+
+void test_incomplete_dest_type(std::span<char> S) {
+  (IncompleteStruct *)S.data(); // expected-warning{{unsafe invocation of 
'data'}}
+  (IncompleteClass *)S.data(); // expected-warning{{unsafe invocation of 
'data'}}
+  (IncompleteUnion *)S.data(); // expected-warning{{unsafe invocation of 
'data'}}
+}
+
+void test_incomplete_source_type(std::span<IncompleteStruct> S) {
+  (float *)S.data(); // expected-warning{{unsafe invocation of 'data'}}
+}
+
+void test_incomplete_array_dest_type(std::span<char> S) {
+  (IncompleteStruct(*)[])S.data(); // expected-warning{{unsafe invocation of 
'data'}}
 }
 
 void test_complete_type(std::span<long> S) {

>From ecb2156fc02fb3c4ae672358df7995c1cce58a0d Mon Sep 17 00:00:00 2001
From: Phoebe Liang <[email protected]>
Date: Wed, 24 Jun 2026 14:34:33 -0400
Subject: [PATCH 2/2] Add dependent test cases.

---
 ...safe-buffer-usage-warning-data-invocation.cpp | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git 
a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp
index 41ac0f12743bd..107611d461d9d 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp
@@ -192,6 +192,22 @@ void test_incomplete_array_dest_type(std::span<char> S) {
   (IncompleteStruct(*)[])S.data(); // expected-warning{{unsafe invocation of 
'data'}}
 }
 
+template <typename DestType>
+void test_dependent_dest_type(std::span<char> S) {
+  (DestType *)S.data(); // expected-warning{{unsafe invocation of 'data'}}
+}
+
+template <typename SourceType>
+void test_dependent_source_type(std::span<SourceType> S) {
+  (float *)S.data(); // expected-warning{{unsafe invocation of 'data'}}
+}
+
+void instantiate_dependent_tests(std::span<char> char_span,
+                                 std::span<IncompleteStruct> incomplete_span) {
+  test_dependent_dest_type<IncompleteStruct>(char_span);
+  test_dependent_source_type<IncompleteStruct>(incomplete_span);
+}
+
 void test_complete_type(std::span<long> S) {
   (struct CompleteStruct *)S.data(); // no warn as the struct size is smaller 
than long
   (class CompleteClass *)S.data();   // no warn as the class size is smaller 
than long

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

Reply via email to