<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>