@@ -1737,6 +1737,51 @@ static void validateMultilineIndents(const Token &Str,
1737
1737
commonIndentation);
1738
1738
}
1739
1739
1740
+ // / Emit diagnostics for single-quote string and suggest replacement
1741
+ // / with double-quoted equivalent.
1742
+ static void diagnoseSingleQuoteStringLiteral (const char *TokStart,
1743
+ const char *TokEnd,
1744
+ DiagnosticEngine *D) {
1745
+ assert (*TokStart == ' \' ' && TokEnd[-1 ] == ' \' ' );
1746
+ if (!D)
1747
+ return ;
1748
+
1749
+ SmallString<32 > replacement;
1750
+ replacement.push_back (' "' );
1751
+ const char *Ptr = TokStart + 1 ;
1752
+ const char *OutputPtr = Ptr;
1753
+
1754
+ while (*Ptr++ != ' \' ' && Ptr < TokEnd) {
1755
+ if (Ptr[-1 ] == ' \\ ' ) {
1756
+ if (*Ptr == ' \' ' ) {
1757
+ replacement.append (OutputPtr, Ptr - 1 );
1758
+ OutputPtr = Ptr + 1 ;
1759
+ // Un-escape single quotes.
1760
+ replacement.push_back (' \' ' );
1761
+ } else if (*Ptr == ' (' ) {
1762
+ // Preserve the contents of interpolation.
1763
+ Ptr = skipToEndOfInterpolatedExpression (Ptr + 1 , replacement.end (),
1764
+ /* IsMultiline=*/ false );
1765
+ assert (*Ptr == ' )' );
1766
+ }
1767
+ // Skip over escaped characters.
1768
+ ++Ptr;
1769
+ } else if (Ptr[-1 ] == ' "' ) {
1770
+ replacement.append (OutputPtr, Ptr - 1 );
1771
+ OutputPtr = Ptr;
1772
+ // Escape double quotes.
1773
+ replacement.append (" \\\" " );
1774
+ }
1775
+ }
1776
+ assert (Ptr == TokEnd && Ptr[-1 ] == ' \' ' );
1777
+ replacement.append (OutputPtr, Ptr - 1 );
1778
+ replacement.push_back (' "' );
1779
+
1780
+ D->diagnose (Lexer::getSourceLoc (TokStart), diag::lex_single_quote_string)
1781
+ .fixItReplaceChars (Lexer::getSourceLoc (TokStart),
1782
+ Lexer::getSourceLoc (TokEnd), replacement);
1783
+ }
1784
+
1740
1785
// / lexStringLiteral:
1741
1786
// / string_literal ::= ["]([^"\\\n\r]|character_escape)*["]
1742
1787
// / string_literal ::= ["]["]["].*["]["]["] - approximately
@@ -1793,46 +1838,9 @@ void Lexer::lexStringLiteral(unsigned CustomDelimiterLen) {
1793
1838
}
1794
1839
1795
1840
if (QuoteChar == ' \' ' ) {
1796
- // Emit diagnostics for single-quote string and suggest replacement
1797
- // with double-quoted equivalent.
1798
1841
assert (!IsMultilineString && CustomDelimiterLen == 0 &&
1799
1842
" Single quoted string cannot have custom delimitor, nor multiline" );
1800
- assert (*TokStart == ' \' ' && CurPtr[-1 ] == ' \' ' );
1801
-
1802
- SmallString<32 > replacement;
1803
- replacement.push_back (' "' );
1804
- const char *Ptr = TokStart + 1 ;
1805
- const char *OutputPtr = Ptr;
1806
-
1807
- while (*Ptr++ != ' \' ' ) {
1808
- if (Ptr[-1 ] == ' \\ ' ) {
1809
- if (*Ptr == ' \' ' ) {
1810
- replacement.append (OutputPtr, Ptr - 1 );
1811
- OutputPtr = Ptr + 1 ;
1812
- // Un-escape single quotes.
1813
- replacement.push_back (' \' ' );
1814
- } else if (*Ptr == ' (' ) {
1815
- // Preserve the contents of interpolation.
1816
- Ptr = skipToEndOfInterpolatedExpression (Ptr + 1 , replacement.end (),
1817
- /* IsMultiline=*/ false );
1818
- assert (*Ptr == ' )' );
1819
- }
1820
- // Skip over escaped characters.
1821
- ++Ptr;
1822
- } else if (Ptr[-1 ] == ' "' ) {
1823
- replacement.append (OutputPtr, Ptr - 1 );
1824
- OutputPtr = Ptr;
1825
- // Escape double quotes.
1826
- replacement.append (" \\\" " );
1827
- }
1828
- }
1829
- assert (Ptr == CurPtr);
1830
- replacement.append (OutputPtr, Ptr - 1 );
1831
- replacement.push_back (' "' );
1832
-
1833
- diagnose (TokStart, diag::lex_single_quote_string)
1834
- .fixItReplaceChars (getSourceLoc (TokStart), getSourceLoc (CurPtr),
1835
- replacement);
1843
+ diagnoseSingleQuoteStringLiteral (TokStart, CurPtr, Diags);
1836
1844
}
1837
1845
1838
1846
if (wasErroneous)
0 commit comments