<div dir="ltr">Hello Alex,<br><br>This commit broke tests on few builders:<br><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast</a><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast</a><br><br>. . .<br>********************<br>Failing Tests (1):<br>    Clang :: Refactor/Extract/ExtractionSemicolonPolicy.cpp<br><br>Please have a look?<br><br>Thanks<br><br>Galina<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 3, 2017 at 11:11 AM, Alex Lorenz via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: arphaman<br>
Date: Fri Nov  3 11:11:22 2017<br>
New Revision: 317343<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=317343&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=317343&view=rev</a><br>
Log:<br>
[refactor][extract] insert semicolons into extracted/inserted code<br>
when needed<br>
<br>
This commit implements the semicolon insertion logic into the extract<br>
refactoring. The following rules are used:<br>
<br>
- extracting expression: add terminating ';' to the extracted function.<br>
- extracting statements that don't require terminating ';' (e.g. switch): add<br>
  terminating ';' to the callee.<br>
- extracting statements with ';':  move (if possible) the original ';' from the<br>
  callee and add terminating ';'.<br>
- otherwise, add ';' to both places.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D39441" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D39441</a><br>
<br>
Added:<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.cpp<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.h<br>
    cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.cpp<br>
    cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.m<br>
Modified:<br>
    cfe/trunk/include/clang/Lex/<wbr>Lexer.h<br>
    cfe/trunk/lib/Lex/Lexer.cpp<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt<br>
    cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract.cpp<br>
    cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractExprIntoFunction.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Lex/<wbr>Lexer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Lexer.h?rev=317343&r1=317342&r2=317343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Lex/Lexer.h?rev=317343&<wbr>r1=317342&r2=317343&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Lex/<wbr>Lexer.h (original)<br>
+++ cfe/trunk/include/clang/Lex/<wbr>Lexer.h Fri Nov  3 11:11:22 2017<br>
@@ -466,6 +466,13 @@ public:<br>
                                         const LangOptions &LangOpts,<br>
                                         unsigned MaxLines = 0);<br>
<br>
+  /// Finds the token that comes right after the given location.<br>
+  ///<br>
+  /// Returns the next token, or none if the location is inside a macro.<br>
+  static Optional<Token> findNextToken(SourceLocation Loc,<br>
+                                       const SourceManager &SM,<br>
+                                       const LangOptions &LangOpts);<br>
+<br>
   /// \brief Checks that the given token is the first token that occurs after<br>
   /// the given location (this excludes comments and whitespace). Returns the<br>
   /// location immediately after the specified token. If the token is not found<br>
<br>
Modified: cfe/trunk/lib/Lex/Lexer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=317343&r1=317342&r2=317343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Lex/<wbr>Lexer.cpp?rev=317343&r1=<wbr>317342&r2=317343&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Lex/Lexer.cpp (original)<br>
+++ cfe/trunk/lib/Lex/Lexer.cpp Fri Nov  3 11:11:22 2017<br>
@@ -1212,18 +1212,12 @@ const char *Lexer::SkipEscapedNewLines(c<br>
   }<br>
 }<br>
<br>
-/// \brief Checks that the given token is the first token that occurs after the<br>
-/// given location (this excludes comments and whitespace). Returns the location<br>
-/// immediately after the specified token. If the token is not found or the<br>
-/// location is inside a macro, the returned source location will be invalid.<br>
-SourceLocation Lexer::findLocationAfterToken(<wbr>SourceLocation Loc,<br>
-                                        tok::TokenKind TKind,<br>
-                                        const SourceManager &SM,<br>
-                                        const LangOptions &LangOpts,<br>
-                                        bool SkipTrailingWhitespaceAndNewLi<wbr>ne) {<br>
+Optional<Token> Lexer::findNextToken(<wbr>SourceLocation Loc,<br>
+                                     const SourceManager &SM,<br>
+                                     const LangOptions &LangOpts) {<br>
   if (Loc.isMacroID()) {<br>
     if (!Lexer::<wbr>isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))<br>
-      return SourceLocation();<br>
+      return None;<br>
   }<br>
   Loc = Lexer::getLocForEndOfToken(<wbr>Loc, 0, SM, LangOpts);<br>
<br>
@@ -1234,7 +1228,7 @@ SourceLocation Lexer::findLocationAfterT<br>
   bool InvalidTemp = false;<br>
   StringRef File = SM.getBufferData(LocInfo.<wbr>first, &InvalidTemp);<br>
   if (InvalidTemp)<br>
-    return SourceLocation();<br>
+    return None;<br>
<br>
   const char *TokenBegin = File.data() + LocInfo.second;<br>
<br>
@@ -1244,15 +1238,25 @@ SourceLocation Lexer::findLocationAfterT<br>
   // Find the token.<br>
   Token Tok;<br>
   lexer.LexFromRawLexer(Tok);<br>
-  if (Tok.isNot(TKind))<br>
+  return Tok;<br>
+}<br>
+<br>
+/// \brief Checks that the given token is the first token that occurs after the<br>
+/// given location (this excludes comments and whitespace). Returns the location<br>
+/// immediately after the specified token. If the token is not found or the<br>
+/// location is inside a macro, the returned source location will be invalid.<br>
+SourceLocation Lexer::findLocationAfterToken(<br>
+    SourceLocation Loc, tok::TokenKind TKind, const SourceManager &SM,<br>
+    const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLi<wbr>ne) {<br>
+  Optional<Token> Tok = findNextToken(Loc, SM, LangOpts);<br>
+  if (!Tok || Tok->isNot(TKind))<br>
     return SourceLocation();<br>
-  SourceLocation TokenLoc = Tok.getLocation();<br>
+  SourceLocation TokenLoc = Tok->getLocation();<br>
<br>
   // Calculate how much whitespace needs to be skipped if any.<br>
   unsigned NumWhitespaceChars = 0;<br>
   if (<wbr>SkipTrailingWhitespaceAndNewLi<wbr>ne) {<br>
-    const char *TokenEnd = SM.getCharacterData(TokenLoc) +<br>
-                           Tok.getLength();<br>
+    const char *TokenEnd = SM.getCharacterData(TokenLoc) + Tok->getLength();<br>
     unsigned char C = *TokenEnd;<br>
     while (isHorizontalWhitespace(C)) {<br>
       C = *(++TokenEnd);<br>
@@ -1269,7 +1273,7 @@ SourceLocation Lexer::findLocationAfterT<br>
     }<br>
   }<br>
<br>
-  return TokenLoc.getLocWithOffset(Tok.<wbr>getLength() + NumWhitespaceChars);<br>
+  return TokenLoc.getLocWithOffset(Tok-<wbr>>getLength() + NumWhitespaceChars);<br>
 }<br>
<br>
 /// getCharAndSizeSlow - Peek a single 'character' from the specified buffer,<br>
<br>
Modified: cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt?rev=317343&r1=317342&r2=317343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt?<wbr>rev=317343&r1=317342&r2=<wbr>317343&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/CMakeLists.txt Fri Nov  3 11:11:22 2017<br>
@@ -4,7 +4,8 @@ add_clang_library(<wbr>clangToolingRefactor<br>
   ASTSelection.cpp<br>
   ASTSelectionRequirements.cpp<br>
   AtomicChange.cpp<br>
-  Extract.cpp<br>
+  Extract/Extract.cpp<br>
+  Extract/SourceExtraction.cpp<br>
   RefactoringActions.cpp<br>
   Rename/RenamingAction.cpp<br>
   Rename/SymbolOccurrences.cpp<br>
<br>
Modified: cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Extract.cpp?rev=317343&r1=317342&r2=317343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract.cpp?rev=<wbr>317343&r1=317342&r2=317343&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract.cpp (original)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract.cpp Fri Nov  3 11:11:22 2017<br>
@@ -14,6 +14,7 @@<br>
 //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
<br>
 #include "clang/Tooling/Refactoring/<wbr>Extract/Extract.h"<br>
+#include "SourceExtraction.h"<br>
 #include "clang/AST/ASTContext.h"<br>
 #include "clang/AST/DeclCXX.h"<br>
 #include "clang/AST/Expr.h"<br>
@@ -145,6 +146,8 @@ ExtractFunction::<wbr>createSourceReplacement<br>
   PP.SuppressLifetimeQualifiers = true;<br>
   PP.SuppressUnwrittenScope = true;<br>
<br>
+  ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::<wbr>compute(<br>
+      Code[Code.size() - 1], ExtractedRange, SM, LangOpts);<br>
   AtomicChange Change(SM, ExtractedDeclLocation);<br>
   // Create the replacement for the extracted declaration.<br>
   {<br>
@@ -162,8 +165,8 @@ ExtractFunction::<wbr>createSourceReplacement<br>
     if (IsExpr && !ReturnType->isVoidType())<br>
       OS << "return ";<br>
     OS << ExtractedCodeRewriter.<wbr>getRewrittenText(<wbr>ExtractedRange);<br>
-    // FIXME: Compute the correct semicolon policy.<br>
-    OS << ';';<br>
+    if (Semicolons.<wbr>isNeededInExtractedFunction())<br>
+      OS << ';';<br>
     OS << "\n}\n\n";<br>
     auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str());<br>
     if (Err)<br>
@@ -178,7 +181,8 @@ ExtractFunction::<wbr>createSourceReplacement<br>
     OS << DeclName << '(';<br>
     // FIXME: Forward arguments.<br>
     OS << ')';<br>
-    // FIXME: Add semicolon if needed.<br>
+    if (Semicolons.<wbr>isNeededInOriginalFunction())<br>
+      OS << ';';<br>
<br>
     auto Err = Change.replace(<br>
         SM, CharSourceRange::<wbr>getTokenRange(ExtractedRange), OS.str());<br>
<br>
Added: cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp?rev=317343&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.cpp?rev=<wbr>317343&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.cpp (added)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.cpp Fri Nov  3 11:11:22 2017<br>
@@ -0,0 +1,112 @@<br>
+//===--- SourceExtraction.cpp - Clang refactoring library -----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "SourceExtraction.h"<br>
+#include "clang/AST/Stmt.h"<br>
+#include "clang/AST/StmtCXX.h"<br>
+#include "clang/AST/StmtObjC.h"<br>
+#include "clang/Basic/SourceManager.h"<br>
+#include "clang/Lex/Lexer.h"<br>
+<br>
+using namespace clang;<br>
+<br>
+namespace {<br>
+<br>
+/// Returns true if the token at the given location is a semicolon.<br>
+bool isSemicolonAtLocation(<wbr>SourceLocation TokenLoc, const SourceManager &SM,<br>
+                           const LangOptions &LangOpts) {<br>
+  return Lexer::getSourceText(<br>
+             CharSourceRange::<wbr>getTokenRange(TokenLoc, TokenLoc), SM,<br>
+             LangOpts) == ";";<br>
+}<br>
+<br>
+/// Returns true if there should be a semicolon after the given statement.<br>
+bool isSemicolonRequiredAfter(const Stmt *S) {<br>
+  if (isa<CompoundStmt>(S))<br>
+    return false;<br>
+  if (const auto *If = dyn_cast<IfStmt>(S))<br>
+    return isSemicolonRequiredAfter(If-><wbr>getElse() ? If->getElse()<br>
+                                                  : If->getThen());<br>
+  if (const auto *While = dyn_cast<WhileStmt>(S))<br>
+    return isSemicolonRequiredAfter(<wbr>While->getBody());<br>
+  if (const auto *For = dyn_cast<ForStmt>(S))<br>
+    return isSemicolonRequiredAfter(For-><wbr>getBody());<br>
+  if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(S))<br>
+    return isSemicolonRequiredAfter(<wbr>CXXFor->getBody());<br>
+  if (const auto *ObjCFor = dyn_cast<<wbr>ObjCForCollectionStmt>(S))<br>
+    return isSemicolonRequiredAfter(<wbr>ObjCFor->getBody());<br>
+  switch (S->getStmtClass()) {<br>
+  case Stmt::SwitchStmtClass:<br>
+  case Stmt::CXXTryStmtClass:<br>
+  case Stmt::<wbr>ObjCAtSynchronizedStmtClass:<br>
+  case Stmt::<wbr>ObjCAutoreleasePoolStmtClass:<br>
+  case Stmt::ObjCAtTryStmtClass:<br>
+    return false;<br>
+  default:<br>
+    return true;<br>
+  }<br>
+}<br>
+<br>
+/// Returns true if the two source locations are on the same line.<br>
+bool areOnSameLine(SourceLocation Loc1, SourceLocation Loc2,<br>
+                   const SourceManager &SM) {<br>
+  return !Loc1.isMacroID() && !Loc2.isMacroID() &&<br>
+         SM.getSpellingLineNumber(Loc1) == SM.getSpellingLineNumber(Loc2)<wbr>;<br>
+}<br>
+<br>
+} // end anonymous namespace<br>
+<br>
+namespace clang {<br>
+namespace tooling {<br>
+<br>
+ExtractionSemicolonPolicy<br>
+ExtractionSemicolonPolicy::<wbr>compute(const Stmt *S, SourceRange &ExtractedRange,<br>
+                                   const SourceManager &SM,<br>
+                                   const LangOptions &LangOpts) {<br>
+  auto neededInExtractedFunction = []() {<br>
+    return ExtractionSemicolonPolicy(<wbr>true, false);<br>
+  };<br>
+  auto neededInOriginalFunction = []() {<br>
+    return ExtractionSemicolonPolicy(<wbr>false, true);<br>
+  };<br>
+<br>
+  /// The extracted expression should be terminated with a ';'. The call to<br>
+  /// the extracted function will replace this expression, so it won't need<br>
+  /// a terminating ';'.<br>
+  if (isa<Expr>(S))<br>
+    return neededInExtractedFunction();<br>
+<br>
+  /// Some statements don't need to be terminated with ';'. The call to the<br>
+  /// extracted function will be a standalone statement, so it should be<br>
+  /// terminated with a ';'.<br>
+  bool NeedsSemi = isSemicolonRequiredAfter(S);<br>
+  if (!NeedsSemi)<br>
+    return neededInOriginalFunction();<br>
+<br>
+  /// Some statements might end at ';'. The extraction will move that ';', so<br>
+  /// the call to the extracted function should be terminated with a ';'.<br>
+  SourceLocation End = ExtractedRange.getEnd();<br>
+  if (isSemicolonAtLocation(End, SM, LangOpts))<br>
+    return neededInOriginalFunction();<br>
+<br>
+  /// Other statements should generally have a trailing ';'. We can try to find<br>
+  /// it and move it together it with the extracted code.<br>
+  Optional<Token> NextToken = Lexer::findNextToken(End, SM, LangOpts);<br>
+  if (NextToken && NextToken->is(tok::semi) &&<br>
+      areOnSameLine(NextToken-><wbr>getLocation(), End, SM)) {<br>
+    ExtractedRange.setEnd(<wbr>NextToken->getLocation());<br>
+    return neededInOriginalFunction();<br>
+  }<br>
+<br>
+  /// Otherwise insert semicolons in both places.<br>
+  return ExtractionSemicolonPolicy(<wbr>true, true);<br>
+}<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
<br>
Added: cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.h?rev=317343&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.h?rev=317343&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.h (added)<br>
+++ cfe/trunk/lib/Tooling/<wbr>Refactoring/Extract/<wbr>SourceExtraction.h Fri Nov  3 11:11:22 2017<br>
@@ -0,0 +1,52 @@<br>
+//===--- SourceExtraction.cpp - Clang refactoring library -----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_LIB_TOOLING_<wbr>REFACTORING_EXTRACT_SOURCE_<wbr>EXTRACTION_H<br>
+#define LLVM_CLANG_LIB_TOOLING_<wbr>REFACTORING_EXTRACT_SOURCE_<wbr>EXTRACTION_H<br>
+<br>
+#include "clang/Basic/LLVM.h"<br>
+<br>
+namespace clang {<br>
+<br>
+class LangOptions;<br>
+class SourceManager;<br>
+class SourceRange;<br>
+class Stmt;<br>
+<br>
+namespace tooling {<br>
+<br>
+/// Determines which semicolons should be inserted during extraction.<br>
+class ExtractionSemicolonPolicy {<br>
+public:<br>
+  bool isNeededInExtractedFunction() const {<br>
+    return IsNeededInExtractedFunction;<br>
+  }<br>
+<br>
+  bool isNeededInOriginalFunction() const { return IsNeededInOriginalFunction; }<br>
+<br>
+  /// Returns the semicolon insertion policy that is needed for extraction of<br>
+  /// the given statement from the given source range.<br>
+  static ExtractionSemicolonPolicy compute(const Stmt *S,<br>
+                                           SourceRange &ExtractedRange,<br>
+                                           const SourceManager &SM,<br>
+                                           const LangOptions &LangOpts);<br>
+<br>
+private:<br>
+  ExtractionSemicolonPolicy(bool IsNeededInExtractedFunction,<br>
+                            bool IsNeededInOriginalFunction)<br>
+      : IsNeededInExtractedFunction(<wbr>IsNeededInExtractedFunction),<br>
+        IsNeededInOriginalFunction(<wbr>IsNeededInOriginalFunction) {}<br>
+  bool IsNeededInExtractedFunction;<br>
+  bool IsNeededInOriginalFunction;<br>
+};<br>
+<br>
+} // end namespace tooling<br>
+} // end namespace clang<br>
+<br>
+#endif // LLVM_CLANG_LIB_TOOLING_<wbr>REFACTORING_EXTRACT_SOURCE_<wbr>EXTRACTION_H<br>
<br>
Modified: cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractExprIntoFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Refactor/Extract/ExtractExprIntoFunction.cpp?rev=317343&r1=317342&r2=317343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Refactor/Extract/<wbr>ExtractExprIntoFunction.cpp?<wbr>rev=317343&r1=317342&r2=<wbr>317343&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractExprIntoFunction.cpp (original)<br>
+++ cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractExprIntoFunction.cpp Fri Nov  3 11:11:22 2017<br>
@@ -20,10 +20,10 @@ void simpleExtractStmtNoCaptures() {<br>
 // CHECK: 1 'astatement' results:<br>
 // CHECK:      static void extracted() {<br>
 // CHECK-NEXT: int a = 1;<br>
-// CHECK-NEXT: int b = 2;;{{$}}<br>
+// CHECK-NEXT: int b = 2;{{$}}<br>
 // CHECK-NEXT: }{{[[:space:]].*}}<br>
 // CHECK-NEXT: void simpleExtractStmtNoCaptures() {<br>
-// CHECK-NEXT:   /*range astatement=->+1:13*/extracted(<wbr>){{$}}<br>
+// CHECK-NEXT:   /*range astatement=->+1:13*/extracted(<wbr>);{{$}}<br>
 // CHECK-NEXT: }<br>
<br>
<br>
<br>
Added: cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp?rev=317343&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Refactor/Extract/<wbr>ExtractionSemicolonPolicy.cpp?<wbr>rev=317343&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.cpp (added)<br>
+++ cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.cpp Fri Nov  3 11:11:22 2017<br>
@@ -0,0 +1,192 @@<br>
+// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 2>&1 | grep -v CHECK | FileCheck %s<br>
+<br>
+struct Rectangle { int width, height; };<br>
+<br>
+void extractStatement(const Rectangle &r) {<br>
+  /*range adeclstmt=->+0:59*/int area = r.width * r.height;<br>
+}<br>
+// CHECK: 1 'adeclstmt' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: int area = r.width * r.height;{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatement(const Rectangle &r) {<br>
+// CHECK-NEXT:   /*range adeclstmt=->+0:59*/extracted()<wbr>;{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractStatementNoSemiIf(const Rectangle &r) {<br>
+  /*range bextractif=->+2:4*/if (r.width) {<br>
+    int x = r.height;<br>
+  }<br>
+}<br>
+// CHECK: 1 'bextractif' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: if (r.width) {<br>
+// CHECK-NEXT: int x = r.height;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementNoSemiIf(const Rectangle &r) {<br>
+// CHECK-NEXT:   /*range bextractif=->+2:4*/extracted()<wbr>;{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractStatementDontExtraneous<wbr>Semi(const Rectangle &r) {<br>
+  /*range cextractif=->+2:4*/if (r.width) {<br>
+    int x = r.height;<br>
+  } ;<br>
+} //^ This semicolon shouldn't be extracted.<br>
+// CHECK: 1 'cextractif' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: if (r.width) {<br>
+// CHECK-NEXT: int x = r.height;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementDontExtraneous<wbr>Semi(const Rectangle &r) {<br>
+// CHECK-NEXT: extracted(); ;{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractStatementNotSemiSwitch(<wbr>) {<br>
+  /*range dextract=->+5:4*/switch (2) {<br>
+  case 1:<br>
+    break;<br>
+  case 2:<br>
+    break;<br>
+  }<br>
+}<br>
+// CHECK: 1 'dextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: switch (2) {<br>
+// CHECK-NEXT: case 1:<br>
+// CHECK-NEXT:   break;<br>
+// CHECK-NEXT: case 2:<br>
+// CHECK-NEXT:   break;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementNotSemiSwitch(<wbr>) {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractStatementNotSemiWhile() {<br>
+  /*range eextract=->+2:4*/while (true) {<br>
+    int x = 0;<br>
+  }<br>
+}<br>
+// CHECK: 1 'eextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: while (true) {<br>
+// CHECK-NEXT: int x = 0;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementNotSemiWhile() {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractStatementNotSemiFor() {<br>
+  /*range fextract=->+1:4*/for (int i = 0; i < 10; ++i) {<br>
+  }<br>
+}<br>
+// CHECK: 1 'fextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementNotSemiFor() {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+struct XS {<br>
+  int *begin() { return 0; }<br>
+  int *end() { return 0; }<br>
+};<br>
+<br>
+void extractStatementNotSemiRangedF<wbr>or(XS xs) {<br>
+  /*range gextract=->+1:4*/for (int i : xs) {<br>
+  }<br>
+}<br>
+// CHECK: 1 'gextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: for (int i : xs) {<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementNotSemiRangedF<wbr>or(XS xs) {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractStatementNotSemiRangedT<wbr>ryCatch() {<br>
+  /*range hextract=->+3:4*/try { int x = 0; }<br>
+  catch (const int &i) {<br>
+    int y = i;<br>
+  }<br>
+}<br>
+// CHECK: 1 'hextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: try { int x = 0; }<br>
+// CHECK-NEXT: catch (const int &i) {<br>
+// CHECK-NEXT:   int y = i;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractStatementNotSemiRangedT<wbr>ryCatch() {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractCantFindSemicolon() {<br>
+  /*range iextract=->+1:17*/do {<br>
+  } while (true)<br>
+  // Add a semicolon in both the extracted and original function as we don't<br>
+  // want to extract the semicolon below.<br>
+  ;<br>
+}<br>
+// CHECK: 1 'iextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: do {<br>
+// CHECK-NEXT: } while (true);{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractCantFindSemicolon() {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: //<br>
+// CHECK-NEXT: //<br>
+// CHECK-NEXT: ;<br>
+// CHECK-NEXT: }<br>
+<br>
+void extractFindSemicolon() {<br>
+  /*range jextract=->+1:17*/do {<br>
+  } while (true) /*grab*/ ;<br>
+}<br>
+// CHECK: 1 'jextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: do {<br>
+// CHECK-NEXT: } while (true) /*grab*/ ;{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void extractFindSemicolon() {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void call();<br>
+<br>
+void careForNonCompoundSemicolons1(<wbr>) {<br>
+  /*range kextract=->+1:11*/if (true)<br>
+    call();<br>
+}<br>
+// CHECK: 1 'kextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: if (true)<br>
+// CHECK-NEXT: call();{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void careForNonCompoundSemicolons1(<wbr>) {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: }<br>
+<br>
+void careForNonCompoundSemicolons2(<wbr>) {<br>
+  /*range lextract=->+3:1*/for (int i = 0; i < 10; ++i)<br>
+    while (i != 0)<br>
+      ;<br>
+  // end right here111!<br>
+}<br>
+// CHECK: 1 'lextract' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)<br>
+// CHECK-NEXT: while (i != 0)<br>
+// CHECK-NEXT:   ;{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+// CHECK-NEXT: void careForNonCompoundSemicolons2(<wbr>) {<br>
+// CHECK-NEXT: extracted();{{$}}<br>
+// CHECK-NEXT: //<br>
+// CHECK-NEXT: }<br>
<br>
Added: cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.m?rev=317343&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Refactor/Extract/<wbr>ExtractionSemicolonPolicy.m?<wbr>rev=317343&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.m (added)<br>
+++ cfe/trunk/test/Refactor/<wbr>Extract/<wbr>ExtractionSemicolonPolicy.m Fri Nov  3 11:11:22 2017<br>
@@ -0,0 +1,56 @@<br>
+// RUN: clang-refactor extract -selection=test:%s %s -- 2>&1 | grep -v CHECK | FileCheck %s<br>
+<br>
+@interface NSArray<br>
++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;<br>
+@end<br>
+<br>
+void extractStatementNoSemiObjCFor(<wbr>NSArray *array) {<br>
+  /*range astmt=->+2:4*/for (id i in array) {<br>
+    int x = 0;<br>
+  }<br>
+}<br>
+// CHECK: 1 'astmt' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: for (id i in array) {<br>
+// CHECK-NEXT: int x = 0;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+<br>
+void extractStatementNoSemiSync() {<br>
+  id lock;<br>
+  /*range bstmt=->+2:4*/@synchronized(<wbr>lock) {<br>
+    int x = 0;<br>
+  }<br>
+}<br>
+// CHECK: 1 'bstmt' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: @synchronized(lock) {<br>
+// CHECK-NEXT: int x = 0;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+<br>
+void extractStatementNoSemiAutorel(<wbr>) {<br>
+  /*range cstmt=->+2:4*/@autoreleasepool {<br>
+    int x = 0;<br>
+  }<br>
+}<br>
+// CHECK: 1 'cstmt' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: @autoreleasepool {<br>
+// CHECK-NEXT: int x = 0;<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
+<br>
+void extractStatementNoSemiTryFinal<wbr>llllly() {<br>
+  /*range dstmt=->+3:4*/@try {<br>
+    int x = 0;<br>
+  } @finally {<br>
+  }<br>
+}<br>
+// CHECK: 1 'dstmt' results:<br>
+// CHECK:      static void extracted() {<br>
+// CHECK-NEXT: @try {<br>
+// CHECK-NEXT: int x = 0;<br>
+// CHECK-NEXT: } @finally {<br>
+// CHECK-NEXT: }{{$}}<br>
+// CHECK-NEXT: }{{[[:space:]].*}}<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>