[clang] [llvm] [clang-tools-extra] [clang] Reject incomplete type arguments for __builtin_dump_struct (PR #72749)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 4 17:59:07 PST 2023
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/72749
>From d23305db7faba1ed1464aeee6d9e0f2ee1994226 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Mon, 6 Nov 2023 16:50:02 +0800
Subject: [PATCH 1/2] [clang] Reject incomplete type arguments for
__builtin_dump_struct
We used to assume that the CXXRecordDecl passed to the 1st argument
always had a definition. This is not true since a pointer to an
incomplete type was not excluded.
---
clang/docs/LanguageExtensions.rst | 2 +-
clang/docs/ReleaseNotes.rst | 3 +++
clang/lib/Sema/SemaChecking.cpp | 5 +++++
clang/test/SemaCXX/builtin-dump-struct.cpp | 4 ++++
4 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 30e288f986782..e80a096357b1d 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2809,7 +2809,7 @@ Example output:
The ``__builtin_dump_struct`` function is used to print the fields of a simple
structure and their values for debugging purposes. The first argument of the
-builtin should be a pointer to the struct to dump. The second argument ``f``
+builtin should be a pointer to a complete record type to dump. The second argument ``f``
should be some callable expression, and can be a function object or an overload
set. The builtin calls ``f``, passing any further arguments ``args...``
followed by a ``printf``-compatible format string and the corresponding
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 74358219ba9fb..f2903c1684dcb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -691,6 +691,9 @@ Bug Fixes to C++ Support
Fixes:
(`#68769 <https://github.com/llvm/llvm-project/issues/68769>`_)
+- Clang now rejects incomplete types for ``__builtin_dump_struct``. Fixes:
+ (`#63506 <https://github.com/llvm/llvm-project/issues/63506>`_)
+
- Clang now defers the instantiation of explicit specifier until constraint checking
completes (except deduction guides). Fixes:
(`#59827 <https://github.com/llvm/llvm-project/issues/59827>`_)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ae588db02bbe7..20ff3ce722da8 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -713,6 +713,11 @@ static ExprResult SemaBuiltinDumpStruct(Sema &S, CallExpr *TheCall) {
return ExprError();
}
const RecordDecl *RD = PtrArgType->getPointeeType()->getAsRecordDecl();
+ if (!RD->isCompleteDefinition()) {
+ S.Diag(PtrArgResult.get()->getBeginLoc(), diag::err_incomplete_type)
+ << PtrArgType->getPointeeType();
+ return ExprError();
+ }
// Second argument is a callable, but we can't fully validate it until we try
// calling it.
diff --git a/clang/test/SemaCXX/builtin-dump-struct.cpp b/clang/test/SemaCXX/builtin-dump-struct.cpp
index b3d2a2d808ce2..477bbcf07a41f 100644
--- a/clang/test/SemaCXX/builtin-dump-struct.cpp
+++ b/clang/test/SemaCXX/builtin-dump-struct.cpp
@@ -149,7 +149,10 @@ B {
}
)"[1]);
+class Incomplete;
+
void errors(B b) {
+ ConstexprString cs;
__builtin_dump_struct(); // expected-error {{too few arguments to function call, expected 2, have 0}}
__builtin_dump_struct(1); // expected-error {{too few arguments to function call, expected 2, have 1}}
__builtin_dump_struct(1, 2); // expected-error {{expected pointer to struct as 1st argument to '__builtin_dump_struct', found 'int'}}
@@ -157,6 +160,7 @@ void errors(B b) {
__builtin_dump_struct(&b, Format, 0); // expected-error {{no matching function for call to 'Format'}}
// expected-note at -1 {{in call to printing function with arguments '(0, "%s", "B")' while dumping struct}}
// expected-note@#Format {{no known conversion from 'int' to 'ConstexprString &' for 1st argument}}
+ __builtin_dump_struct((Incomplete *)nullptr, Format, cs); // expected-error {{incomplete type 'Incomplete' where a complete type is required}}
}
#endif
>From e0bbbd2e5518a98936e1b6f51e8fff66018a7183 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sun, 19 Nov 2023 23:38:50 +0800
Subject: [PATCH 2/2] Use Sema::RequireCompleteType.
---
clang/lib/Sema/SemaChecking.cpp | 12 ++++++------
clang/test/SemaCXX/builtin-dump-struct.cpp | 10 +++++++++-
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 20ff3ce722da8..9f90585b3b7d8 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -712,13 +712,13 @@ static ExprResult SemaBuiltinDumpStruct(Sema &S, CallExpr *TheCall) {
<< 1 << TheCall->getDirectCallee() << PtrArgType;
return ExprError();
}
- const RecordDecl *RD = PtrArgType->getPointeeType()->getAsRecordDecl();
- if (!RD->isCompleteDefinition()) {
- S.Diag(PtrArgResult.get()->getBeginLoc(), diag::err_incomplete_type)
- << PtrArgType->getPointeeType();
+ QualType Pointee = PtrArgType->getPointeeType();
+ const RecordDecl *RD = Pointee->getAsRecordDecl();
+ // Try to instantiate the class template as appropriate; otherwise, access to
+ // its data() may lead to a crash.
+ if (S.RequireCompleteType(PtrArgResult.get()->getBeginLoc(), Pointee,
+ diag::err_incomplete_type))
return ExprError();
- }
-
// Second argument is a callable, but we can't fully validate it until we try
// calling it.
QualType FnArgType = TheCall->getArg(1)->getType();
diff --git a/clang/test/SemaCXX/builtin-dump-struct.cpp b/clang/test/SemaCXX/builtin-dump-struct.cpp
index 477bbcf07a41f..91ffa7c8c05bd 100644
--- a/clang/test/SemaCXX/builtin-dump-struct.cpp
+++ b/clang/test/SemaCXX/builtin-dump-struct.cpp
@@ -149,7 +149,12 @@ B {
}
)"[1]);
-class Incomplete;
+class Incomplete; // #incomplete-type
+
+template <class T>
+class Class {
+ T value = {};
+};
void errors(B b) {
ConstexprString cs;
@@ -161,6 +166,9 @@ void errors(B b) {
// expected-note at -1 {{in call to printing function with arguments '(0, "%s", "B")' while dumping struct}}
// expected-note@#Format {{no known conversion from 'int' to 'ConstexprString &' for 1st argument}}
__builtin_dump_struct((Incomplete *)nullptr, Format, cs); // expected-error {{incomplete type 'Incomplete' where a complete type is required}}
+ // expected-note@#incomplete-type {{forward declaration of 'Incomplete'}}
+ // Ensure the Class<int> gets instantiated; otherwise crash happens.
+ __builtin_dump_struct((Class<int> *)nullptr, Format, cs);
}
#endif
More information about the cfe-commits
mailing list