From: Nico Weber
Date: Fri, 20 Jul 2012 06:44:52 +0000 (+0000)
Subject: Revert r160319, it caused PR13417. Add a test for PR13417.
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43972898614d91c00982f10cdf7f2bfb4a9f6275;p=clang
Revert r160319, it caused PR13417. Add a test for PR13417.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160542 91177308-0d34-0410-b5e6-96231b3b80d8
---
diff --git a/docs/UsersManual.html b/docs/UsersManual.html
index 629d9b2574..7a0e325c03 100644
--- a/docs/UsersManual.html
+++ b/docs/UsersManual.html
@@ -230,9 +230,6 @@ print something like:
When this is disabled, Clang will print "test.c:28: warning..." with no
column number.
-
-The printed column numbers count bytes from the beginning of the line; take
-care if your source contains multibyte characters.
@@ -399,9 +396,6 @@ exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expre
The {}'s are generated by -fdiagnostics-print-source-range-info.
-
-The printed column numbers count bytes from the beginning of the line; take
-care if your source contains multibyte characters.
@@ -422,9 +416,6 @@ respectively). Both the file name and the insertion string escape backslash (as
"\\"), tabs (as "\t"), newlines (as "\n"), double
quotes(as "\"") and non-printable characters (as octal
"\xxx").
-
-The printed column numbers count bytes from the beginning of the line; take
-care if your source contains multibyte characters.
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index f604f8aa57..306306d3ac 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -1124,7 +1124,7 @@ std::string TextDiagnostic::buildFixItInsertionLine(
std::string FixItInsertionLine;
if (Hints.empty() || !DiagOpts.ShowFixits)
return FixItInsertionLine;
- unsigned PrevHintEndCol = 0;
+ unsigned PrevHintEnd = 0;
for (ArrayRef::iterator I = Hints.begin(), E = Hints.end();
I != E; ++I) {
@@ -1136,15 +1136,11 @@ std::string TextDiagnostic::buildFixItInsertionLine(
if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second)) {
// Insert the new code into the line just below the code
// that the user wrote.
- // Note: When modifying this function, be very careful about what is a
- // "column" (printed width, platform-dependent) and what is a
- // "byte offset" (SourceManager "column").
- unsigned HintByteOffset
+ unsigned HintColNo
= SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
-
- // The hint must start inside the source or right at the end
- assert(HintByteOffset < static_cast(map.bytes())+1);
- unsigned HintCol = map.byteToColumn(HintByteOffset);
+ // hint must start inside the source or right at the end
+ assert(HintColNo(map.bytes())+1);
+ HintColNo = map.byteToColumn(HintColNo);
// If we inserted a long previous hint, push this one forwards, and add
// an extra space to show that this is not part of the previous
@@ -1153,27 +1149,32 @@ std::string TextDiagnostic::buildFixItInsertionLine(
//
// Note that if this hint is located immediately after the previous
// hint, no space will be added, since the location is more important.
- if (HintCol < PrevHintEndCol)
- HintCol = PrevHintEndCol + 1;
-
- // FIXME: This function handles multibyte characters in the source, but
- // not in the fixits. This assertion is intended to catch unintended
- // use of multibyte characters in fixits. If we decide to do this, we'll
- // have to track separate byte widths for the source and fixit lines.
- assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
- I->CodeToInsert.size());
-
- // This relies on one byte per column in our fixit hints.
- // This should NOT use HintByteOffset, because the source might have
- // Unicode characters in earlier columns.
- unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
+ if (HintColNo < PrevHintEnd)
+ HintColNo = PrevHintEnd + 1;
+
+ // FIXME: if the fixit includes tabs or other characters that do not
+ // take up a single column per byte when displayed then
+ // I->CodeToInsert.size() is not a column number and we're mixing
+ // units (columns + bytes). We should get printable versions
+ // of each fixit before using them.
+ unsigned LastColumnModified
+ = HintColNo + I->CodeToInsert.size();
+
+ if (LastColumnModified <= static_cast(map.bytes())) {
+ // If we're right in the middle of a multibyte character skip to
+ // the end of it.
+ while (map.byteToColumn(LastColumnModified) == -1)
+ ++LastColumnModified;
+ LastColumnModified = map.byteToColumn(LastColumnModified);
+ }
+
if (LastColumnModified > FixItInsertionLine.size())
FixItInsertionLine.resize(LastColumnModified, ' ');
-
+ assert(HintColNo+I->CodeToInsert.size() <= FixItInsertionLine.size());
std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
- FixItInsertionLine.begin() + HintCol);
+ FixItInsertionLine.begin() + HintColNo);
- PrevHintEndCol = LastColumnModified;
+ PrevHintEnd = LastColumnModified;
} else {
FixItInsertionLine.clear();
break;
diff --git a/test/FixIt/fixit-unicode.c b/test/FixIt/fixit-unicode.c
index 2af5e08faa..d8e4592336 100644
--- a/test/FixIt/fixit-unicode.c
+++ b/test/FixIt/fixit-unicode.c
@@ -1,11 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck -strict-whitespace %s
-// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck -check-prefix=CHECK-MACHINE %s
+// PR13312
struct Foo {
int bar;
};
-// PR13312
void test1() {
struct Foo foo;
(&foo)â>bar = 42;
@@ -13,21 +12,4 @@ void test1() {
// Make sure we emit the fixit right in front of the snowman.
// CHECK: {{^ \^}}
// CHECK: {{^ ;}}
-
-// CHECK-MACHINE: fix-it:"{{.*}}fixit-unicode.c":{11:9-11:9}:";"
-}
-
-
-int printf(const char *, ...);
-void test2() {
- printf("â: %d", 1L);
-// CHECK: warning: format specifies type 'int' but the argument has type 'long'
-// Don't crash emitting a fixit after the delta.
-// CHECK: printf("
-// CHECK: : %d", 1L);
-// Unfortunately, we can't actually check the location of the printed fixit,
-// because different systems will render the delta differently (either as a
-// character, or as .) The fixit should line up with the %d regardless.
-
-// CHECK-MACHINE: fix-it:"{{.*}}fixit-unicode.c":{23:16-23:18}:"%ld"
}
diff --git a/test/Parser/objc-diag-width.mm b/test/Parser/objc-diag-width.mm
new file mode 100644
index 0000000000..3929ba2b09
--- /dev/null
+++ b/test/Parser/objc-diag-width.mm
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s 2>&1 | FileCheck %s
+
+// Just shouldn't crash. -verify suppresses the crash, so don't use it.
+// PR13417
+// CHECK-NOT: Assertion failed
+@interface ExtensionActionContextMenu @end
+@implementation ExtensionActionContextMenu
+namespace {