[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-08-07 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added a comment.

I don't have commit rights yet so I would be grateful for help in this matter :)




Comment at: lib/Lex/Lexer.cpp:469-477
+if (!isVerticalWhitespace(LexStart[0]))
+  continue;
 
-  const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
-  ++LexStart;
-  break;
-}
+if (Lexer::isNewLineEscaped(BufStart, LexStart))
+  continue;
 
+// LexStart should point at first character of logical line.

alexfh wrote:
> The logic is hard to get here. I'd use a single `if` and reverse the 
> condition to get rid of the `continue`s:
> 
>   if (isVerticalWhitespace(*LexStart) && !Lexer::isNewLineEscaped(BufStart, 
> LexStart)) {
> ++LexStart;
> break;
>   }
Yes, I know - I thought that more vertical code composition would help


https://reviews.llvm.org/D30748



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-08-07 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 110029.
idlecode added a comment.

Redability fix in `findBeginningOfLine`


https://reviews.llvm.org/D30748

Files:
  include/clang/Lex/Lexer.h
  lib/Lex/Lexer.cpp
  unittests/Lex/LexerTest.cpp

Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -420,4 +420,57 @@
 #endif
 }
 
+TEST_F(LexerTest, IsNewLineEscapedValid) {
+  auto hasNewLineEscaped = [](const char *S) {
+return Lexer::isNewLineEscaped(S, S + strlen(S) - 1);
+  };
+
+  EXPECT_TRUE(hasNewLineEscaped("\\\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\n"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\r\n"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\n\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\ \t\v\f\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\ \t\v\f\r\n"));
+
+  EXPECT_FALSE(hasNewLineEscaped("\\\r\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\\\r\r\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\\\n\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\r\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\n\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\r\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\n\n"));
+}
+
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const unsigned IdentifierLength = 8;
+  std::string TextToLex = "rabarbar\n"
+  "foo\\\nbar\n"
+  "foo\\\rbar\n"
+  "fo\\\r\nbar\n"
+  "foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+  std::vector LexedTokens = CheckLex(TextToLex, ExpectedTokens);
+
+  for (const Token  : LexedTokens) {
+std::pair OriginalLocation =
+SourceMgr.getDecomposedLoc(Tok.getLocation());
+for (unsigned Offset = 0; Offset < IdentifierLength; ++Offset) {
+  SourceLocation LookupLocation =
+  Tok.getLocation().getLocWithOffset(Offset);
+
+  std::pair FoundLocation =
+  SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(LookupLocation, SourceMgr, LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(FoundLocation.second, OriginalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -463,19 +463,15 @@
   const char *BufStart = Buffer.data();
   if (Offset >= Buffer.size())
 return nullptr;
-  const char *StrData = BufStart + Offset;
 
-  if (StrData[0] == '\n' || StrData[0] == '\r')
-return StrData;
-
-  const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
+  const char *LexStart = BufStart + Offset;
+  for (; LexStart != BufStart; --LexStart) {
+if (isVerticalWhitespace(LexStart[0]) &&
+!Lexer::isNewLineEscaped(BufStart, LexStart)) {
+  // LexStart should point at first character of logical line.
   ++LexStart;
   break;
 }
-
---LexStart;
   }
   return LexStart;
 }
@@ -487,7 +483,7 @@
   std::pair LocInfo = SM.getDecomposedLoc(Loc);
   if (LocInfo.first.isInvalid())
 return Loc;
-  
+
   bool Invalid = false;
   StringRef Buffer = SM.getBufferData(LocInfo.first, );
   if (Invalid)
@@ -499,52 +495,52 @@
   const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second);
   if (!LexStart || LexStart == StrData)
 return Loc;
-  
+
   // Create a lexer starting at the beginning of this token.
   SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second);
   Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart,
  Buffer.end());
   TheLexer.SetCommentRetentionState(true);
-  
+
   // Lex tokens until we find the token that contains the source location.
   Token TheTok;
   do {
 TheLexer.LexFromRawLexer(TheTok);
-
+
 if (TheLexer.getBufferLocation() > StrData) {
   // Lexing this token has taken the lexer past the source location we're
   // looking for. If the current token encompasses our source location,
   // return the beginning of that token.
   if (TheLexer.getBufferLocation() - TheTok.getLength() <= StrData)
 return TheTok.getLocation();
-  
+
   // We ended up skipping over the source location entirely, which means
   // that it points into whitespace. We're done here.
   break;
 }
   } while (TheTok.getKind() != tok::eof);
-  
+
   // We've passed our source location; just return the original source location.
   return Loc;
 }
 
 SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc,
 

[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-08-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 109748.
idlecode added a comment.

Applied clang-format


https://reviews.llvm.org/D30748

Files:
  include/clang/Lex/Lexer.h
  lib/Lex/Lexer.cpp
  unittests/Lex/LexerTest.cpp

Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -420,4 +420,57 @@
 #endif
 }
 
+TEST_F(LexerTest, IsNewLineEscapedValid) {
+  auto hasNewLineEscaped = [](const char *S) {
+return Lexer::isNewLineEscaped(S, S + strlen(S) - 1);
+  };
+
+  EXPECT_TRUE(hasNewLineEscaped("\\\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\n"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\r\n"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\n\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\ \t\v\f\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\ \t\v\f\r\n"));
+
+  EXPECT_FALSE(hasNewLineEscaped("\\\r\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\\\r\r\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\\\n\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\r\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\n\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\r\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\n\n"));
+}
+
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const unsigned IdentifierLength = 8;
+  std::string TextToLex = "rabarbar\n"
+  "foo\\\nbar\n"
+  "foo\\\rbar\n"
+  "fo\\\r\nbar\n"
+  "foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+  std::vector LexedTokens = CheckLex(TextToLex, ExpectedTokens);
+
+  for (const Token  : LexedTokens) {
+std::pair OriginalLocation =
+SourceMgr.getDecomposedLoc(Tok.getLocation());
+for (unsigned Offset = 0; Offset < IdentifierLength; ++Offset) {
+  SourceLocation LookupLocation =
+  Tok.getLocation().getLocWithOffset(Offset);
+
+  std::pair FoundLocation =
+  SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(LookupLocation, SourceMgr, LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(FoundLocation.second, OriginalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -463,19 +463,18 @@
   const char *BufStart = Buffer.data();
   if (Offset >= Buffer.size())
 return nullptr;
-  const char *StrData = BufStart + Offset;
 
-  if (StrData[0] == '\n' || StrData[0] == '\r')
-return StrData;
+  const char *LexStart = BufStart + Offset;
+  for (; LexStart != BufStart; --LexStart) {
+if (!isVerticalWhitespace(LexStart[0]))
+  continue;
 
-  const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
-  ++LexStart;
-  break;
-}
+if (Lexer::isNewLineEscaped(BufStart, LexStart))
+  continue;
 
---LexStart;
+// LexStart should point at first character of logical line.
+++LexStart;
+break;
   }
   return LexStart;
 }
@@ -487,7 +486,7 @@
   std::pair LocInfo = SM.getDecomposedLoc(Loc);
   if (LocInfo.first.isInvalid())
 return Loc;
-  
+
   bool Invalid = false;
   StringRef Buffer = SM.getBufferData(LocInfo.first, );
   if (Invalid)
@@ -499,52 +498,52 @@
   const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second);
   if (!LexStart || LexStart == StrData)
 return Loc;
-  
+
   // Create a lexer starting at the beginning of this token.
   SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second);
   Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart,
  Buffer.end());
   TheLexer.SetCommentRetentionState(true);
-  
+
   // Lex tokens until we find the token that contains the source location.
   Token TheTok;
   do {
 TheLexer.LexFromRawLexer(TheTok);
-
+
 if (TheLexer.getBufferLocation() > StrData) {
   // Lexing this token has taken the lexer past the source location we're
   // looking for. If the current token encompasses our source location,
   // return the beginning of that token.
   if (TheLexer.getBufferLocation() - TheTok.getLength() <= StrData)
 return TheTok.getLocation();
-  
+
   // We ended up skipping over the source location entirely, which means
   // that it points into whitespace. We're done here.
   break;
 }
   } while (TheTok.getKind() != tok::eof);
-  
+
   // We've passed our source location; just return the original source location.
   return Loc;
 }
 
 SourceLocation 

[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-08-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 109740.
idlecode marked an inline comment as done.

https://reviews.llvm.org/D30748

Files:
  include/clang/Lex/Lexer.h
  lib/Lex/Lexer.cpp
  unittests/Lex/LexerTest.cpp

Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -420,4 +420,57 @@
 #endif
 }
 
+TEST_F(LexerTest, IsNewLineEscapedValid) {
+  auto hasNewLineEscaped = [] (const char *S) {
+return Lexer::isNewLineEscaped(S, S + strlen(S) - 1);
+  };
+
+  EXPECT_TRUE(hasNewLineEscaped("\\\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\n"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\r\n"));
+  EXPECT_TRUE(hasNewLineEscaped("\\\n\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\ \t\v\f\r"));
+  EXPECT_TRUE(hasNewLineEscaped("\\ \t\v\f\r\n"));
+
+  EXPECT_FALSE(hasNewLineEscaped("\\\r\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\\\r\r\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\\\n\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\r\n"));
+  EXPECT_FALSE(hasNewLineEscaped("\n\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\r\r"));
+  EXPECT_FALSE(hasNewLineEscaped("\n\n"));
+}
+
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const unsigned IdentifierLength = 8;
+  std::string TextToLex = "rabarbar\n"
+  "foo\\\nbar\n"
+  "foo\\\rbar\n"
+  "fo\\\r\nbar\n"
+  "foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+  std::vector LexedTokens = CheckLex(TextToLex, ExpectedTokens);
+
+  for (const Token  : LexedTokens) {
+std::pair OriginalLocation =
+SourceMgr.getDecomposedLoc(Tok.getLocation());
+for (unsigned Offset = 0; Offset < IdentifierLength; ++Offset) {
+  SourceLocation LookupLocation =
+  Tok.getLocation().getLocWithOffset(Offset);
+
+  std::pair FoundLocation =
+  SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(LookupLocation, SourceMgr, LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(FoundLocation.second, OriginalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -463,19 +463,18 @@
   const char *BufStart = Buffer.data();
   if (Offset >= Buffer.size())
 return nullptr;
-  const char *StrData = BufStart + Offset;
 
-  if (StrData[0] == '\n' || StrData[0] == '\r')
-return StrData;
+  const char *LexStart = BufStart + Offset;
+  for (; LexStart != BufStart; --LexStart) {
+if (!isVerticalWhitespace(LexStart[0]))
+  continue;
 
-  const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
-  ++LexStart;
-  break;
-}
+if (Lexer::isNewLineEscaped(BufStart, LexStart))
+  continue;
 
---LexStart;
+// LexStart should point at first character of logical line.
+++LexStart;
+break;
   }
   return LexStart;
 }
@@ -487,7 +486,7 @@
   std::pair LocInfo = SM.getDecomposedLoc(Loc);
   if (LocInfo.first.isInvalid())
 return Loc;
-  
+
   bool Invalid = false;
   StringRef Buffer = SM.getBufferData(LocInfo.first, );
   if (Invalid)
@@ -499,52 +498,52 @@
   const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second);
   if (!LexStart || LexStart == StrData)
 return Loc;
-  
+
   // Create a lexer starting at the beginning of this token.
   SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second);
   Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart,
  Buffer.end());
   TheLexer.SetCommentRetentionState(true);
-  
+
   // Lex tokens until we find the token that contains the source location.
   Token TheTok;
   do {
 TheLexer.LexFromRawLexer(TheTok);
-
+
 if (TheLexer.getBufferLocation() > StrData) {
   // Lexing this token has taken the lexer past the source location we're
   // looking for. If the current token encompasses our source location,
   // return the beginning of that token.
   if (TheLexer.getBufferLocation() - TheTok.getLength() <= StrData)
 return TheTok.getLocation();
-  
+
   // We ended up skipping over the source location entirely, which means
   // that it points into whitespace. We're done here.
   break;
 }
   } while (TheTok.getKind() != tok::eof);
-  
+
   // We've passed our source location; just return the original source location.
   return Loc;
 }
 
 SourceLocation 

