summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBolshakov <bolsh.andrey@yandex.ru>2022-06-26 23:54:52 +0300
committerKim Gräsman <kim.grasman@gmail.com>2022-07-16 18:30:23 +0200
commitb46a96e5a646fc684c8eed95eb63f4e6edc9d679 (patch)
tree105f635ca667a6f7e46221038ef724ba0abc36b2
parentbab51b55ab092cb74ea62f14042cf66232ccfb40 (diff)
Fix autocast to reference
CastExpr for constructor conversion is absent in the AST in such a case
-rw-r--r--iwyu.cc33
-rw-r--r--tests/cxx/iwyu_stricter_than_cpp-d2.h4
2 files changed, 22 insertions, 15 deletions
diff --git a/iwyu.cc b/iwyu.cc
index e3604e0..478bcfc 100644
--- a/iwyu.cc
+++ b/iwyu.cc
@@ -2002,19 +2002,9 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
// Need the full to-type so we can call its constructor.
case clang::CK_ConstructorConversion:
- // 'Autocast' -- calling a one-arg, non-explicit constructor
- // -- is a special case when it's done for a function call.
- // iwyu requires the function-writer to provide the #include
- // for the casted-to type, just so we don't have to require it
- // here. *However*, the function-author can override this
- // iwyu requirement, in which case we're responsible for the
- // casted-to type. See IwyuBaseASTVisitor::VisitFunctionDecl.
- if (!current_ast_node()->template HasAncestorOfType<CallExpr>() ||
- ContainsKey(
- GetCallerResponsibleTypesForAutocast(current_ast_node()),
- RemovePointersAndReferences(to_type))) {
+ // 'Autocast' in function calls is handled in VisitCXXConstructExpr.
+ if (!current_ast_node()->template HasAncestorOfType<CallExpr>())
required_full_types.push_back(to_type);
- }
break;
// Need the full from-type so we can call its 'operator <totype>()'.
case clang::CK_UserDefinedConversion:
@@ -2286,6 +2276,25 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
if (CanIgnoreCurrentASTNode()) return true;
ReportIfReferenceVararg(expr->getArgs(), expr->getNumArgs(),
expr->getConstructor());
+
+ // 'Autocast' -- calling a one-arg, non-explicit constructor
+ // -- is a special case when it's done for a function call.
+ // iwyu requires the function-writer to provide the #include
+ // for the casted-to type, just so we don't have to require it
+ // here. *However*, the function-author can override this
+ // iwyu requirement, in which case we're responsible for the
+ // casted-to type. See IwyuBaseASTVisitor::VisitFunctionDecl.
+ // Explicitly written CXXTemporaryObjectExpr are ignored here.
+ if (expr->getStmtClass() == Stmt::StmtClass::CXXConstructExprClass) {
+ const Type* type = expr->getType().getTypePtr();
+ if (current_ast_node()->template HasAncestorOfType<CallExpr>() &&
+ ContainsKey(GetCallerResponsibleTypesForAutocast(current_ast_node()),
+ RemoveReferenceAsWritten(type))) {
+ if (!CanIgnoreType(type))
+ ReportTypeUse(CurrentLoc(), type);
+ }
+ }
+
return true;
}
diff --git a/tests/cxx/iwyu_stricter_than_cpp-d2.h b/tests/cxx/iwyu_stricter_than_cpp-d2.h
index f1b101a..4089d95 100644
--- a/tests/cxx/iwyu_stricter_than_cpp-d2.h
+++ b/tests/cxx/iwyu_stricter_than_cpp-d2.h
@@ -21,9 +21,7 @@ void CallTwiceDeclaredFunction() {
// IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h
TwiceDeclaredFunction(1);
- // This *should* be exactly the same, but doesn't seem to be:
- // clang leaves out the constructor-conversion AST node.
- // TODO(csilvers): IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h
+ // IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h
TwiceDeclaredRefFunction(1);
}