Skip to content

Commit b632476

Browse files
[AST][RecoveryExpr] Fix a crash on c89/c90 invalid InitListExpr (#88008) (#88014)
Use refactored `CheckForConstantInitializer()` to skip checking expr with error. --------- Co-authored-by: Aaron Ballman <[email protected]>
1 parent 5a34ff1 commit b632476

File tree

5 files changed

+28
-19
lines changed

5 files changed

+28
-19
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ Bug Fixes in This Version
417417
- Fixed a regression in CTAD that a friend declaration that befriends itself may cause
418418
incorrect constraint substitution. (#GH86769).
419419

420+
- Fixed an assertion failure on invalid InitListExpr in C89 mode (#GH88008).
421+
420422
Bug Fixes to Compiler Builtins
421423
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
422424

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "clang/Sema/Scope.h"
5656
#include "clang/Sema/SemaBase.h"
5757
#include "clang/Sema/SemaConcept.h"
58+
#include "clang/Sema/SemaDiagnostic.h"
5859
#include "clang/Sema/TypoCorrection.h"
5960
#include "clang/Sema/Weak.h"
6061
#include "llvm/ADT/ArrayRef.h"
@@ -3427,7 +3428,8 @@ class Sema final : public SemaBase {
34273428
bool ConstexprSupported, bool CLinkageMayDiffer);
34283429

34293430
/// type checking declaration initializers (C99 6.7.8)
3430-
bool CheckForConstantInitializer(Expr *e, QualType t);
3431+
bool CheckForConstantInitializer(
3432+
Expr *Init, unsigned DiagID = diag::err_init_element_not_constant);
34313433

34323434
QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
34333435
QualType Type, TypeSourceInfo *TSI,

clang/lib/Sema/SemaDecl.cpp

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12671,7 +12671,7 @@ void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) {
1267112671
}
1267212672
}
1267312673

12674-
bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
12674+
bool Sema::CheckForConstantInitializer(Expr *Init, unsigned DiagID) {
1267512675
// FIXME: Need strict checking. In C89, we need to check for
1267612676
// any assignment, increment, decrement, function-calls, or
1267712677
// commas outside of a sizeof. In C99, it's the same list,
@@ -12689,8 +12689,7 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
1268912689
const Expr *Culprit;
1269012690
if (Init->isConstantInitializer(Context, false, &Culprit))
1269112691
return false;
12692-
Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant)
12693-
<< Culprit->getSourceRange();
12692+
Diag(Culprit->getExprLoc(), DiagID) << Culprit->getSourceRange();
1269412693
return true;
1269512694
}
1269612695

@@ -13808,29 +13807,24 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
1380813807
// OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized.
1380913808
// This is true even in C++ for OpenCL.
1381013809
} else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) {
13811-
CheckForConstantInitializer(Init, DclT);
13810+
CheckForConstantInitializer(Init);
1381213811

13813-
// Otherwise, C++ does not restrict the initializer.
13812+
// Otherwise, C++ does not restrict the initializer.
1381413813
} else if (getLangOpts().CPlusPlus) {
1381513814
// do nothing
1381613815

1381713816
// C99 6.7.8p4: All the expressions in an initializer for an object that has
1381813817
// static storage duration shall be constant expressions or string literals.
1381913818
} else if (VDecl->getStorageClass() == SC_Static) {
13820-
CheckForConstantInitializer(Init, DclT);
13819+
CheckForConstantInitializer(Init);
1382113820

13822-
// C89 is stricter than C99 for aggregate initializers.
13823-
// C89 6.5.7p3: All the expressions [...] in an initializer list
13824-
// for an object that has aggregate or union type shall be
13825-
// constant expressions.
13821+
// C89 is stricter than C99 for aggregate initializers.
13822+
// C89 6.5.7p3: All the expressions [...] in an initializer list
13823+
// for an object that has aggregate or union type shall be
13824+
// constant expressions.
1382613825
} else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
1382713826
isa<InitListExpr>(Init)) {
13828-
const Expr *Culprit;
13829-
if (!Init->isConstantInitializer(Context, false, &Culprit)) {
13830-
Diag(Culprit->getExprLoc(),
13831-
diag::ext_aggregate_init_not_constant)
13832-
<< Culprit->getSourceRange();
13833-
}
13827+
CheckForConstantInitializer(Init, diag::ext_aggregate_init_not_constant);
1383413828
}
1383513829

1383613830
if (auto *E = dyn_cast<ExprWithCleanups>(Init))
@@ -13963,7 +13957,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
1396313957
// Avoid duplicate diagnostics for constexpr variables.
1396413958
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
1396513959
!VDecl->isConstexpr())
13966-
CheckForConstantInitializer(Init, DclT);
13960+
CheckForConstantInitializer(Init);
1396713961
}
1396813962

1396913963
QualType InitType = Init->getType();

clang/lib/Sema/SemaExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7331,7 +7331,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
73317331
if (!LiteralExpr->isTypeDependent() &&
73327332
!LiteralExpr->isValueDependent() &&
73337333
!literalType->isDependentType()) // C99 6.5.2.5p3
7334-
if (CheckForConstantInitializer(LiteralExpr, literalType))
7334+
if (CheckForConstantInitializer(LiteralExpr))
73357335
return ExprError();
73367336
} else if (literalType.getAddressSpace() != LangAS::opencl_private &&
73377337
literalType.getAddressSpace() != LangAS::Default) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 %s -verify -fsyntax-only -std=c90
2+
3+
struct S {
4+
int v;
5+
};
6+
7+
struct T; // expected-note {{forward declaration of 'struct T'}}
8+
9+
void gh88008_nocrash(struct T *t) {
10+
struct S s = { .v = t->y }; // expected-error {{incomplete definition of type 'struct T'}}
11+
}

0 commit comments

Comments
 (0)