@@ -168,16 +168,99 @@ bool Sema::IsStringInit(Expr *Init, const ArrayType *AT) {
168
168
return ::IsStringInit (Init, AT, Context) == SIF_None;
169
169
}
170
170
171
+ static StringLiteral *CloneStringLiteral (const StringLiteral *SL,
172
+ ASTContext &C) {
173
+ SourceLocation *SLocs = new (C) SourceLocation[SL->getNumConcatenated ()];
174
+ std::copy (SL->tokloc_begin (), SL->tokloc_end (), SLocs);
175
+ return StringLiteral::Create (
176
+ C, SL->getBytes (), SL->getKind (), SL->isPascal (), SL->getType (),
177
+ ArrayRef<SourceLocation>(SLocs, SL->getNumConcatenated ()));
178
+ }
179
+
180
+ // Exactly follow `IgnoreParensSingleStep` (`AST/IgnoreExpr.h`)
181
+ // We only recursively visit those subexpressions which `IgnoreParensSingleStep`
182
+ // drills down to.
183
+ static Expr *CloneWithRecurseToInnermostSL (Expr *E, ASTContext &C) {
184
+ if (auto *SL = dyn_cast<StringLiteral>(E)) {
185
+ return CloneStringLiteral (SL, C);
186
+ }
187
+
188
+ if (auto *PE = dyn_cast<ParenExpr>(E)) {
189
+ return new (C)
190
+ ParenExpr (PE->getBeginLoc (), PE->getEndLoc (),
191
+ CloneWithRecurseToInnermostSL (PE->getSubExpr (), C));
192
+ }
193
+
194
+ if (auto *UO = dyn_cast<UnaryOperator>(E)) {
195
+ if (UO->getOpcode () == UO_Extension) {
196
+ return UnaryOperator::Create (
197
+ C, CloneWithRecurseToInnermostSL (UO->getSubExpr (), C), UO_Extension,
198
+ UO->getType (), UO->getValueKind (), UO->getObjectKind (),
199
+ UO->getBeginLoc (), UO->canOverflow (), UO->getFPOptionsOverride ());
200
+ }
201
+ }
202
+
203
+ else if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) {
204
+ if (!GSE->isResultDependent ()) {
205
+ ArrayRef<Expr *> GSEAEs = GSE->getAssocExprs ();
206
+ Expr **NewGSEAEs = new (C) Expr *[GSEAEs.size ()];
207
+ std::copy (GSEAEs.begin (), GSEAEs.end (), NewGSEAEs);
208
+ NewGSEAEs[GSE->getResultIndex ()] =
209
+ CloneWithRecurseToInnermostSL (GSE->getResultExpr (), C);
210
+
211
+ auto GSECreate = [&](auto *ExprOrTSI) -> Expr * {
212
+ return GenericSelectionExpr::Create (
213
+ C, GSE->getGenericLoc (), ExprOrTSI, GSE->getAssocTypeSourceInfos (),
214
+ ArrayRef<Expr *>(NewGSEAEs, GSEAEs.size ()), GSE->getDefaultLoc (),
215
+ GSE->getRParenLoc (), GSE->containsUnexpandedParameterPack (),
216
+ GSE->getResultIndex ());
217
+ };
218
+
219
+ return GSE->isExprPredicate () ? GSECreate (GSE->getControllingExpr ())
220
+ : GSECreate (GSE->getControllingType ());
221
+ }
222
+ }
223
+
224
+ else if (auto *CE = dyn_cast<ChooseExpr>(E)) {
225
+ if (!CE->isConditionDependent ()) {
226
+ // Drills to `CE->getChosenSubExpr()`
227
+ const bool isCondTrue = CE->isConditionTrue ();
228
+ return new (C) ChooseExpr (
229
+ CE->getBeginLoc (), CE->getCond (),
230
+ isCondTrue ? CloneWithRecurseToInnermostSL (CE->getLHS (), C)
231
+ : CE->getLHS (),
232
+ isCondTrue ? CE->getRHS ()
233
+ : CloneWithRecurseToInnermostSL (CE->getRHS (), C),
234
+ CE->getType (), CE->getValueKind (), CE->getObjectKind (),
235
+ CE->getRParenLoc (), CE->isConditionTrue ());
236
+ }
237
+ }
238
+
239
+ else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
240
+ if (PE->isTransparent () && PE->getFunctionName ()) {
241
+ return PredefinedExpr::Create (
242
+ C, PE->getLocation (), PE->getType (), PE->getIdentKind (),
243
+ PE->isTransparent (), CloneStringLiteral (PE->getFunctionName (), C));
244
+ }
245
+ }
246
+
247
+ return E;
248
+ }
249
+
171
250
// / Update the type of a string literal, including any surrounding parentheses,
172
251
// / to match the type of the object which it is initializing.
173
- static void updateStringLiteralType (Expr *E, QualType Ty) {
252
+ static Expr *updateStringLiteralType (Expr *E, QualType Ty, Sema &S) {
253
+ Expr *ENew = CloneWithRecurseToInnermostSL (E, S.Context );
254
+ E = ENew;
255
+
174
256
while (true ) {
175
257
E->setType (Ty);
176
258
E->setValueKind (VK_PRValue);
177
259
if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E))
178
260
break ;
179
261
E = IgnoreParensSingleStep (E);
180
262
}
263
+ return ENew;
181
264
}
182
265
183
266
// / Fix a compound literal initializing an array so it's correctly marked
@@ -209,9 +292,9 @@ static bool initializingConstexprVariable(const InitializedEntity &Entity) {
209
292
static void CheckC23ConstexprInitStringLiteral (const StringLiteral *SE,
210
293
Sema &SemaRef, QualType &TT);
211
294
212
- static void CheckStringInit (Expr *Str, QualType &DeclT, const ArrayType *AT,
213
- Sema &S, const InitializedEntity &Entity,
214
- bool CheckC23ConstexprInit = false ) {
295
+ static Expr * CheckStringInit (Expr *Str, QualType &DeclT, const ArrayType *AT,
296
+ Sema &S, const InitializedEntity &Entity,
297
+ bool CheckC23ConstexprInit = false ) {
215
298
// Get the length of the string as parsed.
216
299
auto *ConstantArrayTy =
217
300
cast<ConstantArrayType>(Str->getType ()->getAsArrayTypeUnsafe ());
@@ -228,8 +311,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
228
311
// Return a new array type (C99 6.7.8p22).
229
312
DeclT = S.Context .getConstantArrayType (
230
313
IAT->getElementType (), ConstVal, nullptr , ArraySizeModifier::Normal, 0 );
231
- updateStringLiteralType (Str, DeclT);
232
- return ;
314
+ return updateStringLiteralType (Str, DeclT, S);
233
315
}
234
316
235
317
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
@@ -302,7 +384,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
302
384
// something like:
303
385
// char x[1] = "foo";
304
386
// then this will set the string literal's type to char[1].
305
- updateStringLiteralType (Str, DeclT);
387
+ return updateStringLiteralType (Str, DeclT, S );
306
388
}
307
389
308
390
void emitUninitializedExplicitInitFields (Sema &S, const RecordDecl *R) {
@@ -1608,10 +1690,12 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
1608
1690
1609
1691
if (IsStringInit (expr, arrayType, SemaRef.Context ) == SIF_None) {
1610
1692
// FIXME: Should we do this checking in verify-only mode?
1611
- if (!VerifyOnly)
1612
- CheckStringInit (expr, ElemType, arrayType, SemaRef, Entity,
1613
- SemaRef.getLangOpts ().C23 &&
1614
- initializingConstexprVariable (Entity));
1693
+ if (!VerifyOnly) {
1694
+ expr = CheckStringInit (expr, ElemType, arrayType, SemaRef, Entity,
1695
+ SemaRef.getLangOpts ().C23 &&
1696
+ initializingConstexprVariable (Entity));
1697
+ IList->setInit (Index, expr);
1698
+ }
1615
1699
if (StructuredList)
1616
1700
UpdateStructuredListElement (StructuredList, StructuredIndex, expr);
1617
1701
++Index;
@@ -2121,10 +2205,13 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
2121
2205
// because doing so would involve allocating one character
2122
2206
// constant for each string.
2123
2207
// FIXME: Should we do these checks in verify-only mode too?
2124
- if (!VerifyOnly)
2125
- CheckStringInit (
2126
- IList->getInit (Index), DeclType, arrayType, SemaRef, Entity,
2127
- SemaRef.getLangOpts ().C23 && initializingConstexprVariable (Entity));
2208
+ if (!VerifyOnly) {
2209
+ IList->setInit (
2210
+ Index, CheckStringInit (IList->getInit (Index), DeclType, arrayType,
2211
+ SemaRef, Entity,
2212
+ SemaRef.getLangOpts ().C23 &&
2213
+ initializingConstexprVariable (Entity)));
2214
+ }
2128
2215
if (StructuredList) {
2129
2216
UpdateStructuredListElement (StructuredList, StructuredIndex,
2130
2217
IList->getInit (Index));
@@ -8421,10 +8508,10 @@ ExprResult InitializationSequence::Perform(Sema &S,
8421
8508
case SK_StringInit: {
8422
8509
QualType Ty = Step->Type ;
8423
8510
bool UpdateType = ResultType && Entity.getType ()->isIncompleteArrayType ();
8424
- CheckStringInit (CurInit.get (), UpdateType ? *ResultType : Ty,
8425
- S.Context .getAsArrayType (Ty), S, Entity,
8426
- S.getLangOpts ().C23 &&
8427
- initializingConstexprVariable (Entity));
8511
+ CurInit = CheckStringInit (CurInit.get (), UpdateType ? *ResultType : Ty,
8512
+ S.Context .getAsArrayType (Ty), S, Entity,
8513
+ S.getLangOpts ().C23 &&
8514
+ initializingConstexprVariable (Entity));
8428
8515
break ;
8429
8516
}
8430
8517
0 commit comments