Skip to content

Commit b9af72b

Browse files
[Diagnostics] Reworked -Wstring-concatenation
1 parent f5e4451 commit b9af72b

File tree

3 files changed

+66
-32
lines changed

3 files changed

+66
-32
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12886,6 +12886,53 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
1288612886
AttributeCommonInfo::AS_Pragma));
1288712887
}
1288812888

12889+
if (var->hasInit() && isa<InitListExpr>(var->getInit())) {
12890+
const auto *ILE = cast<InitListExpr>(var->getInit());
12891+
unsigned NumInits = ILE->getNumInits();
12892+
if (NumInits > 2)
12893+
for (unsigned I = 0; I < NumInits; ++I) {
12894+
const auto *Init = ILE->getInit(I);
12895+
if (!Init)
12896+
break;
12897+
const auto *SL = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
12898+
if (!SL)
12899+
break;
12900+
12901+
unsigned NumConcat = SL->getNumConcatenated();
12902+
// Diagnose missing comma in string array initialization.
12903+
// Do not warn when all the elements in the initializer are concatenated
12904+
// together. Do not warn for macros too.
12905+
if (NumConcat == 2 && !SL->getBeginLoc().isMacroID()) {
12906+
bool OnlyOneMissingComma = true;
12907+
for (unsigned J = I + 1; J < NumInits; ++J) {
12908+
const auto *Init = ILE->getInit(J);
12909+
if (!Init)
12910+
break;
12911+
const auto *SLJ = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
12912+
if (!SLJ || SLJ->getNumConcatenated() > 1) {
12913+
OnlyOneMissingComma = false;
12914+
break;
12915+
}
12916+
}
12917+
12918+
if (OnlyOneMissingComma) {
12919+
SmallVector<FixItHint, 1> Hints;
12920+
for (unsigned i = 0; i < NumConcat - 1; ++i)
12921+
Hints.push_back(FixItHint::CreateInsertion(
12922+
PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ","));
12923+
12924+
Diag(SL->getStrTokenLoc(1),
12925+
diag::warn_concatenated_literal_array_init)
12926+
<< Hints;
12927+
Diag(SL->getBeginLoc(),
12928+
diag::note_concatenated_string_literal_silence);
12929+
}
12930+
// Warn just once.
12931+
break;
12932+
}
12933+
}
12934+
}
12935+
1288912936
// All the following checks are C++ only.
1289012937
if (!getLangOpts().CPlusPlus) {
1289112938
// If this variable must be emitted, add it as an initializer for the

clang/lib/Sema/SemaExpr.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6870,7 +6870,6 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
68706870
bool DiagnosedArrayDesignator = false;
68716871
bool DiagnosedNestedDesignator = false;
68726872
bool DiagnosedMixedDesignator = false;
6873-
bool DiagnosedMissingComma = false;
68746873

68756874
// Check that any designated initializers are syntactically valid in the
68766875
// current language mode.
@@ -6912,37 +6911,6 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
69126911
<< DIE->getSourceRange();
69136912
Diag(InitArgList[I]->getBeginLoc(), diag::note_designated_init_mixed)
69146913
<< InitArgList[I]->getSourceRange();
6915-
} else if (const auto *SL = dyn_cast<StringLiteral>(InitArgList[I])) {
6916-
unsigned NumConcat = SL->getNumConcatenated();
6917-
// Diagnose missing comma in string array initialization.
6918-
// Do not warn when all the elements in the initializer are concatenated
6919-
// together. Do not warn for macros too.
6920-
if (!DiagnosedMissingComma && NumConcat == 2 && E > 2 && !SL->getBeginLoc().isMacroID()) {
6921-
bool OnlyOneMissingComma = true;
6922-
for (unsigned J = 0; J < E; ++J) {
6923-
if (J == I)
6924-
continue;
6925-
const auto *SLJ = dyn_cast<StringLiteral>(InitArgList[J]);
6926-
if (!SLJ || SLJ->getNumConcatenated() > 1) {
6927-
OnlyOneMissingComma = false;
6928-
break;
6929-
}
6930-
}
6931-
6932-
if (OnlyOneMissingComma) {
6933-
SmallVector<FixItHint, 1> Hints;
6934-
for (unsigned i = 0; i < NumConcat - 1; ++i)
6935-
Hints.push_back(FixItHint::CreateInsertion(
6936-
PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ","));
6937-
6938-
Diag(SL->getStrTokenLoc(1),
6939-
diag::warn_concatenated_literal_array_init)
6940-
<< Hints;
6941-
Diag(SL->getBeginLoc(),
6942-
diag::note_concatenated_string_literal_silence);
6943-
DiagnosedMissingComma = true;
6944-
}
6945-
}
69466914
}
69476915
}
69486916

clang/test/Sema/string-concat.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,25 @@ const char *not_warn4[] = {"title",
130130
"url"
131131
};
132132

133+
typedef struct {
134+
const char *a;
135+
const char *b;
136+
const char *c;
137+
} A;
138+
139+
const A not_warn5 = (A){"",
140+
""
141+
"",
142+
""};
143+
144+
#ifdef __cplusplus
145+
const A not_warn6 = A{"",
146+
""
147+
"",
148+
""};
149+
#endif
150+
151+
133152
// Do not warn when all the elements in the initializer are concatenated together.
134153
const char *all_elems_in_init_concatenated[] = {"a" "b" "c"};
135154

0 commit comments

Comments
 (0)