diff --git a/iwyu.cc b/iwyu.cc index 3d42646..ea2ec49 100644 --- a/iwyu.cc +++ b/iwyu.cc @@ -1484,6 +1484,8 @@ class IwyuBaseAstVisitor : public BaseAstVisitor { GetFileEntry(call_expr), GetFileEntry(*fn_redecl))) { continue; } + if (fn_redecl->isThisDeclarationADefinition() && !IsInHeader(*fn_redecl)) + continue; for (set::iterator it = retval.begin(); it != retval.end(); ) { if (!CodeAuthorWantsJustAForwardDeclare(*it, GetLocation(*fn_redecl))) { @@ -1768,6 +1770,11 @@ class IwyuBaseAstVisitor : public BaseAstVisitor { while ((redecl = redecl->getPreviousDecl())) ReportDeclUse(CurrentLoc(), redecl); } + if (!IsInHeader(decl)) { + // No point in author-intent analysis of function definitions + // in source files. + return true; + } } else { // Make all our types forward-declarable... current_ast_node()->set_in_forward_declare_context(true); diff --git a/iwyu_location_util.cc b/iwyu_location_util.cc index 31374ad..4036156 100644 --- a/iwyu_location_util.cc +++ b/iwyu_location_util.cc @@ -10,6 +10,7 @@ #include "iwyu_location_util.h" #include "iwyu_ast_util.h" +#include "iwyu_port.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -28,6 +29,7 @@ using clang::CXXMethodDecl; using clang::CXXOperatorCallExpr; using clang::ClassTemplateSpecializationDecl; using clang::ConditionalOperator; +using clang::FileEntry; using clang::FunctionDecl; using clang::MemberExpr; using clang::SourceLocation; @@ -170,4 +172,10 @@ bool IsInScratchSpace(SourceLocation loc) { return StartsWith(PrintableLoc(GetSpellingLoc(loc)), ""); } +bool IsInHeader(const clang::Decl* decl) { + const FileEntry* containing_file = GetFileEntry(decl); + CHECK_(containing_file); + return !GlobalSourceManager()->isMainFile(*containing_file); +} + } // namespace include_what_you_use diff --git a/iwyu_location_util.h b/iwyu_location_util.h index 6f8cf81..a875ed8 100644 --- a/iwyu_location_util.h +++ b/iwyu_location_util.h @@ -228,6 +228,9 @@ inline bool IsBeforeInSameFile(const T& a, const U& b) { return IsBeforeInTranslationUnit(a, b); } +// Returns true if the given declaration is located in a header file. +bool IsInHeader(const clang::Decl*); + } // namespace include_what_you_use #endif // INCLUDE_WHAT_YOU_USE_IWYU_LOCATION_UTIL_H_ diff --git a/tests/cxx/implicit_ctor-d1.h b/tests/cxx/implicit_ctor-d1.h index aa9c4cf..a5aa209 100644 --- a/tests/cxx/implicit_ctor-d1.h +++ b/tests/cxx/implicit_ctor-d1.h @@ -22,6 +22,14 @@ int ImplicitCtorFn(IndirectWithImplicitCtor); // IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h.*for autocast int ImplicitCtorRefFn(const IndirectWithImplicitCtor&); +// Reporting types for "autocast" for header-defined functions still makes sense +// as opposed to function definitions in source files. +// IWYU: IndirectWithImplicitCtor needs a declaration +// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h.*for autocast +inline int InlineImplicitCtorRefFn(const IndirectWithImplicitCtor&) { + return 1; +} + // Test parameter type uses that do not require special handling for "autocast". int NoAutocastFn( // A subtle c++ point: forward-declaring is ok for nonconst, because diff --git a/tests/cxx/implicit_ctor.cc b/tests/cxx/implicit_ctor.cc index bb5341b..2c088a0 100644 --- a/tests/cxx/implicit_ctor.cc +++ b/tests/cxx/implicit_ctor.cc @@ -22,6 +22,18 @@ #include "tests/cxx/implicit_ctor-d1.h" +// No reporting types for "autocast" for .cpp-file-local functions... +// IWYU: IndirectWithImplicitCtor needs a declaration +static int LocalFn(const IndirectWithImplicitCtor&) { + return 1; +} + +// ... or for .cpp-file-definitions of functions declared in a header. +// IWYU: IndirectWithImplicitCtor needs a declaration +int ImplicitCtorRefFn(const IndirectWithImplicitCtor&) { + return 2; +} + // We don't need IndirectWithImplicitCtor even though we must convert to it. int a = ImplicitCtorFn(1); int b = ImplicitCtorRefFn(2); @@ -32,6 +44,13 @@ int c = ImplicitCtorFn(IndirectWithImplicitCtor(3)); // IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h int d = ImplicitCtorRefFn(IndirectWithImplicitCtor(4)); +// LocalFn doesn't provide IndirectWithImplicitCtor type info. +// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h +int e = LocalFn(5); +// InlineImplicitCtorRefFn should provide parameter type info, +// hence no reporting. +int f = InlineImplicitCtorRefFn(6); + // Make sure we are responsible for the conversion when it's not for a // function call. // IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h @@ -48,7 +67,7 @@ tests/cxx/implicit_ctor.cc should add these lines: tests/cxx/implicit_ctor.cc should remove these lines: The full include-list for tests/cxx/implicit_ctor.cc: -#include "tests/cxx/implicit_ctor-d1.h" // for ImplicitCtorFn, ImplicitCtorRefFn +#include "tests/cxx/implicit_ctor-d1.h" // for ImplicitCtorFn, ImplicitCtorRefFn, InlineImplicitCtorRefFn #include "tests/cxx/implicit_ctor-i2.h" // for IndirectWithImplicitCtor ***** IWYU_SUMMARY */