diff options
author | Kim Grasman <kim.grasman@gmail.com> | 2019-03-09 17:15:38 +0100 |
---|---|---|
committer | Kim Gräsman <kim.grasman@gmail.com> | 2019-03-14 17:00:29 +0100 |
commit | 113161781b8a284631b1811aba826269cd9141b0 (patch) | |
tree | b4f2dfed1fd4fa143677cdacc3584d60ad7678e4 | |
parent | 452aeefb6e708f01bc8636bbd96b7a83b0df8811 (diff) |
Generalize how VisitCastExpr tracks required types
Instead of two booleans, keep a vector of Type pointers for which the
complete type is required.
This will make it easier to handle conversion functions, coming up in
the next commit.
-rw-r--r-- | iwyu.cc | 36 |
1 files changed, 18 insertions, 18 deletions
@@ -2006,13 +2006,11 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { // compiler a fighting chance of generating correct code. bool VisitCastExpr(clang::CastExpr* expr) { if (CanIgnoreCurrentASTNode()) return true; - const Type* const from_type = GetTypeOf(expr->getSubExprAsWritten()); - const Type* const to_type = GetTypeOf(expr); - const Type* const deref_from_type = RemovePointersAndReferences(from_type); - const Type* const deref_to_type = RemovePointersAndReferences(to_type); + const Type* from_type = GetTypeOf(expr->getSubExprAsWritten()); + const Type* to_type = GetTypeOf(expr); + + std::vector<const Type*> required_full_types; - bool need_full_deref_from_type = false; - bool need_full_deref_to_type = false; // The list of kinds: http://clang.llvm.org/doxygen/namespaceclang.html switch (expr->getCastKind()) { // This cast still isn't handled directly. @@ -2096,43 +2094,45 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { if (!current_ast_node()->template HasAncestorOfType<CallExpr>() || ContainsKey( GetCallerResponsibleTypesForAutocast(current_ast_node()), - deref_to_type)) { - need_full_deref_to_type = true; + RemovePointersAndReferences(to_type))) { + required_full_types.push_back(to_type); } break; // Need the full from-type so we can call its 'operator <totype>()'. case clang::CK_UserDefinedConversion: - need_full_deref_from_type = true; + required_full_types.push_back(from_type); break; // Kinds that cast up or down an inheritance hierarchy. case clang::CK_BaseToDerived: case clang::CK_BaseToDerivedMemberPointer: // Just 'to' type is enough: full type for derived gets base type too. - need_full_deref_to_type = true; + required_full_types.push_back(to_type); break; case clang::CK_DerivedToBase: case clang::CK_UncheckedDerivedToBase: case clang::CK_DerivedToBaseMemberPointer: - need_full_deref_from_type = true; + required_full_types.push_back(from_type); break; case clang::CK_Dynamic: // Usually dynamic casting is a base-to-derived cast, but it is // possible to dynamic-cast between siblings, in which case we // need both types. - need_full_deref_from_type = true; - need_full_deref_to_type = true; + required_full_types.push_back(from_type); + required_full_types.push_back(to_type); break; } // TODO(csilvers): test if we correctly say we use FooPtr for // typedef Foo* FooPtr; ... static_cast<FooPtr>(...) ... - if (need_full_deref_from_type && !CanIgnoreType(deref_from_type)) { - ReportTypeUse(CurrentLoc(), deref_from_type); - } - if (need_full_deref_to_type && !CanIgnoreType(deref_to_type)) { - ReportTypeUse(CurrentLoc(), deref_to_type); + for (const Type* type : required_full_types) { + const Type* deref_type = RemovePointersAndReferences(type); + if (CanIgnoreType(deref_type)) + continue; + + ReportTypeUse(CurrentLoc(), deref_type); } + return true; } |