[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-08-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode marked 3 inline comments as done.
idlecode added inline comments.



Comment at: lib/Lex/Lexer.cpp:460
+/// \brief Check if new line pointed by Str is escaped.
+bool isNewLineEscaped(const char *BufferStart, const char *Str) {
+  assert(isVerticalWhitespace(Str[0]));

alexfh wrote:
> The way the function is exposed to the test may lead to confusion. I'd either 
> properly declare it in the header (and place it in a namespace, if it is not 
> yet) or at least leave a comment here that the function is not static, since 
> it needs to be exposed to the test.
Ok, I have made `isNewLineEscaped` a static method of `Lexer` - in Lexer.h 
there were no global function declaration and I didn't like the idea of 
introducing one.
I would make it protected/private member but it have to be visible to unit 
tests (and introducing friend classes just for this method doesn't seem worth 
it).


https://reviews.llvm.org/D30748



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-06-10 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 102110.
idlecode added a comment.

Added tests for `isNewLineEscaped` - this fixed some corner cases


https://reviews.llvm.org/D30748

Files:
  lib/Lex/Lexer.cpp
  unittests/Lex/LexerTest.cpp

Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -25,6 +25,8 @@
 
 using namespace clang;
 
+bool isNewLineEscaped(const char *BufferStart, const char *Str);
+
 namespace {
 
 // The test fixture.
@@ -365,4 +367,53 @@
   EXPECT_EQ(SourceMgr.getFileIDSize(SourceMgr.getFileID(helper1ArgLoc)), 8U);
 }
 
+TEST_F(LexerTest, IsNewLineEscapedValid) {
+  std::vector> TestLines = {
+  {true, "\\\r"},{true, "\\\n"},{true, "\\\r\n"},
+  {true, "\\\n\r"},  {true, "\\ \t\v\f\r"}, {true, "\\ \t\v\f\r\n"},
+  {false, "\\\r\r"}, {false, "\\\r\r\n"},   {false, "\\\n\n"},
+  {false, "\r"}, {false, "\n"}, {false, "\r\n"},
+  {false, "\n\r"},   {false, "\r\r"},   {false, "\n\n"}};
+
+  int i = 1;
+  for (const std::pair  : TestLines) {
+bool IsEscaped = Pattern.first;
+const std::string  = Pattern.second;
+EXPECT_EQ(IsEscaped,
+  isNewLineEscaped(Line.c_str(), Line.c_str() + Line.length() - 1))
+<< "Pattern #" << i << " not recognized as escaped new line\n";
+++i;
+  }
+}
+
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const unsigned IdentifierLength = 8;
+  std::string TextToLex = "rabarbar\n"
+  "foo\\\nbar\n"
+  "foo\\\rbar\n"
+  "fo\\\r\nbar\n"
+  "foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+  std::vector LexedTokens = CheckLex(TextToLex, ExpectedTokens);
+
+  for (const Token  : LexedTokens) {
+std::pair OriginalLocation =
+SourceMgr.getDecomposedLoc(Tok.getLocation());
+for (unsigned Offset = 0; Offset < IdentifierLength; ++Offset) {
+  SourceLocation LookupLocation =
+  Tok.getLocation().getLocWithOffset(Offset);
+
+  std::pair FoundLocation =
+  SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(LookupLocation, SourceMgr, LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(FoundLocation.second, OriginalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -456,25 +456,45 @@
   return false;
 }
 
+/// \brief Check if new line pointed by Str is escaped.
+bool isNewLineEscaped(const char *BufferStart, const char *Str) {
+  assert(isVerticalWhitespace(Str[0]));
+  if (Str - 1 < BufferStart)
+return false;
+
+  if ((Str[0] == '\n' && Str[-1] == '\r') ||
+  (Str[0] == '\r' && Str[-1] == '\n')) {
+if (Str - 2 < BufferStart)
+  return false;
+--Str;
+  }
+  --Str;
+
+  // Rewind to first non-space character:
+  while (isHorizontalWhitespace(*Str) && Str > BufferStart)
+--Str;
+
+  return *Str == '\\';
+}
+
 /// Returns the pointer that points to the beginning of line that contains
 /// the given offset, or null if the offset if invalid.
 static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) {
   const char *BufStart = Buffer.data();
   if (Offset >= Buffer.size())
 return nullptr;
-  const char *StrData = BufStart + Offset;
 
-  if (StrData[0] == '\n' || StrData[0] == '\r')
-return StrData;
+  const char *LexStart = BufStart + Offset;
+  for (; LexStart != BufStart; --LexStart) {
+if (!isVerticalWhitespace(LexStart[0]))
+  continue;
 
-  const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
-  ++LexStart;
-  break;
-}
+if (isNewLineEscaped(BufStart, LexStart))
+  continue;
 
---LexStart;
+// LexStart should point at first character of logical line.
+++LexStart;
+break;
   }
   return LexStart;
 }
@@ -486,7 +506,7 @@
   std::pair LocInfo = SM.getDecomposedLoc(Loc);
   if (LocInfo.first.isInvalid())
 return Loc;
-  
+
   bool Invalid = false;
   StringRef Buffer = SM.getBufferData(LocInfo.first, );
   if (Invalid)
@@ -498,52 +518,52 @@
   const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second);
   if (!LexStart || LexStart == StrData)
 return Loc;
-  
+
   // Create a lexer starting at the beginning of this token.
   SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second);
   Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart,

[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-05-10 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added a comment.

Oh, sorry about this - I forgot. I will send patch during this weekend


https://reviews.llvm.org/D30748



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-03-11 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 91466.
idlecode added a comment.

Addressed Alexander's comments


https://reviews.llvm.org/D30748

Files:
  lib/Lex/Lexer.cpp
  unittests/Lex/LexerTest.cpp

Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -380,4 +380,34 @@
   EXPECT_EQ(SourceMgr.getFileIDSize(SourceMgr.getFileID(helper1ArgLoc)), 8U);
 }
 
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const unsigned IdentifierLength = 8;
+  std::string TextToLex = "rabarbar\n"
+  "foo\\\nbar\n"
+  "foo\\\rbar\n"
+  "fo\\\r\nbar\n"
+  "foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+  std::vector LexedTokens = CheckLex(TextToLex, ExpectedTokens);
+
+  for (const Token  : LexedTokens) {
+std::pair OriginalLocation =
+SourceMgr.getDecomposedLoc(Tok.getLocation());
+for (unsigned Offset = 0; Offset < IdentifierLength; ++Offset) {
+  SourceLocation LookupLocation =
+  Tok.getLocation().getLocWithOffset(Offset);
+
+  std::pair FoundLocation =
+  SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(LookupLocation, SourceMgr, LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(FoundLocation.second, OriginalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -452,39 +452,56 @@
   return false;
 }
 
+/// \brief Check if new line pointed by Str is escaped.
+static bool isNewLineEscaped(const char *BufferStart, const char *Str) {
+  assert(isVerticalWhitespace(Str[0]));
+  if (Str - 1 < BufferStart)
+return false;
+  if (Str[-1] == '\\')
+return true;
+  if (!isVerticalWhitespace(Str[-1]))
+return false;
+  if (Str - 2 < BufferStart)
+return false;
+  if (Str[-2] == '\\')
+return true;
+  return false;
+}
+
 static SourceLocation getBeginningOfFileToken(SourceLocation Loc,
   const SourceManager ,
   const LangOptions ) {
   assert(Loc.isFileID());
   std::pair LocInfo = SM.getDecomposedLoc(Loc);
   if (LocInfo.first.isInvalid())
 return Loc;
-  
+
   bool Invalid = false;
   StringRef Buffer = SM.getBufferData(LocInfo.first, );
   if (Invalid)
 return Loc;
 
   // Back up from the current location until we hit the beginning of a line
   // (or the buffer). We'll relex from that point.
-  const char *BufStart = Buffer.data();
   if (LocInfo.second >= Buffer.size())
 return Loc;
-  
-  const char *StrData = BufStart+LocInfo.second;
-  if (StrData[0] == '\n' || StrData[0] == '\r')
-return Loc;
+
+  const char *BufStart = Buffer.data();
+  const char *StrData = BufStart + LocInfo.second;
 
   const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
-  ++LexStart;
-  break;
-}
+  for (; LexStart != BufStart; --LexStart) {
+if (!isVerticalWhitespace(LexStart[0]))
+  continue;
 
---LexStart;
+if (isNewLineEscaped(BufStart, LexStart))
+  continue;
+
+// LexStart should point at first character of logical line.
+++LexStart;
+break;
   }
-  
+
   // Create a lexer starting at the beginning of this token.
   SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second);
   Lexer TheLexer(LexerStartLoc, LangOpts, BufStart, LexStart, Buffer.end());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-03-11 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode marked 3 inline comments as done.
idlecode added inline comments.



Comment at: lib/Lex/Lexer.cpp:457
+static bool isNewLineEscaped(const char *BufferStart, const char *Str) {
+  while (Str > BufferStart && isWhitespace(*Str))
+--Str;

alexfh wrote:
> We only care about two specific sequences here: `\\\r\n` or `\\\n`, not a 
> backslash followed by arbitrary whitespace.
I just saw that some functions (e.g. line 1285 in this file) accept whitespaces 
between escape character and new line. How about now?


https://reviews.llvm.org/D30748



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30748: [Lexer] Finding beginning of token with escaped new line

2017-03-08 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode created this revision.

Lexer::GetBeginningOfToken produced invalid location when
backtracking across escaped new lines.

This fixes PR26228


https://reviews.llvm.org/D30748

Files:
  lib/Lex/Lexer.cpp
  unittests/Lex/LexerTest.cpp


Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -380,4 +380,36 @@
   EXPECT_EQ(SourceMgr.getFileIDSize(SourceMgr.getFileID(helper1ArgLoc)), 8U);
 }
 
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const auto IdentifierLength = 8;
+  std::string textToLex =
+"rabarbar\n"
+"foo\\\nbar\n"
+"foo\\\rbar\n"
+"fo\\\r\nbar\n"
+"foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+
+  auto lexedTokens = CheckLex(textToLex, ExpectedTokens);
+
+  for (const auto  : lexedTokens) {
+auto originalLocation = SourceMgr.getDecomposedLoc(tok.getLocation());
+for (unsigned offset = 0; offset < IdentifierLength; ++offset) {
+  auto lookupLocation = tok.getLocation().getLocWithOffset(offset);
+
+  auto foundLocation = SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(
+lookupLocation,
+SourceMgr,
+LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(foundLocation.second, originalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -452,6 +452,13 @@
   return false;
 }
 
+/// \brief Check if new line pointed by Str is escaped.
+static bool isNewLineEscaped(const char *BufferStart, const char *Str) {
+  while (Str > BufferStart && isWhitespace(*Str))
+--Str;
+  return Str[0] == '\\';
+}
+
 static SourceLocation getBeginningOfFileToken(SourceLocation Loc,
   const SourceManager ,
   const LangOptions ) {
@@ -467,22 +474,23 @@
 
   // Back up from the current location until we hit the beginning of a line
   // (or the buffer). We'll relex from that point.
-  const char *BufStart = Buffer.data();
   if (LocInfo.second >= Buffer.size())
 return Loc;
   
-  const char *StrData = BufStart+LocInfo.second;
-  if (StrData[0] == '\n' || StrData[0] == '\r')
-return Loc;
+  const char *BufStart = Buffer.data();
+  const char *StrData = BufStart + LocInfo.second;
 
   const char *LexStart = StrData;
-  while (LexStart != BufStart) {
-if (LexStart[0] == '\n' || LexStart[0] == '\r') {
-  ++LexStart;
-  break;
-}
+  for (; LexStart != BufStart; --LexStart) {
+if (!isVerticalWhitespace(LexStart[0]))
+  continue;
 
---LexStart;
+if (isNewLineEscaped(BufStart, LexStart))
+  continue;
+
+// LexStart should point at first character of logical line.
+++LexStart;
+break;
   }
   
   // Create a lexer starting at the beginning of this token.


Index: unittests/Lex/LexerTest.cpp
===
--- unittests/Lex/LexerTest.cpp
+++ unittests/Lex/LexerTest.cpp
@@ -380,4 +380,36 @@
   EXPECT_EQ(SourceMgr.getFileIDSize(SourceMgr.getFileID(helper1ArgLoc)), 8U);
 }
 
+TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
+  // Each line should have the same length for
+  // further offset calculation to be more straightforward.
+  const auto IdentifierLength = 8;
+  std::string textToLex =
+"rabarbar\n"
+"foo\\\nbar\n"
+"foo\\\rbar\n"
+"fo\\\r\nbar\n"
+"foo\\\n\rba\n";
+  std::vector ExpectedTokens{5, tok::identifier};
+
+  auto lexedTokens = CheckLex(textToLex, ExpectedTokens);
+
+  for (const auto  : lexedTokens) {
+auto originalLocation = SourceMgr.getDecomposedLoc(tok.getLocation());
+for (unsigned offset = 0; offset < IdentifierLength; ++offset) {
+  auto lookupLocation = tok.getLocation().getLocWithOffset(offset);
+
+  auto foundLocation = SourceMgr.getDecomposedExpansionLoc(
+  Lexer::GetBeginningOfToken(
+lookupLocation,
+SourceMgr,
+LangOpts));
+
+  // Check that location returned by the GetBeginningOfToken
+  // is the same as original token location reported by Lexer.
+  EXPECT_EQ(foundLocation.second, originalLocation.second);
+}
+  }
+}
+
 } // anonymous namespace
Index: lib/Lex/Lexer.cpp
===
--- lib/Lex/Lexer.cpp
+++ lib/Lex/Lexer.cpp
@@ -452,6 +452,13 @@
   return false;
 }
 
+/// \brief Check if new line pointed by Str is escaped.
+static bool isNewLineEscaped(const char *BufferStart, const char *Str) {
+  while (Str > BufferStart && 

[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-16 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode closed this revision.
idlecode added a comment.

Committed as r295113


https://reviews.llvm.org/D29724



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30002: [clang-tidy] Fix handling of methods with try-statement as a body in modernize-use-override

2017-02-15 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode created this revision.
idlecode added a project: clang-tools-extra.
Herald added a subscriber: JDevlieghere.

Fix generated by modernize-use-override caused syntax error when method
used try-statement as a body. `override` keyword was inserted after last
declaration token which happened to be a `try` keyword.

This fixes PR27119.


https://reviews.llvm.org/D30002

Files:
  clang-tidy/modernize/UseOverrideCheck.cpp
  test/clang-tidy/modernize-use-override.cpp


Index: test/clang-tidy/modernize-use-override.cpp
===
--- test/clang-tidy/modernize-use-override.cpp
+++ test/clang-tidy/modernize-use-override.cpp
@@ -288,3 +288,17 @@
 };
 template <> void MembersOfSpecializations<3>::a() {}
 void ff() { MembersOfSpecializations<3>().a(); };
+
+// In case try statement is used as a method body,
+// make sure that override fix is placed before try keyword.
+struct TryStmtAsBody : public Base {
+  void a() try
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void a() override try
+  { b(); } catch(...) { c(); }
+
+  virtual void d() try
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void d() override try
+  { e(); } catch(...) { f(); }
+};
Index: clang-tidy/modernize/UseOverrideCheck.cpp
===
--- clang-tidy/modernize/UseOverrideCheck.cpp
+++ clang-tidy/modernize/UseOverrideCheck.cpp
@@ -147,14 +147,13 @@
   // end of the declaration of the function, but prefer to put it on the
   // same line as the declaration if the beginning brace for the start of
   // the body falls on the next line.
-  Token LastNonCommentToken;
-  for (Token T : Tokens) {
-if (!T.is(tok::comment)) {
-  LastNonCommentToken = T;
-}
-  }
-  InsertLoc = LastNonCommentToken.getEndLoc();
   ReplacementText = " override";
+  auto LastTokenIter = std::prev(Tokens.end());
+  // When try statement is used instead of compound statement as
+  // method body - insert override keyword before it.
+  if (LastTokenIter->is(tok::kw_try))
+LastTokenIter = std::prev(LastTokenIter);
+  InsertLoc = LastTokenIter->getEndLoc();
 }
 
 if (!InsertLoc.isValid()) {


Index: test/clang-tidy/modernize-use-override.cpp
===
--- test/clang-tidy/modernize-use-override.cpp
+++ test/clang-tidy/modernize-use-override.cpp
@@ -288,3 +288,17 @@
 };
 template <> void MembersOfSpecializations<3>::a() {}
 void ff() { MembersOfSpecializations<3>().a(); };
+
+// In case try statement is used as a method body,
+// make sure that override fix is placed before try keyword.
+struct TryStmtAsBody : public Base {
+  void a() try
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this
+  // CHECK-FIXES: {{^}}  void a() override try
+  { b(); } catch(...) { c(); }
+
+  virtual void d() try
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: prefer using
+  // CHECK-FIXES: {{^}}  void d() override try
+  { e(); } catch(...) { f(); }
+};
Index: clang-tidy/modernize/UseOverrideCheck.cpp
===
--- clang-tidy/modernize/UseOverrideCheck.cpp
+++ clang-tidy/modernize/UseOverrideCheck.cpp
@@ -147,14 +147,13 @@
   // end of the declaration of the function, but prefer to put it on the
   // same line as the declaration if the beginning brace for the start of
   // the body falls on the next line.
-  Token LastNonCommentToken;
-  for (Token T : Tokens) {
-if (!T.is(tok::comment)) {
-  LastNonCommentToken = T;
-}
-  }
-  InsertLoc = LastNonCommentToken.getEndLoc();
   ReplacementText = " override";
+  auto LastTokenIter = std::prev(Tokens.end());
+  // When try statement is used instead of compound statement as
+  // method body - insert override keyword before it.
+  if (LastTokenIter->is(tok::kw_try))
+LastTokenIter = std::prev(LastTokenIter);
+  InsertLoc = LastTokenIter->getEndLoc();
 }
 
 if (!InsertLoc.isValid()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-11 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added a comment.

Yes, please.
Thanks for you time :)


https://reviews.llvm.org/D29724



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-11 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 88101.
idlecode added a comment.

Addressed Richard's inline comment.


https://reviews.llvm.org/D29724

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  include/clang/Frontend/LangStandard.h
  include/clang/Frontend/LangStandards.def
  lib/Frontend/CompilerInvocation.cpp
  test/Driver/unknown-std.c
  test/Driver/unknown-std.cl
  test/Driver/unknown-std.cpp

Index: test/Driver/unknown-std.cpp
===
--- /dev/null
+++ test/Driver/unknown-std.cpp
@@ -0,0 +1,26 @@
+// This file checks output given when processing C++/ObjC++ files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'c++98' for 'ISO C++ 1998 with amendments' standard
+// CHECK-NEXT: note: use 'c++03' for 'ISO C++ 1998 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++98' for 'ISO C++ 1998 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++0x' for 'ISO C++ 2011 with amendments' standard
+// CHECK-NEXT: note: use 'c++11' for 'ISO C++ 2011 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++0x' for 'ISO C++ 2011 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu++11' for 'ISO C++ 2011 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++1y' for 'ISO C++ 2014 with amendments' standard
+// CHECK-NEXT: note: use 'c++14' for 'ISO C++ 2014 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++1y' for 'ISO C++ 2014 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++1z' for 'Working draft for ISO C++ 2017' standard
+// CHECK-NEXT: note: use 'gnu++1z' for 'Working draft for ISO C++ 2017 with GNU extensions' standard
+// CHECK-NEXT: note: use 'cuda' for 'NVIDIA CUDA(tm)' standard
+
+// Make sure that no other output is present.
+// CHECK-NOT: {{^.+$}}
+
Index: test/Driver/unknown-std.cl
===
--- /dev/null
+++ test/Driver/unknown-std.cl
@@ -0,0 +1,16 @@
+// This file checks output given when processing OpenCL files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'cl' for 'OpenCL 1.0' standard
+// CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard
+// CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard
+// CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard
+
+// Make sure that no other output is present.
+// CHECK-NOT: {{^.+$}}
+
Index: test/Driver/unknown-std.c
===
--- /dev/null
+++ test/Driver/unknown-std.c
@@ -0,0 +1,34 @@
+// This file checks output given when processing C/ObjC files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'c89' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'c90' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'iso9899:1990' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'iso9899:199409' for 'ISO C 1990 with amendment 1' standard
+// CHECK-NEXT: note: use 'gnu89' for 'ISO C 1990 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu90' for 'ISO C 1990 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c99' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'c9x' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'iso9899:1999' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'iso9899:199x' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'gnu99' for 'ISO C 1999 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu9x' for 'ISO C 1999 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c11' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'c1x' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'iso9899:2011' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'iso9899:201x' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'gnu11' for 'ISO C 2011 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu1x' for 'ISO C 2011 with GNU extensions' standard
+// CHECK-NEXT: note: use 'cl' for 'OpenCL 1.0' standard
+// CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard
+// CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard
+// CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard
+
+// Make sure that no other output is present.
+// 

[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-11 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 88100.
idlecode added a comment.

Displayed standards will now match processed file kind


https://reviews.llvm.org/D29724

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  include/clang/Frontend/LangStandard.h
  include/clang/Frontend/LangStandards.def
  lib/Frontend/CompilerInvocation.cpp
  test/Driver/unknown-std.c
  test/Driver/unknown-std.cl
  test/Driver/unknown-std.cpp

Index: test/Driver/unknown-std.cpp
===
--- /dev/null
+++ test/Driver/unknown-std.cpp
@@ -0,0 +1,26 @@
+// This file checks output given when processing C++/ObjC++ files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'c++98' for 'ISO C++ 1998 with amendments' standard
+// CHECK-NEXT: note: use 'c++03' for 'ISO C++ 1998 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++98' for 'ISO C++ 1998 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++0x' for 'ISO C++ 2011 with amendments' standard
+// CHECK-NEXT: note: use 'c++11' for 'ISO C++ 2011 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++0x' for 'ISO C++ 2011 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu++11' for 'ISO C++ 2011 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++1y' for 'ISO C++ 2014 with amendments' standard
+// CHECK-NEXT: note: use 'c++14' for 'ISO C++ 2014 with amendments' standard
+// CHECK-NEXT: note: use 'gnu++1y' for 'ISO C++ 2014 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard
+// CHECK-NEXT: note: use 'c++1z' for 'Working draft for ISO C++ 2017' standard
+// CHECK-NEXT: note: use 'gnu++1z' for 'Working draft for ISO C++ 2017 with GNU extensions' standard
+// CHECK-NEXT: note: use 'cuda' for 'NVIDIA CUDA(tm)' standard
+
+// Make sure that no other output is present.
+// CHECK-NOT: {{^.+$}}
+
Index: test/Driver/unknown-std.cl
===
--- /dev/null
+++ test/Driver/unknown-std.cl
@@ -0,0 +1,16 @@
+// This file checks output given when processing OpenCL files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'cl' for 'OpenCL 1.0' standard
+// CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard
+// CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard
+// CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard
+
+// Make sure that no other output is present.
+// CHECK-NOT: {{^.+$}}
+
Index: test/Driver/unknown-std.c
===
--- /dev/null
+++ test/Driver/unknown-std.c
@@ -0,0 +1,34 @@
+// This file checks output given when processing C/ObjC files.
+// When user selects invalid language standard
+// print out supported values with short description.
+
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck --match-full-lines %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK-NEXT: note: use 'c89' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'c90' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'iso9899:1990' for 'ISO C 1990' standard
+// CHECK-NEXT: note: use 'iso9899:199409' for 'ISO C 1990 with amendment 1' standard
+// CHECK-NEXT: note: use 'gnu89' for 'ISO C 1990 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu90' for 'ISO C 1990 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c99' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'c9x' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'iso9899:1999' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'iso9899:199x' for 'ISO C 1999' standard
+// CHECK-NEXT: note: use 'gnu99' for 'ISO C 1999 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu9x' for 'ISO C 1999 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c11' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'c1x' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'iso9899:2011' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'iso9899:201x' for 'ISO C 2011' standard
+// CHECK-NEXT: note: use 'gnu11' for 'ISO C 2011 with GNU extensions' standard
+// CHECK-NEXT: note: use 'gnu1x' for 'ISO C 2011 with GNU extensions' standard
+// CHECK-NEXT: note: use 'cl' for 'OpenCL 1.0' standard
+// CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard
+// CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard
+// CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard
+
+// Make sure that no other output is 

[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-10 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added a comment.

Indeed, thanks :)
I ran `make check-all` and had no errors so I thought there are no tests.




Comment at: lib/Frontend/CompilerInvocation.cpp:1709
+Diags.Report(diag::note_drv_supported_value_with_description)
+  << Std.getName() << Std.getDescription();
+  }

ahatanak wrote:
> Is it possible to change the diagnostic so that it's easier to tell which 
> part is the supported value and which part is the description?
> 
> The diagnostic looks like this, and I found it a little hard to tell at a 
> quick glance:
> 
> "c89 - ISO C 1990" 
Sure, I have tried few formats with quotes/colons but how about this (a bit 
verbose) version:
```
note: supported values are:
note: 'c89' for standard 'ISO C 1990'
note: 'c90' for standard 'ISO C 1990'
note: 'iso9899:1990' for standard 'ISO C 1990'
...
```
What do you think about it? Do you have any suggestions?


https://reviews.llvm.org/D29724



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-10 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode updated this revision to Diff 88029.
idlecode added a comment.

Added test, changed printout style a bit (but this still needs to be checked)


https://reviews.llvm.org/D29724

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  lib/Frontend/CompilerInvocation.cpp
  test/Driver/unknown-std.c


Index: test/Driver/unknown-std.c
===
--- /dev/null
+++ test/Driver/unknown-std.c
@@ -0,0 +1,42 @@
+// RUN: not %clang %s -std=foobar -c 2>&1 | \
+// RUN: FileCheck %s
+
+// CHECK: error: invalid value 'foobar' in '-std=foobar'
+// CHECK: note: supported values are:
+// CHECK: note: 'c89' for standard 'ISO C 1990'
+// CHECK: note: 'c90' for standard 'ISO C 1990'
+// CHECK: note: 'iso9899:1990' for standard 'ISO C 1990'
+// CHECK: note: 'iso9899:199409' for standard 'ISO C 1990 with amendment 1'
+// CHECK: note: 'gnu89' for standard 'ISO C 1990 with GNU extensions'
+// CHECK: note: 'gnu90' for standard 'ISO C 1990 with GNU extensions'
+// CHECK: note: 'c99' for standard 'ISO C 1999'
+// CHECK: note: 'c9x' for standard 'ISO C 1999'
+// CHECK: note: 'iso9899:1999' for standard 'ISO C 1999'
+// CHECK: note: 'iso9899:199x' for standard 'ISO C 1999'
+// CHECK: note: 'gnu99' for standard 'ISO C 1999 with GNU extensions'
+// CHECK: note: 'gnu9x' for standard 'ISO C 1999 with GNU extensions'
+// CHECK: note: 'c11' for standard 'ISO C 2011'
+// CHECK: note: 'c1x' for standard 'ISO C 2011'
+// CHECK: note: 'iso9899:2011' for standard 'ISO C 2011'
+// CHECK: note: 'iso9899:201x' for standard 'ISO C 2011'
+// CHECK: note: 'gnu11' for standard 'ISO C 2011 with GNU extensions'
+// CHECK: note: 'gnu1x' for standard 'ISO C 2011 with GNU extensions'
+// CHECK: note: 'c++98' for standard 'ISO C++ 1998 with amendments'
+// CHECK: note: 'c++03' for standard 'ISO C++ 1998 with amendments'
+// CHECK: note: 'gnu++98' for standard 'ISO C++ 1998 with amendments and GNU 
extensions'
+// CHECK: note: 'c++0x' for standard 'ISO C++ 2011 with amendments'
+// CHECK: note: 'c++11' for standard 'ISO C++ 2011 with amendments'
+// CHECK: note: 'gnu++0x' for standard 'ISO C++ 2011 with amendments and GNU 
extensions'
+// CHECK: note: 'gnu++11' for standard 'ISO C++ 2011 with amendments and GNU 
extensions'
+// CHECK: note: 'c++1y' for standard 'ISO C++ 2014 with amendments'
+// CHECK: note: 'c++14' for standard 'ISO C++ 2014 with amendments'
+// CHECK: note: 'gnu++1y' for standard 'ISO C++ 2014 with amendments and GNU 
extensions'
+// CHECK: note: 'gnu++14' for standard 'ISO C++ 2014 with amendments and GNU 
extensions'
+// CHECK: note: 'c++1z' for standard 'Working draft for ISO C++ 2017'
+// CHECK: note: 'gnu++1z' for standard 'Working draft for ISO C++ 2017 with 
GNU extensions'
+// CHECK: note: 'cl' for standard 'OpenCL 1.0'
+// CHECK: note: 'cl1.1' for standard 'OpenCL 1.1'
+// CHECK: note: 'cl1.2' for standard 'OpenCL 1.2'
+// CHECK: note: 'cl2.0' for standard 'OpenCL 2.0'
+// CHECK: note: 'cuda' for standard 'NVIDIA CUDA(tm)'
+
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1694,10 +1694,21 @@
   .Case(alias, LangStandard::lang_##id)
 #include "clang/Frontend/LangStandards.def"
   .Default(LangStandard::lang_unspecified);
-if (LangStd == LangStandard::lang_unspecified)
+if (LangStd == LangStandard::lang_unspecified) {
   Diags.Report(diag::err_drv_invalid_value)
 << A->getAsString(Args) << A->getValue();
-else {
+  // Report all supported standards with description.
+  Diags.Report(diag::note_drv_supported_values);
+  for (unsigned KindValue = 0;
+  KindValue != LangStandard::lang_unspecified;
+  ++KindValue)
+  {
+const LangStandard  = LangStandard::getLangStandardForKind(
+  static_cast(KindValue));
+Diags.Report(diag::note_drv_supported_value_with_description)
+  << Std.getName() << Std.getDescription();
+  }
+} else {
   // Valid standard, check to make sure language and standard are
   // compatible.
   const LangStandard  = LangStandard::getLangStandardForKind(LangStd);
Index: include/clang/Basic/DiagnosticDriverKinds.td
===
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -230,6 +230,8 @@
   "The last /TC or /TP option takes precedence over earlier instances">;
 def note_drv_address_sanitizer_debug_runtime : Note<
   "AddressSanitizer doesn't support linking with debug runtime libraries yet">;
+def note_drv_supported_values : Note<"supported values are:">;
+def note_drv_supported_value_with_description : Note<"'%0' for standard '%1'">;
 
 def err_analyzer_config_no_value : Error<
   "analyzer-config option '%0' has a key but no value">;


Index: test/Driver/unknown-std.c

[PATCH] D29724: [Driver] Report available language standards on user error

2017-02-08 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode created this revision.

In case user did not provide valid standard name for `-std` option,
available values (with short description) will be reported.

To test: `clang -std=iso3103 -c source.c`


https://reviews.llvm.org/D29724

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  lib/Frontend/CompilerInvocation.cpp


Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1694,10 +1694,21 @@
   .Case(alias, LangStandard::lang_##id)
 #include "clang/Frontend/LangStandards.def"
   .Default(LangStandard::lang_unspecified);
-if (LangStd == LangStandard::lang_unspecified)
+if (LangStd == LangStandard::lang_unspecified) {
   Diags.Report(diag::err_drv_invalid_value)
 << A->getAsString(Args) << A->getValue();
-else {
+  // Report all supported standards with description.
+  Diags.Report(diag::note_drv_supported_values);
+  for (unsigned KindValue = 0;
+  KindValue != LangStandard::lang_unspecified;
+  ++KindValue)
+  {
+const LangStandard  = LangStandard::getLangStandardForKind(
+  static_cast(KindValue));
+Diags.Report(diag::note_drv_supported_value_with_description)
+  << Std.getName() << Std.getDescription();
+  }
+} else {
   // Valid standard, check to make sure language and standard are
   // compatible.
   const LangStandard  = LangStandard::getLangStandardForKind(LangStd);
Index: include/clang/Basic/DiagnosticDriverKinds.td
===
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -230,6 +230,8 @@
   "The last /TC or /TP option takes precedence over earlier instances">;
 def note_drv_address_sanitizer_debug_runtime : Note<
   "AddressSanitizer doesn't support linking with debug runtime libraries yet">;
+def note_drv_supported_values : Note<"supported values are:">;
+def note_drv_supported_value_with_description : Note<" %0 - %1">;
 
 def err_analyzer_config_no_value : Error<
   "analyzer-config option '%0' has a key but no value">;


Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1694,10 +1694,21 @@
   .Case(alias, LangStandard::lang_##id)
 #include "clang/Frontend/LangStandards.def"
   .Default(LangStandard::lang_unspecified);
-if (LangStd == LangStandard::lang_unspecified)
+if (LangStd == LangStandard::lang_unspecified) {
   Diags.Report(diag::err_drv_invalid_value)
 << A->getAsString(Args) << A->getValue();
-else {
+  // Report all supported standards with description.
+  Diags.Report(diag::note_drv_supported_values);
+  for (unsigned KindValue = 0;
+  KindValue != LangStandard::lang_unspecified;
+  ++KindValue)
+  {
+const LangStandard  = LangStandard::getLangStandardForKind(
+  static_cast(KindValue));
+Diags.Report(diag::note_drv_supported_value_with_description)
+  << Std.getName() << Std.getDescription();
+  }
+} else {
   // Valid standard, check to make sure language and standard are
   // compatible.
   const LangStandard  = LangStandard::getLangStandardForKind(LangStd);
Index: include/clang/Basic/DiagnosticDriverKinds.td
===
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -230,6 +230,8 @@
   "The last /TC or /TP option takes precedence over earlier instances">;
 def note_drv_address_sanitizer_debug_runtime : Note<
   "AddressSanitizer doesn't support linking with debug runtime libraries yet">;
+def note_drv_supported_values : Note<"supported values are:">;
+def note_drv_supported_value_with_description : Note<" %0 - %1">;
 
 def err_analyzer_config_no_value : Error<
   "analyzer-config option '%0' has a key but no value">;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29267: [clang-tidy] safety-no-assembler

2017-02-06 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode accepted this revision.
idlecode added a comment.
This revision is now accepted and ready to land.

Sure, but I don't have commit rights so someone else have to push it :)


https://reviews.llvm.org/D29267



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29267: [clang-tidy] safety-no-assembler

2017-02-06 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added a comment.

LGTM. HIC++ Standard seems worth implementing.


https://reviews.llvm.org/D29267



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28235: [clang-format cleanup] merge continuous deleted lines into one deletion.

2017-02-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode requested changes to this revision.
idlecode added a comment.
This revision now requires changes to proceed.

Few other tests (from `ChangeNamespaceTest`) require update too.


https://reviews.llvm.org/D28235



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28235: [clang-format cleanup] merge continuous deleted lines into one deletion.

2017-02-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added inline comments.



Comment at: lib/Format/Format.cpp:1182
+ I != E; ++I)
+  LastToNextLineFirst[(*I)->Last] = (*std::next(I))->First;
 tooling::Replacements Fixes;

Could you add brackets around loop body?



Comment at: lib/Format/Format.cpp:1184
 tooling::Replacements Fixes;
 std::vector Tokens;
 std::copy(DeletedTokens.begin(), DeletedTokens.end(),

While you are here, could you get rid of `Tokens` vector too?
I believe iterating over `DeletedTokens`directly will do the job.


https://reviews.llvm.org/D28235



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29267: [clang-tidy] safety-no-assembler

2017-02-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added inline comments.



Comment at: clang-tools-extra/docs/clang-tidy/checks/list.rst:156
+   safety-no-assembler
+   safety-no-vector-bool

`safety-no-vector-bool` seems to belong to the other patch.



Comment at: clang-tools-extra/test/clang-tidy/safety-no-assembler.cpp:2
+// RUN: %check_clang_tidy %s safety-no-assembler %t
+
+void f() {

Maybe this check should handle `FileScopeAsmDecl` and `AsmLabelAttr` too?

```
__asm__(".symver foo, bar@v");
static int s asm("spam");
```


https://reviews.llvm.org/D29267



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29393: [clang-tidy] Don't warn about call to unresolved operator*

2017-02-04 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added inline comments.



Comment at: clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp:63
+cxxOperatorCallExpr(argumentCountIs(1),
+callee(unresolvedLookupExpr()),
+hasArgument(0, cxxThisExpr(;

malcolm.parsons wrote:
> idlecode wrote:
> > Seems that it will catch all unary operators with ##this## as first 
> > argument.
> > e.g. in case `operator-` is defined somewhere, check will not warn about 
> > returning `-this`.
> > Do you think adding `hasOverloadedOperatorName("*")` for such abstract case 
> > is worth it?
> I'm just trying to suppress them warning from the template. The operator can 
> be checked properly in an instantiation.
LGTM then :)


https://reviews.llvm.org/D29393



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29267: [clang-tidy] safety-no-assembler

2017-02-03 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added a comment.

Standard you linked mentions portability as the reason inline assembler should 
be avoided. Should it really be named 'safety'?


https://reviews.llvm.org/D29267



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29393: [clang-tidy] Don't warn about call to unresolved operator*

2017-02-03 Thread Paweł Żukowski via Phabricator via cfe-commits
idlecode added inline comments.



Comment at: clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp:63
+cxxOperatorCallExpr(argumentCountIs(1),
+callee(unresolvedLookupExpr()),
+hasArgument(0, cxxThisExpr(;

Seems that it will catch all unary operators with ##this## as first argument.
e.g. in case `operator-` is defined somewhere, check will not warn about 
returning `-this`.
Do you think adding `hasOverloadedOperatorName("*")` for such abstract case is 
worth it?


https://reviews.llvm.org/D29393



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits