Skip to content

Commit 7a3b5d7

Browse files
authored
[C] Fix crash-on-invalid due to infinite recursion (#140925)
There are two related issues being fixed in this patch. Both issues relate to use of an invalid structure which contains a member that we error recover such that the field has the same type as the structure. In both cases, we would hit an infinite loop while analyzing the fields because the type of the field matches the type of the record. Fixes #140887
1 parent c42c91c commit 7a3b5d7

File tree

5 files changed

+28
-2
lines changed

5 files changed

+28
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ C23 Feature Support
273273
be completed).
274274
- Fixed a failed assertion with an invalid parameter to the ``#embed``
275275
directive. Fixes #GH126940.
276+
- Fixed a crash when a declaration of a ``constexpr`` variable with an invalid
277+
type. Fixes #GH140887
276278

277279
C11 Feature Support
278280
^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8681,7 +8681,8 @@ static bool CheckC23ConstexprVarType(Sema &SemaRef, SourceLocation VarLoc,
86818681

86828682
if (CanonT->isRecordType()) {
86838683
const RecordDecl *RD = CanonT->getAsRecordDecl();
8684-
if (llvm::any_of(RD->fields(), [&SemaRef, VarLoc](const FieldDecl *F) {
8684+
if (!RD->isInvalidDecl() &&
8685+
llvm::any_of(RD->fields(), [&SemaRef, VarLoc](const FieldDecl *F) {
86858686
return CheckC23ConstexprVarType(SemaRef, VarLoc, F->getType());
86868687
}))
86878688
return true;

clang/lib/Sema/SemaInit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6618,7 +6618,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
66186618
// initializer present. However, we only do this for structure types, not
66196619
// union types, because an unitialized field in a union is generally
66206620
// reasonable, especially in C where unions can be used for type punning.
6621-
if (!Initializer && !Rec->isUnion()) {
6621+
if (!Initializer && !Rec->isUnion() && !Rec->isInvalidDecl()) {
66226622
if (const FieldDecl *FD = getConstField(Rec)) {
66236623
unsigned DiagID = diag::warn_default_init_const_field_unsafe;
66246624
if (Var->getStorageDuration() == SD_Static ||
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s
2+
3+
// This was previously causing a stack overflow when checking the valid
4+
// declaration of an invalid type. Ensure we issue reasonable diagnostics
5+
// instead of crashing.
6+
struct GH140887 { // expected-note {{definition of 'struct GH140887' is not complete until the closing '}'}}
7+
GH140887(); // expected-error {{must use 'struct' tag to refer to type 'GH140887'}} \
8+
expected-error {{expected member name or ';' after declaration specifiers}} \
9+
expected-error {{field has incomplete type 'struct GH140887'}}
10+
};
11+
constexpr struct GH140887 a; // expected-error {{constexpr variable 'a' must be initialized by a constant expression}}
12+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
3+
// This invalid code was causing a stack overflow, check that we issue
4+
// reasonable diagnostics and not crash.
5+
struct GH140887 { // expected-note {{definition of 'struct GH140887' is not complete until the closing '}'}}
6+
struct GH140887 s; // expected-error {{field has incomplete type 'struct GH140887'}}
7+
};
8+
9+
void gh140887() {
10+
struct GH140887 s;
11+
}

0 commit comments

Comments
 (0)