summaryrefslogtreecommitdiffstats
path: root/unittests/Tooling
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Tooling')
-rw-r--r--unittests/Tooling/ASTSelectionTest.cpp7
-rw-r--r--unittests/Tooling/CMakeLists.txt3
-rw-r--r--unittests/Tooling/CastExprTest.cpp7
-rw-r--r--unittests/Tooling/CommentHandlerTest.cpp7
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp49
-rw-r--r--unittests/Tooling/DiagnosticsYamlTest.cpp147
-rw-r--r--unittests/Tooling/ExecutionTest.cpp7
-rw-r--r--unittests/Tooling/FixItTest.cpp7
-rw-r--r--unittests/Tooling/HeaderIncludesTest.cpp21
-rw-r--r--unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp7
-rw-r--r--unittests/Tooling/LookupTest.cpp86
-rw-r--r--unittests/Tooling/QualTypeNamesTest.cpp11
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/Class.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp53
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp7
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp7
-rw-r--r--unittests/Tooling/RefactoringActionRulesTest.cpp7
-rw-r--r--unittests/Tooling/RefactoringCallbacksTest.cpp7
-rw-r--r--unittests/Tooling/RefactoringTest.cpp7
-rw-r--r--unittests/Tooling/ReplacementTest.h7
-rw-r--r--unittests/Tooling/ReplacementsYamlTest.cpp7
-rw-r--r--unittests/Tooling/RewriterTest.cpp7
-rw-r--r--unittests/Tooling/RewriterTestContext.h7
-rw-r--r--unittests/Tooling/SourceCodeTest.cpp97
-rw-r--r--unittests/Tooling/StencilTest.cpp223
-rw-r--r--unittests/Tooling/TestVisitor.h7
-rw-r--r--unittests/Tooling/ToolingTest.cpp42
-rw-r--r--unittests/Tooling/TransformerTest.cpp462
47 files changed, 1167 insertions, 279 deletions
diff --git a/unittests/Tooling/ASTSelectionTest.cpp b/unittests/Tooling/ASTSelectionTest.cpp
index 2f5df8f430..7ad5148213 100644
--- a/unittests/Tooling/ASTSelectionTest.cpp
+++ b/unittests/Tooling/ASTSelectionTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/ASTSelectionTest.cpp ------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt
index 7619c7fb23..994b88b95b 100644
--- a/unittests/Tooling/CMakeLists.txt
+++ b/unittests/Tooling/CMakeLists.txt
@@ -49,7 +49,10 @@ add_clang_unittest(ToolingTests
RefactoringTest.cpp
ReplacementsYamlTest.cpp
RewriterTest.cpp
+ SourceCodeTest.cpp
+ StencilTest.cpp
ToolingTest.cpp
+ TransformerTest.cpp
)
target_link_libraries(ToolingTests
diff --git a/unittests/Tooling/CastExprTest.cpp b/unittests/Tooling/CastExprTest.cpp
index 5310c21254..a9e78d2155 100644
--- a/unittests/Tooling/CastExprTest.cpp
+++ b/unittests/Tooling/CastExprTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/CastExprTest.cpp ----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/CommentHandlerTest.cpp b/unittests/Tooling/CommentHandlerTest.cpp
index 9c3abdc4b1..5ceed95b98 100644
--- a/unittests/Tooling/CommentHandlerTest.cpp
+++ b/unittests/Tooling/CommentHandlerTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/CommentHandlerTest.cpp -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index 949d6a3b73..4e27df71d8 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/CompilationDatabaseTest.cpp -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -89,12 +88,17 @@ TEST(JSONCompilationDatabase, GetAllFiles) {
expected_files.push_back(PathStorage.str());
llvm::sys::path::native("//net/dir/file2", PathStorage);
expected_files.push_back(PathStorage.str());
+ llvm::sys::path::native("//net/file1", PathStorage);
+ expected_files.push_back(PathStorage.str());
EXPECT_EQ(expected_files,
getAllFiles("[{\"directory\":\"//net/dir\","
"\"command\":\"command\","
"\"file\":\"file1\"},"
" {\"directory\":\"//net/dir\","
"\"command\":\"command\","
+ "\"file\":\"../file1\"},"
+ " {\"directory\":\"//net/dir\","
+ "\"command\":\"command\","
"\"file\":\"file2\"}]",
ErrorMessage, JSONCommandLineSyntax::Gnu))
<< ErrorMessage;
@@ -669,6 +673,27 @@ protected:
return llvm::join(Results[0].CommandLine, " ");
}
+ // Parse the file whose command was used out of the Heuristic string.
+ std::string getProxy(llvm::StringRef F) {
+ auto Results =
+ inferMissingCompileCommands(llvm::make_unique<MemCDB>(Entries))
+ ->getCompileCommands(path(F));
+ if (Results.empty())
+ return "none";
+ StringRef Proxy = Results.front().Heuristic;
+ if (!Proxy.consume_front("inferred from "))
+ return "";
+ // We have a proxy file, convert back to a unix relative path.
+ // This is a bit messy, but we do need to test these strings somehow...
+ llvm::SmallString<32> TempDir;
+ llvm::sys::path::system_temp_directory(false, TempDir);
+ Proxy.consume_front(TempDir);
+ Proxy.consume_front(llvm::sys::path::get_separator());
+ llvm::SmallString<32> Result = Proxy;
+ llvm::sys::path::native(Result, llvm::sys::path::Style::posix);
+ return Result.str();
+ }
+
MemCDB::EntryMap Entries;
};
@@ -678,18 +703,16 @@ TEST_F(InterpolateTest, Nearby) {
add("an/other/foo.cpp");
// great: dir and name both match (prefix or full, case insensitive)
- EXPECT_EQ(getCommand("dir/f.cpp"), "clang -D dir/foo.cpp");
- EXPECT_EQ(getCommand("dir/FOO.cpp"), "clang -D dir/foo.cpp");
+ EXPECT_EQ(getProxy("dir/f.cpp"), "dir/foo.cpp");
+ EXPECT_EQ(getProxy("dir/FOO.cpp"), "dir/foo.cpp");
// no name match. prefer matching dir, break ties by alpha
- EXPECT_EQ(getCommand("dir/a.cpp"), "clang -D dir/bar.cpp");
+ EXPECT_EQ(getProxy("dir/a.cpp"), "dir/bar.cpp");
// an exact name match beats one segment of directory match
- EXPECT_EQ(getCommand("some/other/bar.h"),
- "clang -D dir/bar.cpp -x c++-header");
+ EXPECT_EQ(getProxy("some/other/bar.h"), "dir/bar.cpp");
// two segments of directory match beat a prefix name match
- EXPECT_EQ(getCommand("an/other/b.cpp"), "clang -D an/other/foo.cpp");
+ EXPECT_EQ(getProxy("an/other/b.cpp"), "an/other/foo.cpp");
// if nothing matches at all, we still get the closest alpha match
- EXPECT_EQ(getCommand("below/some/obscure/path.cpp"),
- "clang -D an/other/foo.cpp");
+ EXPECT_EQ(getProxy("below/some/obscure/path.cpp"), "an/other/foo.cpp");
}
TEST_F(InterpolateTest, Language) {
@@ -723,7 +746,7 @@ TEST_F(InterpolateTest, Case) {
add("FOO/BAR/BAZ/SHOUT.cc");
add("foo/bar/baz/quiet.cc");
// Case mismatches are completely ignored, so we choose the name match.
- EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D FOO/BAR/BAZ/SHOUT.cc");
+ EXPECT_EQ(getProxy("foo/bar/baz/shout.C"), "FOO/BAR/BAZ/SHOUT.cc");
}
TEST_F(InterpolateTest, Aliasing) {
diff --git a/unittests/Tooling/DiagnosticsYamlTest.cpp b/unittests/Tooling/DiagnosticsYamlTest.cpp
index f4de53fad2..aaba258911 100644
--- a/unittests/Tooling/DiagnosticsYamlTest.cpp
+++ b/unittests/Tooling/DiagnosticsYamlTest.cpp
@@ -1,9 +1,8 @@
//===- unittests/Tooling/DiagnosticsYamlTest.cpp - Serialization tests ---===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -21,11 +20,13 @@ using namespace clang::tooling;
using clang::tooling::Diagnostic;
static DiagnosticMessage makeMessage(const std::string &Message, int FileOffset,
- const std::string &FilePath) {
+ const std::string &FilePath,
+ const StringMap<Replacements> &Fix) {
DiagnosticMessage DiagMessage;
DiagMessage.Message = Message;
DiagMessage.FileOffset = FileOffset;
DiagMessage.FilePath = FilePath;
+ DiagMessage.Fix = Fix;
return DiagMessage;
}
@@ -33,10 +34,52 @@ static Diagnostic makeDiagnostic(StringRef DiagnosticName,
const std::string &Message, int FileOffset,
const std::string &FilePath,
const StringMap<Replacements> &Fix) {
- return Diagnostic(DiagnosticName, makeMessage(Message, FileOffset, FilePath),
- Fix, {}, Diagnostic::Warning, "path/to/build/directory");
+ return Diagnostic(DiagnosticName,
+ makeMessage(Message, FileOffset, FilePath, Fix), {},
+ Diagnostic::Warning, "path/to/build/directory");
}
+static const char *YAMLContent =
+ "---\n"
+ "MainSourceFile: 'path/to/source.cpp'\n"
+ "Diagnostics: \n"
+ " - DiagnosticName: 'diagnostic#1\'\n"
+ " DiagnosticMessage: \n"
+ " Message: 'message #1'\n"
+ " FilePath: 'path/to/source.cpp'\n"
+ " FileOffset: 55\n"
+ " Replacements: \n"
+ " - FilePath: 'path/to/source.cpp'\n"
+ " Offset: 100\n"
+ " Length: 12\n"
+ " ReplacementText: 'replacement #1'\n"
+ " - DiagnosticName: 'diagnostic#2'\n"
+ " DiagnosticMessage: \n"
+ " Message: 'message #2'\n"
+ " FilePath: 'path/to/header.h'\n"
+ " FileOffset: 60\n"
+ " Replacements: \n"
+ " - FilePath: 'path/to/header.h'\n"
+ " Offset: 62\n"
+ " Length: 2\n"
+ " ReplacementText: 'replacement #2'\n"
+ " - DiagnosticName: 'diagnostic#3'\n"
+ " DiagnosticMessage: \n"
+ " Message: 'message #3'\n"
+ " FilePath: 'path/to/source2.cpp'\n"
+ " FileOffset: 72\n"
+ " Replacements: []\n"
+ " Notes: \n"
+ " - Message: Note1\n"
+ " FilePath: 'path/to/note1.cpp'\n"
+ " FileOffset: 88\n"
+ " Replacements: []\n"
+ " - Message: Note2\n"
+ " FilePath: 'path/to/note2.cpp'\n"
+ " FileOffset: 99\n"
+ " Replacements: []\n"
+ "...\n";
+
TEST(DiagnosticsYamlTest, serializesDiagnostics) {
TranslationUnitDiagnostics TUD;
TUD.MainSourceFile = "path/to/source.cpp";
@@ -56,9 +99,9 @@ TEST(DiagnosticsYamlTest, serializesDiagnostics) {
TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#3", "message #3", 72,
"path/to/source2.cpp", {}));
TUD.Diagnostics.back().Notes.push_back(
- makeMessage("Note1", 88, "path/to/note1.cpp"));
+ makeMessage("Note1", 88, "path/to/note1.cpp", {}));
TUD.Diagnostics.back().Notes.push_back(
- makeMessage("Note2", 99, "path/to/note2.cpp"));
+ makeMessage("Note2", 99, "path/to/note2.cpp", {}));
std::string YamlContent;
raw_string_ostream YamlContentStream(YamlContent);
@@ -66,80 +109,12 @@ TEST(DiagnosticsYamlTest, serializesDiagnostics) {
yaml::Output YAML(YamlContentStream);
YAML << TUD;
- EXPECT_EQ("---\n"
- "MainSourceFile: 'path/to/source.cpp'\n"
- "Diagnostics: \n"
- " - DiagnosticName: 'diagnostic#1\'\n"
- " Message: 'message #1'\n"
- " FileOffset: 55\n"
- " FilePath: 'path/to/source.cpp'\n"
- " Replacements: \n"
- " - FilePath: 'path/to/source.cpp'\n"
- " Offset: 100\n"
- " Length: 12\n"
- " ReplacementText: 'replacement #1'\n"
- " - DiagnosticName: 'diagnostic#2'\n"
- " Message: 'message #2'\n"
- " FileOffset: 60\n"
- " FilePath: 'path/to/header.h'\n"
- " Replacements: \n"
- " - FilePath: 'path/to/header.h'\n"
- " Offset: 62\n"
- " Length: 2\n"
- " ReplacementText: 'replacement #2'\n"
- " - DiagnosticName: 'diagnostic#3'\n"
- " Message: 'message #3'\n"
- " FileOffset: 72\n"
- " FilePath: 'path/to/source2.cpp'\n"
- " Notes: \n"
- " - Message: Note1\n"
- " FilePath: 'path/to/note1.cpp'\n"
- " FileOffset: 88\n"
- " - Message: Note2\n"
- " FilePath: 'path/to/note2.cpp'\n"
- " FileOffset: 99\n"
- " Replacements: []\n"
- "...\n",
- YamlContentStream.str());
+ EXPECT_EQ(YAMLContent, YamlContentStream.str());
}
TEST(DiagnosticsYamlTest, deserializesDiagnostics) {
- std::string YamlContent = "---\n"
- "MainSourceFile: path/to/source.cpp\n"
- "Diagnostics: \n"
- " - DiagnosticName: 'diagnostic#1'\n"
- " Message: 'message #1'\n"
- " FileOffset: 55\n"
- " FilePath: path/to/source.cpp\n"
- " Replacements: \n"
- " - FilePath: path/to/source.cpp\n"
- " Offset: 100\n"
- " Length: 12\n"
- " ReplacementText: 'replacement #1'\n"
- " - DiagnosticName: 'diagnostic#2'\n"
- " Message: 'message #2'\n"
- " FileOffset: 60\n"
- " FilePath: path/to/header.h\n"
- " Replacements: \n"
- " - FilePath: path/to/header.h\n"
- " Offset: 62\n"
- " Length: 2\n"
- " ReplacementText: 'replacement #2'\n"
- " - DiagnosticName: 'diagnostic#3'\n"
- " Message: 'message #3'\n"
- " FileOffset: 98\n"
- " FilePath: path/to/source.cpp\n"
- " Notes:\n"
- " - Message: Note1\n"
- " FilePath: 'path/to/note1.cpp'\n"
- " FileOffset: 66\n"
- " - Message: Note2\n"
- " FilePath: 'path/to/note2.cpp'\n"
- " FileOffset: 77\n"
- " Replacements: []\n"
- "...\n";
TranslationUnitDiagnostics TUDActual;
- yaml::Input YAML(YamlContent);
+ yaml::Input YAML(YAMLContent);
YAML >> TUDActual;
ASSERT_FALSE(YAML.error());
@@ -161,7 +136,7 @@ TEST(DiagnosticsYamlTest, deserializesDiagnostics) {
EXPECT_EQ("message #1", D1.Message.Message);
EXPECT_EQ(55u, D1.Message.FileOffset);
EXPECT_EQ("path/to/source.cpp", D1.Message.FilePath);
- std::vector<Replacement> Fixes1 = getFixes(D1.Fix);
+ std::vector<Replacement> Fixes1 = getFixes(D1.Message.Fix);
ASSERT_EQ(1u, Fixes1.size());
EXPECT_EQ("path/to/source.cpp", Fixes1[0].getFilePath());
EXPECT_EQ(100u, Fixes1[0].getOffset());
@@ -173,7 +148,7 @@ TEST(DiagnosticsYamlTest, deserializesDiagnostics) {
EXPECT_EQ("message #2", D2.Message.Message);
EXPECT_EQ(60u, D2.Message.FileOffset);
EXPECT_EQ("path/to/header.h", D2.Message.FilePath);
- std::vector<Replacement> Fixes2 = getFixes(D2.Fix);
+ std::vector<Replacement> Fixes2 = getFixes(D2.Message.Fix);
ASSERT_EQ(1u, Fixes2.size());
EXPECT_EQ("path/to/header.h", Fixes2[0].getFilePath());
EXPECT_EQ(62u, Fixes2[0].getOffset());
@@ -183,15 +158,15 @@ TEST(DiagnosticsYamlTest, deserializesDiagnostics) {
Diagnostic D3 = TUDActual.Diagnostics[2];
EXPECT_EQ("diagnostic#3", D3.DiagnosticName);
EXPECT_EQ("message #3", D3.Message.Message);
- EXPECT_EQ(98u, D3.Message.FileOffset);
- EXPECT_EQ("path/to/source.cpp", D3.Message.FilePath);
+ EXPECT_EQ(72u, D3.Message.FileOffset);
+ EXPECT_EQ("path/to/source2.cpp", D3.Message.FilePath);
EXPECT_EQ(2u, D3.Notes.size());
EXPECT_EQ("Note1", D3.Notes[0].Message);
- EXPECT_EQ(66u, D3.Notes[0].FileOffset);
+ EXPECT_EQ(88u, D3.Notes[0].FileOffset);
EXPECT_EQ("path/to/note1.cpp", D3.Notes[0].FilePath);
EXPECT_EQ("Note2", D3.Notes[1].Message);
- EXPECT_EQ(77u, D3.Notes[1].FileOffset);
+ EXPECT_EQ(99u, D3.Notes[1].FileOffset);
EXPECT_EQ("path/to/note2.cpp", D3.Notes[1].FilePath);
- std::vector<Replacement> Fixes3 = getFixes(D3.Fix);
+ std::vector<Replacement> Fixes3 = getFixes(D3.Message.Fix);
EXPECT_TRUE(Fixes3.empty());
}
diff --git a/unittests/Tooling/ExecutionTest.cpp b/unittests/Tooling/ExecutionTest.cpp
index 785ec7c2bc..31d5fe5c42 100644
--- a/unittests/Tooling/ExecutionTest.cpp
+++ b/unittests/Tooling/ExecutionTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/ExecutionTest.cpp - Tool execution tests. --------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/FixItTest.cpp b/unittests/Tooling/FixItTest.cpp
index 365180e67f..ec9801d345 100644
--- a/unittests/Tooling/FixItTest.cpp
+++ b/unittests/Tooling/FixItTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/FixitTest.cpp ------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/HeaderIncludesTest.cpp b/unittests/Tooling/HeaderIncludesTest.cpp
index ff68f75a6e..635d7ebb1e 100644
--- a/unittests/Tooling/HeaderIncludesTest.cpp
+++ b/unittests/Tooling/HeaderIncludesTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/CleanupTest.cpp - Include insertion/deletion tests ===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -15,9 +14,6 @@
#include "gtest/gtest.h"
-using clang::tooling::ReplacementTest;
-using clang::tooling::toReplacements;
-
namespace clang {
namespace tooling {
namespace {
@@ -316,6 +312,17 @@ TEST_F(HeaderIncludesTest, RealHeaderGuardAfterComments) {
EXPECT_EQ(Expected, insert(Code, "<vector>"));
}
+TEST_F(HeaderIncludesTest, PragmaOnce) {
+ std::string Code = "// comment \n"
+ "#pragma once\n"
+ "int x;\n";
+ std::string Expected = "// comment \n"
+ "#pragma once\n"
+ "#include <vector>\n"
+ "int x;\n";
+ EXPECT_EQ(Expected, insert(Code, "<vector>"));
+}
+
TEST_F(HeaderIncludesTest, IfNDefWithNoDefine) {
std::string Code = "// comment \n"
"#ifndef X\n"
diff --git a/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp b/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
index 7387e9c44d..38079f706f 100644
--- a/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
+++ b/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/LookupTest.cpp b/unittests/Tooling/LookupTest.cpp
index a08b2b418f..372cbbf62b 100644
--- a/unittests/Tooling/LookupTest.cpp
+++ b/unittests/Tooling/LookupTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/LookupTest.cpp ------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -45,8 +44,8 @@ TEST(LookupTest, replaceNestedFunctionName) {
const auto *Callee = cast<DeclRefExpr>(Expr->getCallee()->IgnoreImplicit());
const ValueDecl *FD = Callee->getDecl();
return tooling::replaceNestedName(
- Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
- ReplacementString);
+ Callee->getQualifier(), Callee->getLocation(),
+ Visitor.DeclStack.back()->getDeclContext(), FD, ReplacementString);
};
Visitor.OnCall = [&](CallExpr *Expr) {
@@ -130,20 +129,38 @@ TEST(LookupTest, replaceNestedFunctionName) {
// If the shortest name is ambiguous, we need to add more qualifiers.
Visitor.OnCall = [&](CallExpr *Expr) {
- EXPECT_EQ("::a::y::bar", replaceCallExpr(Expr, "::a::y::bar"));
+ EXPECT_EQ("a::y::bar", replaceCallExpr(Expr, "::a::y::bar"));
};
Visitor.runOver(R"(
namespace a {
- namespace b {
- namespace x { void foo() {} }
- namespace y { void foo() {} }
- }
+ namespace b {
+ namespace x { void foo() {} }
+ namespace y { void foo() {} }
+ }
}
namespace a {
- namespace b {
- void f() { x::foo(); }
+ namespace b {
+ void f() { x::foo(); }
+ }
+ })");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ // y::bar would be ambiguous due to "a::b::y".
+ EXPECT_EQ("::y::bar", replaceCallExpr(Expr, "::y::bar"));
+ };
+ Visitor.runOver(R"(
+ namespace a {
+ namespace b {
+ void foo() {}
+ namespace y { }
+ }
}
+
+ namespace a {
+ namespace b {
+ void f() { foo(); }
+ }
})");
Visitor.OnCall = [&](CallExpr *Expr) {
@@ -164,12 +181,12 @@ TEST(LookupTest, replaceNestedFunctionName) {
TEST(LookupTest, replaceNestedClassName) {
GetDeclsVisitor Visitor;
- auto replaceRecordTypeLoc = [&](RecordTypeLoc Loc,
+ auto replaceRecordTypeLoc = [&](RecordTypeLoc TLoc,
StringRef ReplacementString) {
- const auto *FD = cast<CXXRecordDecl>(Loc.getDecl());
+ const auto *FD = cast<CXXRecordDecl>(TLoc.getDecl());
return tooling::replaceNestedName(
- nullptr, Visitor.DeclStack.back()->getDeclContext(), FD,
- ReplacementString);
+ nullptr, TLoc.getBeginLoc(), Visitor.DeclStack.back()->getDeclContext(),
+ FD, ReplacementString);
};
Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
@@ -194,6 +211,41 @@ TEST(LookupTest, replaceNestedClassName) {
};
Visitor.runOver("namespace a { namespace b { class Foo {}; } }\n"
"namespace c { using a::b::Foo; Foo f();; }\n");
+
+ // Rename TypeLoc `x::y::Old` to new name `x::Foo` at [0] and check that the
+ // type is replaced with "Foo" instead of "x::Foo". Although there is a symbol
+ // `x::y::Foo` in c.cc [1], it should not make "Foo" at [0] ambiguous because
+ // it's not visible at [0].
+ Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
+ if (Type.getDecl()->getQualifiedNameAsString() == "x::y::Old") {
+ EXPECT_EQ("Foo", replaceRecordTypeLoc(Type, "::x::Foo"));
+ }
+ };
+ Visitor.runOver(R"(
+ // a.h
+ namespace x {
+ namespace y {
+ class Old {};
+ class Other {};
+ }
+ }
+
+ // b.h
+ namespace x {
+ namespace y {
+ // This is to be renamed to x::Foo
+ // The expected replacement is "Foo".
+ Old f; // [0].
+ }
+ }
+
+ // c.cc
+ namespace x {
+ namespace y {
+ using Foo = ::x::y::Other; // [1]
+ }
+ }
+ )");
}
} // end anonymous namespace
diff --git a/unittests/Tooling/QualTypeNamesTest.cpp b/unittests/Tooling/QualTypeNamesTest.cpp
index b4c56f7bd5..b6c3029778 100644
--- a/unittests/Tooling/QualTypeNamesTest.cpp
+++ b/unittests/Tooling/QualTypeNamesTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/QualTypeNameTest.cpp ------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -195,6 +194,7 @@ TEST(QualTypeNameTest, getFullyQualifiedName) {
GlobalNsPrefix.ExpectedQualTypeNames["ZVal"] = "::A::B::Y::Z";
GlobalNsPrefix.ExpectedQualTypeNames["GlobalZVal"] = "::Z";
GlobalNsPrefix.ExpectedQualTypeNames["CheckK"] = "D::aStruct";
+ GlobalNsPrefix.ExpectedQualTypeNames["YZMPtr"] = "::A::B::X ::A::B::Y::Z::*";
GlobalNsPrefix.runOver(
"namespace A {\n"
" namespace B {\n"
@@ -206,8 +206,9 @@ TEST(QualTypeNameTest, getFullyQualifiedName) {
" template <typename T>\n"
" using Alias = CCC<T>;\n"
" Alias<int> IntAliasVal;\n"
- " struct Y { struct Z {}; };\n"
+ " struct Y { struct Z { X YZIPtr; }; };\n"
" Y::Z ZVal;\n"
+ " X Y::Z::*YZMPtr;\n"
" }\n"
"}\n"
"struct Z {};\n"
diff --git a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
index e91873c406..e207f03971 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
index 2e7b398c3d..965bb3d7b7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp
@@ -1,9 +1,8 @@
//===- unittests/Tooling/RecursiveASTVisitorPostOrderASTVisitor.cpp -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
index dc2adaf4da..299e1b022a 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
index 33163c30e5..022ef8b832 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/Attr.cpp -----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
index ca2e4a4691..1fb192dcda 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp ---===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
index a83e55137a..c7b31e06e0 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp --------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
index 414b0f0174..91de8d17c9 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp b/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
index 666c924d1a..3ea5abd46a 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/Class.cpp ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
index f775a31e59..b4f4f54dc7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp --------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
index cd0e4260a8..adc972e1c3 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp b/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
index c2194ab292..27999e5ef8 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
index 396f25de5c..80d9c98735 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp -==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
index 587f84bb43..a15f4c83c5 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
index 01f6e19029..401ae6b15d 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
index d48b5a89c8..1dafeef7cd 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp b/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
index 218f7e0c2d..3fc3cb1a99 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
index c3f8e4f419..b1d6d593e7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
index d3a3eba15d..560cdf95c0 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
new file mode 100644
index 0000000000..d0e4fb733e
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
@@ -0,0 +1,53 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+ : public ExpectedLocationVisitor<LambdaTemplateParametersVisitor> {
+public:
+ bool shouldVisitImplicitCode() const { return false; }
+
+ bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ EXPECT_FALSE(D->isImplicit());
+ Match(D->getName(), D->getLocStart());
+ return true;
+ }
+
+ bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ EXPECT_FALSE(D->isImplicit());
+ Match(D->getName(), D->getLocStart());
+ return true;
+ }
+
+ bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ EXPECT_FALSE(D->isImplicit());
+ Match(D->getName(), D->getLocStart());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+ LambdaTemplateParametersVisitor Visitor;
+ Visitor.ExpectMatch("T", 2, 15);
+ Visitor.ExpectMatch("I", 2, 24);
+ Visitor.ExpectMatch("TT", 2, 31);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { \n"
+ " auto l = []<class T, int I, template<class> class TT>(auto p) { }; \n"
+ "}",
+ LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
index 23afda6e87..868a3988c7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
index b6a5a18e01..c316f98f40 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
index 0c9cbf2eb4..ae427a02bc 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp b/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
index 72f6c644b3..c05be7f2e3 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RefactoringActionRulesTest.cpp b/unittests/Tooling/RefactoringActionRulesTest.cpp
index acacfa05b4..7daef33337 100644
--- a/unittests/Tooling/RefactoringActionRulesTest.cpp
+++ b/unittests/Tooling/RefactoringActionRulesTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RefactoringTestActionRulesTest.cpp ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RefactoringCallbacksTest.cpp b/unittests/Tooling/RefactoringCallbacksTest.cpp
index e226522a70..1663581d65 100644
--- a/unittests/Tooling/RefactoringCallbacksTest.cpp
+++ b/unittests/Tooling/RefactoringCallbacksTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RefactoringCallbacksTest.cpp ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp
index d618c0fb07..ed111b7878 100644
--- a/unittests/Tooling/RefactoringTest.cpp
+++ b/unittests/Tooling/RefactoringTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RefactoringTest.cpp - Refactoring unit tests ------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/ReplacementTest.h b/unittests/Tooling/ReplacementTest.h
index b6fe5c79b7..b97e0e7f2f 100644
--- a/unittests/Tooling/ReplacementTest.h
+++ b/unittests/Tooling/ReplacementTest.h
@@ -1,9 +1,8 @@
//===- unittest/Tooling/ReplacementTest.h - Replacements related test------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/unittests/Tooling/ReplacementsYamlTest.cpp b/unittests/Tooling/ReplacementsYamlTest.cpp
index 2e5a87a931..ab9f6c9b5d 100644
--- a/unittests/Tooling/ReplacementsYamlTest.cpp
+++ b/unittests/Tooling/ReplacementsYamlTest.cpp
@@ -1,9 +1,8 @@
//===- unittests/Tooling/ReplacementsYamlTest.cpp - Serialization tests ---===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/unittests/Tooling/RewriterTest.cpp b/unittests/Tooling/RewriterTest.cpp
index 4305d421e1..e744940783 100644
--- a/unittests/Tooling/RewriterTest.cpp
+++ b/unittests/Tooling/RewriterTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/RewriterTest.cpp ----------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/unittests/Tooling/RewriterTestContext.h b/unittests/Tooling/RewriterTestContext.h
index 9e66484158..ba919d6472 100644
--- a/unittests/Tooling/RewriterTestContext.h
+++ b/unittests/Tooling/RewriterTestContext.h
@@ -1,9 +1,8 @@
//===--- RewriterTestContext.h ----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/unittests/Tooling/SourceCodeTest.cpp b/unittests/Tooling/SourceCodeTest.cpp
new file mode 100644
index 0000000000..258947a1a7
--- /dev/null
+++ b/unittests/Tooling/SourceCodeTest.cpp
@@ -0,0 +1,97 @@
+//===- unittest/Tooling/SourceCodeTest.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Tooling/Refactoring/SourceCode.h"
+
+using namespace clang;
+
+using tooling::getText;
+using tooling::getExtendedText;
+
+namespace {
+
+struct CallsVisitor : TestVisitor<CallsVisitor> {
+ bool VisitCallExpr(CallExpr *Expr) {
+ OnCall(Expr, Context);
+ return true;
+ }
+
+ std::function<void(CallExpr *, ASTContext *Context)> OnCall;
+};
+
+TEST(SourceCodeTest, getText) {
+ CallsVisitor Visitor;
+
+ Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
+ EXPECT_EQ("foo(x, y)", getText(*CE, *Context));
+ };
+ Visitor.runOver("void foo(int x, int y) { foo(x, y); }");
+
+ Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
+ EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context));
+ };
+ Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n"
+ "void foo(int x, int y) { APPLY(foo, x, y); }");
+}
+
+TEST(SourceCodeTest, getTextWithMacro) {
+ CallsVisitor Visitor;
+
+ Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
+ EXPECT_EQ("F OO", getText(*CE, *Context));
+ Expr *P0 = CE->getArg(0);
+ Expr *P1 = CE->getArg(1);
+ EXPECT_EQ("", getText(*P0, *Context));
+ EXPECT_EQ("", getText(*P1, *Context));
+ };
+ Visitor.runOver("#define F foo(\n"
+ "#define OO x, y)\n"
+ "void foo(int x, int y) { F OO ; }");
+
+ Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
+ EXPECT_EQ("", getText(*CE, *Context));
+ Expr *P0 = CE->getArg(0);
+ Expr *P1 = CE->getArg(1);
+ EXPECT_EQ("x", getText(*P0, *Context));
+ EXPECT_EQ("y", getText(*P1, *Context));
+ };
+ Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"
+ "void foo(int x, int y) { FOO(x,y) }");
+}
+
+TEST(SourceCodeTest, getExtendedText) {
+ CallsVisitor Visitor;
+
+ Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
+ EXPECT_EQ("foo(x, y);",
+ getExtendedText(*CE, tok::TokenKind::semi, *Context));
+
+ Expr *P0 = CE->getArg(0);
+ Expr *P1 = CE->getArg(1);
+ EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context));
+ EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context));
+ EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context));
+ };
+ Visitor.runOver("void foo(int x, int y) { foo(x, y); }");
+ Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }");
+ Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }");
+ Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }");
+ Visitor.runOver(
+ "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }");
+
+ Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
+ EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context));
+ };
+ Visitor.runOver("bool foo() { if (foo()) return true; return false; }");
+ Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }");
+ Visitor.runOver("int foo() { return foo() + 3; }");
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/StencilTest.cpp b/unittests/Tooling/StencilTest.cpp
new file mode 100644
index 0000000000..ffdca0562e
--- /dev/null
+++ b/unittests/Tooling/StencilTest.cpp
@@ -0,0 +1,223 @@
+//===- unittest/Tooling/StencilTest.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Stencil.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/FixIt.h"
+#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace tooling;
+using namespace ast_matchers;
+
+namespace {
+using ::testing::AllOf;
+using ::testing::Eq;
+using ::testing::HasSubstr;
+using MatchResult = MatchFinder::MatchResult;
+using tooling::stencil::node;
+using tooling::stencil::sNode;
+using tooling::stencil::text;
+
+// In tests, we can't directly match on llvm::Expected since its accessors
+// mutate the object. So, we collapse it to an Optional.
+static llvm::Optional<std::string> toOptional(llvm::Expected<std::string> V) {
+ if (V)
+ return *V;
+ ADD_FAILURE() << "Losing error in conversion to IsSomething: "
+ << llvm::toString(V.takeError());
+ return llvm::None;
+}
+
+// A very simple matcher for llvm::Optional values.
+MATCHER_P(IsSomething, ValueMatcher, "") {
+ if (!arg)
+ return false;
+ return ::testing::ExplainMatchResult(ValueMatcher, *arg, result_listener);
+}
+
+// Create a valid translation-unit from a statement.
+static std::string wrapSnippet(llvm::Twine StatementCode) {
+ return ("auto stencil_test_snippet = []{" + StatementCode + "};").str();
+}
+
+static DeclarationMatcher wrapMatcher(const StatementMatcher &Matcher) {
+ return varDecl(hasName("stencil_test_snippet"),
+ hasDescendant(compoundStmt(hasAnySubstatement(Matcher))));
+}
+
+struct TestMatch {
+ // The AST unit from which `result` is built. We bundle it because it backs
+ // the result. Users are not expected to access it.
+ std::unique_ptr<ASTUnit> AstUnit;
+ // The result to use in the test. References `ast_unit`.
+ MatchResult Result;
+};
+
+// Matches `Matcher` against the statement `StatementCode` and returns the
+// result. Handles putting the statement inside a function and modifying the
+// matcher correspondingly. `Matcher` should match `StatementCode` exactly --
+// that is, produce exactly one match.
+static llvm::Optional<TestMatch> matchStmt(llvm::Twine StatementCode,
+ StatementMatcher Matcher) {
+ auto AstUnit = buildASTFromCode(wrapSnippet(StatementCode));
+ if (AstUnit == nullptr) {
+ ADD_FAILURE() << "AST construction failed";
+ return llvm::None;
+ }
+ ASTContext &Context = AstUnit->getASTContext();
+ auto Matches = ast_matchers::match(wrapMatcher(Matcher), Context);
+ // We expect a single, exact match for the statement.
+ if (Matches.size() != 1) {
+ ADD_FAILURE() << "Wrong number of matches: " << Matches.size();
+ return llvm::None;
+ }
+ return TestMatch{std::move(AstUnit), MatchResult(Matches[0], &Context)};
+}
+
+class StencilTest : public ::testing::Test {
+protected:
+ // Verifies that the given stencil fails when evaluated on a valid match
+ // result. Binds a statement to "stmt", a (non-member) ctor-initializer to
+ // "init", an expression to "expr" and a (nameless) declaration to "decl".
+ void testError(const Stencil &Stencil,
+ ::testing::Matcher<std::string> Matcher) {
+ const std::string Snippet = R"cc(
+ struct A {};
+ class F : public A {
+ public:
+ F(int) {}
+ };
+ F(1);
+ )cc";
+ auto StmtMatch = matchStmt(
+ Snippet,
+ stmt(hasDescendant(
+ cxxConstructExpr(
+ hasDeclaration(decl(hasDescendant(cxxCtorInitializer(
+ isBaseInitializer())
+ .bind("init")))
+ .bind("decl")))
+ .bind("expr")))
+ .bind("stmt"));
+ ASSERT_TRUE(StmtMatch);
+ if (auto ResultOrErr = Stencil.eval(StmtMatch->Result)) {
+ ADD_FAILURE() << "Expected failure but succeeded: " << *ResultOrErr;
+ } else {
+ auto Err = llvm::handleErrors(ResultOrErr.takeError(),
+ [&Matcher](const llvm::StringError &Err) {
+ EXPECT_THAT(Err.getMessage(), Matcher);
+ });
+ if (Err) {
+ ADD_FAILURE() << "Unhandled error: " << llvm::toString(std::move(Err));
+ }
+ }
+ }
+
+ // Tests failures caused by references to unbound nodes. `unbound_id` is the
+ // id that will cause the failure.
+ void testUnboundNodeError(const Stencil &Stencil, llvm::StringRef UnboundId) {
+ testError(Stencil, AllOf(HasSubstr(UnboundId), HasSubstr("not bound")));
+ }
+};
+
+TEST_F(StencilTest, SingleStatement) {
+ StringRef Condition("C"), Then("T"), Else("E");
+ const std::string Snippet = R"cc(
+ if (true)
+ return 1;
+ else
+ return 0;
+ )cc";
+ auto StmtMatch = matchStmt(
+ Snippet, ifStmt(hasCondition(expr().bind(Condition)),
+ hasThen(stmt().bind(Then)), hasElse(stmt().bind(Else))));
+ ASSERT_TRUE(StmtMatch);
+ // Invert the if-then-else.
+ auto Stencil = Stencil::cat("if (!", node(Condition), ") ", sNode(Else),
+ " else ", sNode(Then));
+ EXPECT_THAT(toOptional(Stencil.eval(StmtMatch->Result)),
+ IsSomething(Eq("if (!true) return 0; else return 1;")));
+}
+
+TEST_F(StencilTest, SingleStatementCallOperator) {
+ StringRef Condition("C"), Then("T"), Else("E");
+ const std::string Snippet = R"cc(
+ if (true)
+ return 1;
+ else
+ return 0;
+ )cc";
+ auto StmtMatch = matchStmt(
+ Snippet, ifStmt(hasCondition(expr().bind(Condition)),
+ hasThen(stmt().bind(Then)), hasElse(stmt().bind(Else))));
+ ASSERT_TRUE(StmtMatch);
+ // Invert the if-then-else.
+ Stencil S = Stencil::cat("if (!", node(Condition), ") ", sNode(Else),
+ " else ", sNode(Then));
+ EXPECT_THAT(toOptional(S(StmtMatch->Result)),
+ IsSomething(Eq("if (!true) return 0; else return 1;")));
+}
+
+TEST_F(StencilTest, UnboundNode) {
+ const std::string Snippet = R"cc(
+ if (true)
+ return 1;
+ else
+ return 0;
+ )cc";
+ auto StmtMatch = matchStmt(Snippet, ifStmt(hasCondition(stmt().bind("a1")),
+ hasThen(stmt().bind("a2"))));
+ ASSERT_TRUE(StmtMatch);
+ auto Stencil = Stencil::cat("if(!", sNode("a1"), ") ", node("UNBOUND"), ";");
+ auto ResultOrErr = Stencil.eval(StmtMatch->Result);
+ EXPECT_TRUE(llvm::errorToBool(ResultOrErr.takeError()))
+ << "Expected unbound node, got " << *ResultOrErr;
+}
+
+// Tests that a stencil with a single parameter (`Id`) evaluates to the expected
+// string, when `Id` is bound to the expression-statement in `Snippet`.
+void testExpr(StringRef Id, StringRef Snippet, const Stencil &Stencil,
+ StringRef Expected) {
+ auto StmtMatch = matchStmt(Snippet, expr().bind(Id));
+ ASSERT_TRUE(StmtMatch);
+ EXPECT_THAT(toOptional(Stencil.eval(StmtMatch->Result)),
+ IsSomething(Expected));
+}
+
+TEST_F(StencilTest, NodeOp) {
+ StringRef Id = "id";
+ testExpr(Id, "3;", Stencil::cat(node(Id)), "3");
+}
+
+TEST_F(StencilTest, SNodeOp) {
+ StringRef Id = "id";
+ testExpr(Id, "3;", Stencil::cat(sNode(Id)), "3;");
+}
+
+TEST(StencilEqualityTest, Equality) {
+ using stencil::dPrint;
+ auto Lhs = Stencil::cat("foo", node("node"), dPrint("dprint_id"));
+ auto Rhs = Lhs;
+ EXPECT_EQ(Lhs, Rhs);
+}
+
+TEST(StencilEqualityTest, InEqualityDifferentOrdering) {
+ auto Lhs = Stencil::cat("foo", node("node"));
+ auto Rhs = Stencil::cat(node("node"), "foo");
+ EXPECT_NE(Lhs, Rhs);
+}
+
+TEST(StencilEqualityTest, InEqualityDifferentSizes) {
+ auto Lhs = Stencil::cat("foo", node("node"), "bar", "baz");
+ auto Rhs = Stencil::cat("foo", node("node"), "bar");
+ EXPECT_NE(Lhs, Rhs);
+}
+} // namespace
diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h
index 1a22ae737b..ff90a77a69 100644
--- a/unittests/Tooling/TestVisitor.h
+++ b/unittests/Tooling/TestVisitor.h
@@ -1,9 +1,8 @@
//===--- TestVisitor.h ------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index 186463f80a..34f68a6aeb 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -1,9 +1,8 @@
//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -383,7 +382,7 @@ TEST(ClangToolTest, ArgumentAdjusters) {
ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
[&Found, &Ran](const CommandLineArguments &Args, StringRef /*unused*/) {
Ran = true;
- if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end())
+ if (llvm::is_contained(Args, "-fsyntax-only"))
Found = true;
return Args;
};
@@ -441,8 +440,7 @@ TEST(ClangToolTest, StripDependencyFileAdjuster) {
Tool.run(Action.get());
auto HasFlag = [&FinalArgs](const std::string &Flag) {
- return std::find(FinalArgs.begin(), FinalArgs.end(), Flag) !=
- FinalArgs.end();
+ return llvm::find(FinalArgs, Flag) != FinalArgs.end();
};
EXPECT_FALSE(HasFlag("-MD"));
EXPECT_FALSE(HasFlag("-MMD"));
@@ -450,6 +448,36 @@ TEST(ClangToolTest, StripDependencyFileAdjuster) {
EXPECT_TRUE(HasFlag("-w"));
}
+// Check getClangStripPluginsAdjuster strips plugin related args.
+TEST(ClangToolTest, StripPluginsAdjuster) {
+ FixedCompilationDatabase Compilations(
+ "/", {"-Xclang", "-add-plugin", "-Xclang", "random-plugin"});
+
+ ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
+ Tool.mapVirtualFile("/a.cc", "void a() {}");
+
+ std::unique_ptr<FrontendActionFactory> Action(
+ newFrontendActionFactory<SyntaxOnlyAction>());
+
+ CommandLineArguments FinalArgs;
+ ArgumentsAdjuster CheckFlagsAdjuster =
+ [&FinalArgs](const CommandLineArguments &Args, StringRef /*unused*/) {
+ FinalArgs = Args;
+ return Args;
+ };
+ Tool.clearArgumentsAdjusters();
+ Tool.appendArgumentsAdjuster(getStripPluginsAdjuster());
+ Tool.appendArgumentsAdjuster(CheckFlagsAdjuster);
+ Tool.run(Action.get());
+
+ auto HasFlag = [&FinalArgs](const std::string &Flag) {
+ return llvm::find(FinalArgs, Flag) != FinalArgs.end();
+ };
+ EXPECT_FALSE(HasFlag("-Xclang"));
+ EXPECT_FALSE(HasFlag("-add-plugin"));
+ EXPECT_FALSE(HasFlag("-random-plugin"));
+}
+
namespace {
/// Find a target name such that looking for it in TargetRegistry by that name
/// returns the same target. We expect that there is at least one target
diff --git a/unittests/Tooling/TransformerTest.cpp b/unittests/Tooling/TransformerTest.cpp
new file mode 100644
index 0000000000..e07d9b7029
--- /dev/null
+++ b/unittests/Tooling/TransformerTest.cpp
@@ -0,0 +1,462 @@
+//===- unittest/Tooling/TransformerTest.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Refactoring/Transformer.h"
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace tooling;
+using namespace ast_matchers;
+
+namespace {
+using ::testing::IsEmpty;
+
+constexpr char KHeaderContents[] = R"cc(
+ struct string {
+ string(const char*);
+ char* c_str();
+ int size();
+ };
+ int strlen(const char*);
+
+ namespace proto {
+ struct PCFProto {
+ int foo();
+ };
+ struct ProtoCommandLineFlag : PCFProto {
+ PCFProto& GetProto();
+ };
+ } // namespace proto
+ class Logger {};
+ void operator<<(Logger& l, string msg);
+ Logger& log(int level);
+)cc";
+
+static ast_matchers::internal::Matcher<clang::QualType>
+isOrPointsTo(const clang::ast_matchers::DeclarationMatcher &TypeMatcher) {
+ return anyOf(hasDeclaration(TypeMatcher), pointsTo(TypeMatcher));
+}
+
+static std::string format(StringRef Code) {
+ const std::vector<Range> Ranges(1, Range(0, Code.size()));
+ auto Style = format::getLLVMStyle();
+ const auto Replacements = format::reformat(Style, Code, Ranges);
+ auto Formatted = applyAllReplacements(Code, Replacements);
+ if (!Formatted) {
+ ADD_FAILURE() << "Could not format code: "
+ << llvm::toString(Formatted.takeError());
+ return std::string();
+ }
+ return *Formatted;
+}
+
+static void compareSnippets(StringRef Expected,
+ const llvm::Optional<std::string> &MaybeActual) {
+ ASSERT_TRUE(MaybeActual) << "Rewrite failed. Expecting: " << Expected;
+ auto Actual = *MaybeActual;
+ std::string HL = "#include \"header.h\"\n";
+ auto I = Actual.find(HL);
+ if (I != std::string::npos)
+ Actual.erase(I, HL.size());
+ EXPECT_EQ(format(Expected), format(Actual));
+}
+
+// FIXME: consider separating this class into its own file(s).
+class ClangRefactoringTestBase : public testing::Test {
+protected:
+ void appendToHeader(StringRef S) { FileContents[0].second += S; }
+
+ void addFile(StringRef Filename, StringRef Content) {
+ FileContents.emplace_back(Filename, Content);
+ }
+
+ llvm::Optional<std::string> rewrite(StringRef Input) {
+ std::string Code = ("#include \"header.h\"\n" + Input).str();
+ auto Factory = newFrontendActionFactory(&MatchFinder);
+ if (!runToolOnCodeWithArgs(
+ Factory->create(), Code, std::vector<std::string>(), "input.cc",
+ "clang-tool", std::make_shared<PCHContainerOperations>(),
+ FileContents)) {
+ llvm::errs() << "Running tool failed.\n";
+ return None;
+ }
+ if (ErrorCount != 0) {
+ llvm::errs() << "Generating changes failed.\n";
+ return None;
+ }
+ auto ChangedCode =
+ applyAtomicChanges("input.cc", Code, Changes, ApplyChangesSpec());
+ if (!ChangedCode) {
+ llvm::errs() << "Applying changes failed: "
+ << llvm::toString(ChangedCode.takeError()) << "\n";
+ return None;
+ }
+ return *ChangedCode;
+ }
+
+ Transformer::ChangeConsumer consumer() {
+ return [this](Expected<AtomicChange> C) {
+ if (C) {
+ Changes.push_back(std::move(*C));
+ } else {
+ consumeError(C.takeError());
+ ++ErrorCount;
+ }
+ };
+ }
+
+ void testRule(RewriteRule Rule, StringRef Input, StringRef Expected) {
+ Transformer T(std::move(Rule), consumer());
+ T.registerMatchers(&MatchFinder);
+ compareSnippets(Expected, rewrite(Input));
+ }
+
+ clang::ast_matchers::MatchFinder MatchFinder;
+ // Records whether any errors occurred in individual changes.
+ int ErrorCount = 0;
+ AtomicChanges Changes;
+
+private:
+ FileContentMappings FileContents = {{"header.h", ""}};
+};
+
+class TransformerTest : public ClangRefactoringTestBase {
+protected:
+ TransformerTest() { appendToHeader(KHeaderContents); }
+};
+
+// Given string s, change strlen($s.c_str()) to $s.size().
+static RewriteRule ruleStrlenSize() {
+ StringRef StringExpr = "strexpr";
+ auto StringType = namedDecl(hasAnyName("::basic_string", "::string"));
+ auto R = makeRule(
+ callExpr(callee(functionDecl(hasName("strlen"))),
+ hasArgument(0, cxxMemberCallExpr(
+ on(expr(hasType(isOrPointsTo(StringType)))
+ .bind(StringExpr)),
+ callee(cxxMethodDecl(hasName("c_str")))))),
+ change<clang::Expr>("REPLACED"));
+ R.Explanation = text("Use size() method directly on string.");
+ return R;
+}
+
+TEST_F(TransformerTest, StrlenSize) {
+ std::string Input = "int f(string s) { return strlen(s.c_str()); }";
+ std::string Expected = "int f(string s) { return REPLACED; }";
+ testRule(ruleStrlenSize(), Input, Expected);
+}
+
+// Tests that no change is applied when a match is not expected.
+TEST_F(TransformerTest, NoMatch) {
+ std::string Input = "int f(string s) { return s.size(); }";
+ testRule(ruleStrlenSize(), Input, Input);
+}
+
+// Tests that expressions in macro arguments are rewritten (when applicable).
+TEST_F(TransformerTest, StrlenSizeMacro) {
+ std::string Input = R"cc(
+#define ID(e) e
+ int f(string s) { return ID(strlen(s.c_str())); })cc";
+ std::string Expected = R"cc(
+#define ID(e) e
+ int f(string s) { return ID(REPLACED); })cc";
+ testRule(ruleStrlenSize(), Input, Expected);
+}
+
+// Tests replacing an expression.
+TEST_F(TransformerTest, Flag) {
+ StringRef Flag = "flag";
+ RewriteRule Rule = makeRule(
+ cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
+ hasName("proto::ProtoCommandLineFlag"))))
+ .bind(Flag)),
+ unless(callee(cxxMethodDecl(hasName("GetProto"))))),
+ change<clang::Expr>(Flag, "EXPR"));
+
+ std::string Input = R"cc(
+ proto::ProtoCommandLineFlag flag;
+ int x = flag.foo();
+ int y = flag.GetProto().foo();
+ )cc";
+ std::string Expected = R"cc(
+ proto::ProtoCommandLineFlag flag;
+ int x = EXPR.foo();
+ int y = flag.GetProto().foo();
+ )cc";
+
+ testRule(std::move(Rule), Input, Expected);
+}
+
+TEST_F(TransformerTest, NodePartNameNamedDecl) {
+ StringRef Fun = "fun";
+ RewriteRule Rule =
+ makeRule(functionDecl(hasName("bad")).bind(Fun),
+ change<clang::FunctionDecl>(Fun, NodePart::Name, "good"));
+
+ std::string Input = R"cc(
+ int bad(int x);
+ int bad(int x) { return x * x; }
+ )cc";
+ std::string Expected = R"cc(
+ int good(int x);
+ int good(int x) { return x * x; }
+ )cc";
+
+ testRule(Rule, Input, Expected);
+}
+
+TEST_F(TransformerTest, NodePartNameDeclRef) {
+ std::string Input = R"cc(
+ template <typename T>
+ T bad(T x) {
+ return x;
+ }
+ int neutral(int x) { return bad<int>(x) * x; }
+ )cc";
+ std::string Expected = R"cc(
+ template <typename T>
+ T bad(T x) {
+ return x;
+ }
+ int neutral(int x) { return good<int>(x) * x; }
+ )cc";
+
+ StringRef Ref = "ref";
+ testRule(makeRule(declRefExpr(to(functionDecl(hasName("bad")))).bind(Ref),
+ change<clang::Expr>(Ref, NodePart::Name, "good")),
+ Input, Expected);
+}
+
+TEST_F(TransformerTest, NodePartNameDeclRefFailure) {
+ std::string Input = R"cc(
+ struct Y {
+ int operator*();
+ };
+ int neutral(int x) {
+ Y y;
+ int (Y::*ptr)() = &Y::operator*;
+ return *y + x;
+ }
+ )cc";
+
+ StringRef Ref = "ref";
+ Transformer T(makeRule(declRefExpr(to(functionDecl())).bind(Ref),
+ change<clang::Expr>(Ref, NodePart::Name, "good")),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ EXPECT_FALSE(rewrite(Input));
+}
+
+TEST_F(TransformerTest, NodePartMember) {
+ StringRef E = "expr";
+ RewriteRule Rule = makeRule(memberExpr(member(hasName("bad"))).bind(E),
+ change<clang::Expr>(E, NodePart::Member, "good"));
+
+ std::string Input = R"cc(
+ struct S {
+ int bad;
+ };
+ int g() {
+ S s;
+ return s.bad;
+ }
+ )cc";
+ std::string Expected = R"cc(
+ struct S {
+ int bad;
+ };
+ int g() {
+ S s;
+ return s.good;
+ }
+ )cc";
+
+ testRule(Rule, Input, Expected);
+}
+
+TEST_F(TransformerTest, NodePartMemberQualified) {
+ std::string Input = R"cc(
+ struct S {
+ int bad;
+ int good;
+ };
+ struct T : public S {
+ int bad;
+ };
+ int g() {
+ T t;
+ return t.S::bad;
+ }
+ )cc";
+ std::string Expected = R"cc(
+ struct S {
+ int bad;
+ int good;
+ };
+ struct T : public S {
+ int bad;
+ };
+ int g() {
+ T t;
+ return t.S::good;
+ }
+ )cc";
+
+ StringRef E = "expr";
+ testRule(makeRule(memberExpr().bind(E),
+ change<clang::Expr>(E, NodePart::Member, "good")),
+ Input, Expected);
+}
+
+TEST_F(TransformerTest, NodePartMemberMultiToken) {
+ std::string Input = R"cc(
+ struct Y {
+ int operator*();
+ int good();
+ template <typename T> void foo(T t);
+ };
+ int neutral(int x) {
+ Y y;
+ y.template foo<int>(3);
+ return y.operator *();
+ }
+ )cc";
+ std::string Expected = R"cc(
+ struct Y {
+ int operator*();
+ int good();
+ template <typename T> void foo(T t);
+ };
+ int neutral(int x) {
+ Y y;
+ y.template good<int>(3);
+ return y.good();
+ }
+ )cc";
+
+ StringRef MemExpr = "member";
+ testRule(makeRule(memberExpr().bind(MemExpr),
+ change<clang::Expr>(MemExpr, NodePart::Member, "good")),
+ Input, Expected);
+}
+
+TEST_F(TransformerTest, MultiChange) {
+ std::string Input = R"cc(
+ void foo() {
+ if (10 > 1.0)
+ log(1) << "oh no!";
+ else
+ log(0) << "ok";
+ }
+ )cc";
+ std::string Expected = R"(
+ void foo() {
+ if (true) { /* then */ }
+ else { /* else */ }
+ }
+ )";
+
+ StringRef C = "C", T = "T", E = "E";
+ testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
+ hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
+ {change<Expr>(C, "true"), change<Stmt>(T, "{ /* then */ }"),
+ change<Stmt>(E, "{ /* else */ }")}),
+ Input, Expected);
+}
+
+//
+// Negative tests (where we expect no transformation to occur).
+//
+
+// Tests for a conflict in edits from a single match for a rule.
+TEST_F(TransformerTest, TextGeneratorFailure) {
+ std::string Input = "int conflictOneRule() { return 3 + 7; }";
+ // Try to change the whole binary-operator expression AND one its operands:
+ StringRef O = "O";
+ auto AlwaysFail = [](const ast_matchers::MatchFinder::MatchResult &)
+ -> llvm::Expected<std::string> {
+ return llvm::createStringError(llvm::errc::invalid_argument, "ERROR");
+ };
+ Transformer T(makeRule(binaryOperator().bind(O), change<Expr>(O, AlwaysFail)),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ EXPECT_FALSE(rewrite(Input));
+ EXPECT_THAT(Changes, IsEmpty());
+ EXPECT_EQ(ErrorCount, 1);
+}
+
+// Tests for a conflict in edits from a single match for a rule.
+TEST_F(TransformerTest, OverlappingEditsInRule) {
+ std::string Input = "int conflictOneRule() { return 3 + 7; }";
+ // Try to change the whole binary-operator expression AND one its operands:
+ StringRef O = "O", L = "L";
+ Transformer T(
+ makeRule(binaryOperator(hasLHS(expr().bind(L))).bind(O),
+ {change<Expr>(O, "DELETE_OP"), change<Expr>(L, "DELETE_LHS")}),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ EXPECT_FALSE(rewrite(Input));
+ EXPECT_THAT(Changes, IsEmpty());
+ EXPECT_EQ(ErrorCount, 1);
+}
+
+// Tests for a conflict in edits across multiple matches (of the same rule).
+TEST_F(TransformerTest, OverlappingEditsMultipleMatches) {
+ std::string Input = "int conflictOneRule() { return -7; }";
+ // Try to change the whole binary-operator expression AND one its operands:
+ StringRef E = "E";
+ Transformer T(makeRule(expr().bind(E), change<Expr>(E, "DELETE_EXPR")),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ // The rewrite process fails because the changes conflict with each other...
+ EXPECT_FALSE(rewrite(Input));
+ // ... but two changes were produced.
+ EXPECT_EQ(Changes.size(), 2u);
+ EXPECT_EQ(ErrorCount, 0);
+}
+
+TEST_F(TransformerTest, ErrorOccurredMatchSkipped) {
+ // Syntax error in the function body:
+ std::string Input = "void errorOccurred() { 3 }";
+ Transformer T(makeRule(functionDecl(hasName("errorOccurred")),
+ change<Decl>("DELETED;")),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ // The rewrite process itself fails...
+ EXPECT_FALSE(rewrite(Input));
+ // ... and no changes or errors are produced in the process.
+ EXPECT_THAT(Changes, IsEmpty());
+ EXPECT_EQ(ErrorCount, 0);
+}
+
+TEST_F(TransformerTest, NoTransformationInMacro) {
+ std::string Input = R"cc(
+#define MACRO(str) strlen((str).c_str())
+ int f(string s) { return MACRO(s); })cc";
+ testRule(ruleStrlenSize(), Input, Input);
+}
+
+// This test handles the corner case where a macro called within another macro
+// expands to matching code, but the matched code is an argument to the nested
+// macro. A simple check of isMacroArgExpansion() vs. isMacroBodyExpansion()
+// will get this wrong, and transform the code. This test verifies that no such
+// transformation occurs.
+TEST_F(TransformerTest, NoTransformationInNestedMacro) {
+ std::string Input = R"cc(
+#define NESTED(e) e
+#define MACRO(str) NESTED(strlen((str).c_str()))
+ int f(string s) { return MACRO(s); })cc";
+ testRule(ruleStrlenSize(), Input, Input);
+}
+} // namespace