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 {