aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Tooling/TransformerTest.cpp
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2020-06-01 13:40:20 +0100
committerStephen Kelly <steveire@gmail.com>2020-11-02 20:21:48 +0000
commit53df3beb624989ed32d87697d0c17601d7871465 (patch)
tree48532289c96591f82be7fe46826f8ba683e0e081 /clang/unittests/Tooling/TransformerTest.cpp
parent537cc6dd2b36a7219a9bbaa6bc6f32c99a1baae1 (diff)
downloadllvm-53df3beb624989ed32d87697d0c17601d7871465.zip
llvm-53df3beb624989ed32d87697d0c17601d7871465.tar.gz
llvm-53df3beb624989ed32d87697d0c17601d7871465.tar.bz2
Ignore template instantiations if not in AsIs mode
Summary: IgnoreUnlessSpelledInSource mode should ignore these because they are not written in the source. This matters for example when trying to replace types or values which are templated. The new test in TransformerTest.cpp in this commit demonstrates the problem. In existing matcher code, users can write `unless(isInTemplateInstantiation())` or `unless(isInstantiated())` (the user must know which to use). The point of the TK_IgnoreUnlessSpelledInSource mode is to allow the novice to avoid such details. This patch changes the IgnoreUnlessSpelledInSource mode to skip over implicit template instantiations. This patch does not change the TK_AsIs mode. Note: An obvious attempt at an alternative implementation would simply change the shouldVisitTemplateInstantiations() in ASTMatchFinder.cpp to return something conditional on the operational TraversalKind. That does not work because shouldVisitTemplateInstantiations() is called before a possible top-level traverse() matcher changes the operational TraversalKind. Reviewers: sammccall, aaron.ballman, gribozavr2, ymandel, klimek Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D80961
Diffstat (limited to 'clang/unittests/Tooling/TransformerTest.cpp')
-rw-r--r--clang/unittests/Tooling/TransformerTest.cpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp
index ff735cd..46f1d63 100644
--- a/clang/unittests/Tooling/TransformerTest.cpp
+++ b/clang/unittests/Tooling/TransformerTest.cpp
@@ -1064,6 +1064,70 @@ TEST_F(TransformerTest, ErrorOccurredMatchSkipped) {
EXPECT_EQ(ErrorCount, 0);
}
+TEST_F(TransformerTest, TemplateInstantiation) {
+
+ std::string NonTemplatesInput = R"cpp(
+struct S {
+ int m_i;
+};
+)cpp";
+ std::string NonTemplatesExpected = R"cpp(
+struct S {
+ safe_int m_i;
+};
+)cpp";
+
+ std::string TemplatesInput = R"cpp(
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ T m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+)cpp";
+
+ auto MatchedField = fieldDecl(hasType(asString("int"))).bind("theField");
+
+ // Changes the 'int' in 'S', but not the 'T' in 'TemplStruct':
+ testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedField),
+ changeTo(cat("safe_int ", name("theField")))),
+ NonTemplatesInput + TemplatesInput,
+ NonTemplatesExpected + TemplatesInput);
+
+ // In AsIs mode, template instantiations are modified, which is
+ // often not desired:
+
+ std::string IncorrectTemplatesExpected = R"cpp(
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ safe_int m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+)cpp";
+
+ // Changes the 'int' in 'S', and (incorrectly) the 'T' in 'TemplStruct':
+ testRule(makeRule(traverse(TK_AsIs, MatchedField),
+ changeTo(cat("safe_int ", name("theField")))),
+
+ NonTemplatesInput + TemplatesInput,
+ NonTemplatesExpected + IncorrectTemplatesExpected);
+}
+
// Transformation of macro source text when the change encompasses the entirety
// of the expanded text.
TEST_F(TransformerTest, SimpleMacro) {