Commit e36392b6 authored by Lukasz Anforowicz's avatar Lukasz Anforowicz Committed by Commit Bot

Preserving qualifiers and specifiers: |const|, |volatile|, |mutable|.

Bug: 1069567
Change-Id: Ifee67f9d96e320f6c4d0c09c1ec5a0cb2c8d0871
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2146058
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarBartek Nowierski <bartekn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760343}
parent b154d0ed
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "clang/Tooling/Tooling.h" #include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/LineIterator.h" #include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
...@@ -52,10 +53,14 @@ class FieldDeclRewriter : public MatchFinder::MatchCallback { ...@@ -52,10 +53,14 @@ class FieldDeclRewriter : public MatchFinder::MatchCallback {
void run(const MatchFinder::MatchResult& result) override { void run(const MatchFinder::MatchResult& result) override {
const clang::SourceManager& source_manager = *result.SourceManager; const clang::SourceManager& source_manager = *result.SourceManager;
const clang::FieldDecl* field_decl = const clang::FieldDecl* field_decl =
result.Nodes.getNodeAs<clang::FieldDecl>("fieldDecl"); result.Nodes.getNodeAs<clang::FieldDecl>("fieldDecl");
assert(field_decl && "matcher should bind 'fieldDecl'");
const clang::TypeSourceInfo* type_source_info = const clang::TypeSourceInfo* type_source_info =
field_decl->getTypeSourceInfo(); field_decl->getTypeSourceInfo();
assert(type_source_info && "assuming |type_source_info| is always present");
clang::QualType pointer_type = type_source_info->getType(); clang::QualType pointer_type = type_source_info->getType();
assert(type_source_info->getType()->isPointerType() && assert(type_source_info->getType()->isPointerType() &&
...@@ -78,27 +83,41 @@ class FieldDeclRewriter : public MatchFinder::MatchCallback { ...@@ -78,27 +83,41 @@ class FieldDeclRewriter : public MatchFinder::MatchCallback {
field_decl->getBeginLoc(), field_decl->getBeginLoc(),
field_decl->getLocation().getLocWithOffset(-1)); field_decl->getLocation().getLocWithOffset(-1));
// Calculate |replacement_text|.
std::string replacement_text = GenerateNewText(pointer_type);
if (field_decl->isMutable())
replacement_text.insert(0, "mutable ");
// Generate and add a replacement. // Generate and add a replacement.
replacements_->emplace_back( replacements_->emplace_back(
source_manager, clang::CharSourceRange::getCharRange(replacement_range), source_manager, clang::CharSourceRange::getCharRange(replacement_range),
GenerateNewText(pointer_type)); replacement_text);
} }
private: private:
std::string GenerateNewText(const clang::QualType& pointer_type) { std::string GenerateNewText(const clang::QualType& pointer_type) {
std::string result;
assert(pointer_type->isPointerType() && "caller must pass a pointer type!"); assert(pointer_type->isPointerType() && "caller must pass a pointer type!");
clang::QualType pointee_type = pointer_type->getPointeeType(); clang::QualType pointee_type = pointer_type->getPointeeType();
// Preserve qualifiers.
assert(!pointer_type.isRestrictQualified() &&
"|restrict| is a C-only qualifier and CheckedPtr<T> needs C++");
if (pointer_type.isConstQualified())
result += "const ";
if (pointer_type.isVolatileQualified())
result += "volatile ";
// Convert pointee type to string. // Convert pointee type to string.
clang::LangOptions lang_options; clang::LangOptions lang_options;
clang::PrintingPolicy printing_policy(lang_options); clang::PrintingPolicy printing_policy(lang_options);
printing_policy.SuppressTagKeyword = 1; // s/class Pointee/Pointee/ printing_policy.SuppressTagKeyword = 1; // s/class Pointee/Pointee/
std::string pointee_type_as_string = std::string pointee_type_as_string =
pointee_type.getAsString(printing_policy); pointee_type.getAsString(printing_policy);
result += llvm::formatv("CheckedPtr<{0}>", pointee_type_as_string);
// TODO(lukasza): Preserve qualifiers from |pointer_type| by generating return result;
// results from fresh AST (rather than via string concatenation).
return std::string("CheckedPtr<") + pointee_type_as_string + ">";
} }
std::vector<Replacement>* const replacements_; std::vector<Replacement>* const replacements_;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
class SomeClass; class SomeClass;
class MyClass { class MyClass {
MyClass() : ptr_field3_(nullptr), ptr_field6_(nullptr) {} MyClass() : ptr_field3_(nullptr), ptr_field7_(nullptr) {}
// Expected rewrite: CheckedPtr<const SomeClass> ptr_field1_; // Expected rewrite: CheckedPtr<const SomeClass> ptr_field1_;
CheckedPtr<const SomeClass> ptr_field1_; CheckedPtr<const SomeClass> ptr_field1_;
...@@ -14,23 +14,17 @@ class MyClass { ...@@ -14,23 +14,17 @@ class MyClass {
CheckedPtr<volatile SomeClass> ptr_field2_; CheckedPtr<volatile SomeClass> ptr_field2_;
// Expected rewrite: const CheckedPtr<SomeClass> ptr_field3_; // Expected rewrite: const CheckedPtr<SomeClass> ptr_field3_;
// const CheckedPtr<SomeClass> ptr_field3_;
// TODO(lukasza): Fix this by using |qualType.getAsString|.
// Currently the "outer" |const| is dropped.
CheckedPtr<SomeClass> ptr_field3_;
// Expected rewrite: mutable CheckedPtr<SomeClass> ptr_field4_; // Expected rewrite: mutable CheckedPtr<SomeClass> ptr_field4_;
// mutable CheckedPtr<SomeClass> ptr_field4_;
// TODO(lukasza): Fix this by looking at |field_decl->isMutable()|.
// Currently the |mutable| specifier is dropped.
CheckedPtr<SomeClass> ptr_field4_;
// Expected rewrite: CheckedPtr<const SomeClass> ptr_field5_; // Expected rewrite: CheckedPtr<const SomeClass> ptr_field5_;
CheckedPtr<const SomeClass> ptr_field5_; CheckedPtr<const SomeClass> ptr_field5_;
// Expected rewrite: volatile CheckedPtr<const SomeClass> ptr_field6_; // Expected rewrite: volatile CheckedPtr<const SomeClass> ptr_field6_;
// volatile CheckedPtr<const SomeClass> ptr_field6_;
// TODO(lukasza): Fix this by using |qualType.getAsString|.
// Currently the "outer" qualifiers (like |volatile| below) are dropped. // Expected rewrite: const CheckedPtr<const SomeClass> ptr_field7_;
CheckedPtr<const SomeClass> ptr_field6_; const CheckedPtr<const SomeClass> ptr_field7_;
}; };
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
class SomeClass; class SomeClass;
class MyClass { class MyClass {
MyClass() : ptr_field3_(nullptr), ptr_field6_(nullptr) {} MyClass() : ptr_field3_(nullptr), ptr_field7_(nullptr) {}
// Expected rewrite: CheckedPtr<const SomeClass> ptr_field1_; // Expected rewrite: CheckedPtr<const SomeClass> ptr_field1_;
const SomeClass* ptr_field1_; const SomeClass* ptr_field1_;
...@@ -14,23 +14,17 @@ class MyClass { ...@@ -14,23 +14,17 @@ class MyClass {
volatile SomeClass* ptr_field2_; volatile SomeClass* ptr_field2_;
// Expected rewrite: const CheckedPtr<SomeClass> ptr_field3_; // Expected rewrite: const CheckedPtr<SomeClass> ptr_field3_;
//
// TODO(lukasza): Fix this by using |qualType.getAsString|.
// Currently the "outer" |const| is dropped.
SomeClass* const ptr_field3_; SomeClass* const ptr_field3_;
// Expected rewrite: mutable CheckedPtr<SomeClass> ptr_field4_; // Expected rewrite: mutable CheckedPtr<SomeClass> ptr_field4_;
//
// TODO(lukasza): Fix this by looking at |field_decl->isMutable()|.
// Currently the |mutable| specifier is dropped.
mutable SomeClass* ptr_field4_; mutable SomeClass* ptr_field4_;
// Expected rewrite: CheckedPtr<const SomeClass> ptr_field5_; // Expected rewrite: CheckedPtr<const SomeClass> ptr_field5_;
SomeClass const* ptr_field5_; SomeClass const* ptr_field5_;
// Expected rewrite: volatile CheckedPtr<const SomeClass> ptr_field6_; // Expected rewrite: volatile CheckedPtr<const SomeClass> ptr_field6_;
//
// TODO(lukasza): Fix this by using |qualType.getAsString|.
// Currently the "outer" qualifiers (like |volatile| below) are dropped.
const SomeClass* volatile ptr_field6_; const SomeClass* volatile ptr_field6_;
// Expected rewrite: const CheckedPtr<const SomeClass> ptr_field7_;
const SomeClass* const ptr_field7_;
}; };
...@@ -26,4 +26,4 @@ struct MyStruct { ...@@ -26,4 +26,4 @@ struct MyStruct {
}; };
// [1] non-supported-type - type that won't ever be either // [1] non-supported-type - type that won't ever be either
// A) allocated by PartitionAllc or B) derived from CheckedPtrSupport. // A) allocated by PartitionAlloc or B) derived from CheckedPtrSupport.
...@@ -26,4 +26,4 @@ struct MyStruct { ...@@ -26,4 +26,4 @@ struct MyStruct {
}; };
// [1] non-supported-type - type that won't ever be either // [1] non-supported-type - type that won't ever be either
// A) allocated by PartitionAllc or B) derived from CheckedPtrSupport. // A) allocated by PartitionAlloc or B) derived from CheckedPtrSupport.
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