Commit 63f4f75a authored by Lukasz Anforowicz's avatar Lukasz Anforowicz Committed by Commit Bot

Append |.get()| to: auto* var_ptr = my_struct.ptr_field;

Bug: 1069567
Change-Id: Ie1b48c0a6ee3ed66213b59827dc77ef7d57d9a45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2156069
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774879}
parent b1348513
...@@ -529,6 +529,20 @@ int main(int argc, const char* argv[]) { ...@@ -529,6 +529,20 @@ int main(int argc, const char* argv[]) {
match_finder.addMatcher(affected_ternary_operator_arg_matcher, match_finder.addMatcher(affected_ternary_operator_arg_matcher,
&affected_expr_rewriter); &affected_expr_rewriter);
// |auto| type declarations =========
// Given
// struct S { int* y; };
// void foo(const S& s) {
// auto* p = s.y;
// }
// binds the |s.y| expr if it matches the |affected_expr_matcher| above.
auto auto_var_decl_matcher = declStmt(forEach(varDecl(
allOf(hasType(pointerType(pointee(autoType()))),
hasInitializer(anyOf(
affected_implicit_expr_matcher,
initListExpr(hasInit(0, affected_implicit_expr_matcher))))))));
match_finder.addMatcher(auto_var_decl_matcher, &affected_expr_rewriter);
// Prepare and run the tool. // Prepare and run the tool.
std::unique_ptr<clang::tooling::FrontendActionFactory> factory = std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
clang::tooling::newFrontendActionFactory(&match_finder, clang::tooling::newFrontendActionFactory(&match_finder,
......
...@@ -13,8 +13,79 @@ struct MyStruct { ...@@ -13,8 +13,79 @@ struct MyStruct {
CheckedPtr<SomeClass> ptr; CheckedPtr<SomeClass> ptr;
CheckedPtr<SomeClass> ptr2; CheckedPtr<SomeClass> ptr2;
CheckedPtr<const SomeClass> const_ptr; CheckedPtr<const SomeClass> const_ptr;
int (*func_ptr_field)();
}; };
namespace auto_tests {
MyStruct* GetMyStruct() {
return nullptr;
}
SomeClass* GetSomeClass() {
return nullptr;
}
SomeClass* ConvertSomeClassToSomeClass(SomeClass* some_class) {
return some_class;
}
void foo() {
MyStruct my_struct;
// After the rewrite |my_struct.ptr_field| is no longer a pointer,
// so |auto*| won't work. We fix this up, by appending |.get()|.
// Expected rewrite: auto* ptr_var = my_struct.ptr.get();
auto* ptr_var = my_struct.ptr.get();
// Tests for other kinds of initialization.
// Expected rewrite: |.get()| should be appended in both cases below.
auto* init_test1(my_struct.ptr.get());
auto* init_test2{my_struct.ptr.get()};
// Test for handling of the |const| qualifier.
// Expected rewrite: const auto* ptr_var = my_struct.ptr.get();
const auto* const_ptr_var = my_struct.ptr.get();
// More complicated initialization expression, but the |ptr_field| struct
// member dereference is still the top/last expression here.
// Expected rewrite: ...->ptr.get()
auto* complicated_var = GetMyStruct()->ptr.get();
// The test below covers:
// 1. Two variables with single |auto|,
// 2. Tricky placement of |*| (next to the variable name).
// Expected rewrite: ...ptr.get()... (twice in the 2nd example).
auto *ptr_var1 = my_struct.ptr.get(), *ptr_var2 = GetSomeClass();
auto *ptr_var3 = my_struct.ptr.get(), *ptr_var4 = my_struct.ptr.get();
auto *ptr_var5 = GetSomeClass(), *ptr_var6 = my_struct.ptr.get();
// Test for the case where
// 1. The resulting type is the same as in the |ptr_var| and |complicated_var|
// examples
// 2. Deep in the initialization expression there is a member dereference
// of |ptr_field|
// but
// 3. The final/top-level initialization expression doesn't dereference
// |ptr_field|.
// No rewrite expected.
auto* not_affected_field_var = ConvertSomeClassToSomeClass(my_struct.ptr);
// Test for pointer |auto| assigned from non-CheckedPtr-elligible field.
// No rewrite expected.
auto* func_ptr_var = my_struct.func_ptr_field;
// Test for non-pointer |auto| assigned from CheckedPtr-elligible field.
// No rewrite expected.
auto non_pointer_auto_var = my_struct.ptr;
// Test for non-auto pointer.
// No rewrite expected.
SomeClass* non_auto_ptr_var = my_struct.ptr;
}
} // namespace auto_tests
namespace printf_tests { namespace printf_tests {
int ConvertSomeClassToInt(SomeClass* some_class) { int ConvertSomeClassToInt(SomeClass* some_class) {
......
...@@ -11,8 +11,79 @@ struct MyStruct { ...@@ -11,8 +11,79 @@ struct MyStruct {
SomeClass* ptr; SomeClass* ptr;
SomeClass* ptr2; SomeClass* ptr2;
const SomeClass* const_ptr; const SomeClass* const_ptr;
int (*func_ptr_field)();
}; };
namespace auto_tests {
MyStruct* GetMyStruct() {
return nullptr;
}
SomeClass* GetSomeClass() {
return nullptr;
}
SomeClass* ConvertSomeClassToSomeClass(SomeClass* some_class) {
return some_class;
}
void foo() {
MyStruct my_struct;
// After the rewrite |my_struct.ptr_field| is no longer a pointer,
// so |auto*| won't work. We fix this up, by appending |.get()|.
// Expected rewrite: auto* ptr_var = my_struct.ptr.get();
auto* ptr_var = my_struct.ptr;
// Tests for other kinds of initialization.
// Expected rewrite: |.get()| should be appended in both cases below.
auto* init_test1(my_struct.ptr);
auto* init_test2{my_struct.ptr};
// Test for handling of the |const| qualifier.
// Expected rewrite: const auto* ptr_var = my_struct.ptr.get();
const auto* const_ptr_var = my_struct.ptr;
// More complicated initialization expression, but the |ptr_field| struct
// member dereference is still the top/last expression here.
// Expected rewrite: ...->ptr.get()
auto* complicated_var = GetMyStruct()->ptr;
// The test below covers:
// 1. Two variables with single |auto|,
// 2. Tricky placement of |*| (next to the variable name).
// Expected rewrite: ...ptr.get()... (twice in the 2nd example).
auto *ptr_var1 = my_struct.ptr, *ptr_var2 = GetSomeClass();
auto *ptr_var3 = my_struct.ptr, *ptr_var4 = my_struct.ptr;
auto *ptr_var5 = GetSomeClass(), *ptr_var6 = my_struct.ptr;
// Test for the case where
// 1. The resulting type is the same as in the |ptr_var| and |complicated_var|
// examples
// 2. Deep in the initialization expression there is a member dereference
// of |ptr_field|
// but
// 3. The final/top-level initialization expression doesn't dereference
// |ptr_field|.
// No rewrite expected.
auto* not_affected_field_var = ConvertSomeClassToSomeClass(my_struct.ptr);
// Test for pointer |auto| assigned from non-CheckedPtr-elligible field.
// No rewrite expected.
auto* func_ptr_var = my_struct.func_ptr_field;
// Test for non-pointer |auto| assigned from CheckedPtr-elligible field.
// No rewrite expected.
auto non_pointer_auto_var = my_struct.ptr;
// Test for non-auto pointer.
// No rewrite expected.
SomeClass* non_auto_ptr_var = my_struct.ptr;
}
} // namespace auto_tests
namespace printf_tests { namespace printf_tests {
int ConvertSomeClassToInt(SomeClass* some_class) { int ConvertSomeClassToInt(SomeClass* some_class) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment