Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,6 @@ Improvements to Clang's diagnostics
an override of a virtual method.
- Fixed fix-it hint for fold expressions. Clang now correctly places the suggested right
parenthesis when diagnosing malformed fold expressions. (#GH151787)
- ``-Wstring-concatenation`` now diagnoses every missing comma in an initializer list,
rather than stopping after the first. (#GH153745)

- Fixed an issue where emitted format-signedness diagnostics were not associated with an appropriate
diagnostic id. Besides being incorrect from an API standpoint, this was user visible, e.g.:
Expand Down
43 changes: 19 additions & 24 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14708,14 +14708,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
isa<InitListExpr>(var->getInit())) {
const auto *ILE = cast<InitListExpr>(var->getInit());
unsigned NumInits = ILE->getNumInits();
if (NumInits > 2) {
auto concatenatedPartsAt = [&](unsigned Index) -> unsigned {
if (const Expr *E = ILE->getInit(Index))
if (const auto *S = dyn_cast<StringLiteral>(E->IgnoreImpCasts()))
return S->getNumConcatenated();
return 0;
};

if (NumInits > 2)
for (unsigned I = 0; I < NumInits; ++I) {
const auto *Init = ILE->getInit(I);
if (!Init)
Expand All @@ -14728,33 +14721,35 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// Diagnose missing comma in string array initialization.
// Do not warn when all the elements in the initializer are concatenated
// together. Do not warn for macros too.
if (NumConcat == 2) {
if (SL->getBeginLoc().isMacroID())
continue;

unsigned L = I > 0 ? concatenatedPartsAt(I - 1) : 0;
unsigned R = I + 1 < NumInits ? concatenatedPartsAt(I + 1) : 0;

// Skip neighbors with multi-part concatenations.
if (R > 1)
continue;
if (NumConcat == 2 && !SL->getBeginLoc().isMacroID()) {
bool OnlyOneMissingComma = true;
for (unsigned J = I + 1; J < NumInits; ++J) {
const auto *Init = ILE->getInit(J);
if (!Init)
break;
const auto *SLJ = dyn_cast<StringLiteral>(Init->IgnoreImpCasts());
if (!SLJ || SLJ->getNumConcatenated() > 1) {
OnlyOneMissingComma = false;
break;
}
}

// Diagnose when at least one neighbor is a single literal.
if (R == 1 || L == 1) {
if (OnlyOneMissingComma) {
SmallVector<FixItHint, 1> Hints;
// Insert a comma between the two tokens of this element.
Hints.push_back(FixItHint::CreateInsertion(
PP.getLocForEndOfToken(SL->getStrTokenLoc(0)), ", "));
for (unsigned i = 0; i < NumConcat - 1; ++i)
Hints.push_back(FixItHint::CreateInsertion(
PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ","));

Diag(SL->getStrTokenLoc(1),
diag::warn_concatenated_literal_array_init)
<< Hints;
Diag(SL->getBeginLoc(),
diag::note_concatenated_string_literal_silence);
}
// In any case, stop now.
break;
}
}
}
}


Expand Down
28 changes: 0 additions & 28 deletions clang/test/Sema/string-concat.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,31 +168,3 @@ const char *extra_parens_to_suppress_warning[] = {
"promise"),
"shared_future"
};

const char *multiple_missing_commas1[] = {
"1",
"2" // expected-note {{place parentheses around the string literal to silence warning}}
"3", // expected-warning {{suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma?}}
"4",
"5",
"6" // expected-note {{place parentheses around the string literal to silence warning}}
"7", // expected-warning {{suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma?}}
"8",
"9",
"10",
"11",
};

const char *multiple_missing_commas2[] = {
"1",
"2"
"3"
"4"
"5",
"6" // expected-note {{place parentheses around the string literal to silence warning}}
"7", // expected-warning {{suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma?}}
"8",
"9",
"10",
"11",
};