Avoid 'autocast' reporting for function definition
A function may just transmit passed-by-reference parameter somewhere. Requirement to explicitly write forward declaration in the same file (.cpp-file) to avoid '#include' suggestion is impractical when that type is already fwd-declared in the corresponding header. 'Autocast' may still make sense for header-defined functions, due to unlimited number of possible callers, so analysis of those fuctions is kept. Both function declaration site handling and call site handling are changed.
This commit is contained in:
parent
8b3da1112e
commit
862812049a
7
iwyu.cc
7
iwyu.cc
|
@ -1484,6 +1484,8 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
|
||||||
GetFileEntry(call_expr), GetFileEntry(*fn_redecl))) {
|
GetFileEntry(call_expr), GetFileEntry(*fn_redecl))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (fn_redecl->isThisDeclarationADefinition() && !IsInHeader(*fn_redecl))
|
||||||
|
continue;
|
||||||
for (set<const Type*>::iterator it = retval.begin();
|
for (set<const Type*>::iterator it = retval.begin();
|
||||||
it != retval.end(); ) {
|
it != retval.end(); ) {
|
||||||
if (!CodeAuthorWantsJustAForwardDeclare(*it, GetLocation(*fn_redecl))) {
|
if (!CodeAuthorWantsJustAForwardDeclare(*it, GetLocation(*fn_redecl))) {
|
||||||
|
@ -1768,6 +1770,11 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
|
||||||
while ((redecl = redecl->getPreviousDecl()))
|
while ((redecl = redecl->getPreviousDecl()))
|
||||||
ReportDeclUse(CurrentLoc(), redecl);
|
ReportDeclUse(CurrentLoc(), redecl);
|
||||||
}
|
}
|
||||||
|
if (!IsInHeader(decl)) {
|
||||||
|
// No point in author-intent analysis of function definitions
|
||||||
|
// in source files.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Make all our types forward-declarable...
|
// Make all our types forward-declarable...
|
||||||
current_ast_node()->set_in_forward_declare_context(true);
|
current_ast_node()->set_in_forward_declare_context(true);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "iwyu_location_util.h"
|
#include "iwyu_location_util.h"
|
||||||
|
|
||||||
#include "iwyu_ast_util.h"
|
#include "iwyu_ast_util.h"
|
||||||
|
#include "iwyu_port.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/DeclBase.h"
|
#include "clang/AST/DeclBase.h"
|
||||||
#include "clang/AST/DeclCXX.h"
|
#include "clang/AST/DeclCXX.h"
|
||||||
|
@ -28,6 +29,7 @@ using clang::CXXMethodDecl;
|
||||||
using clang::CXXOperatorCallExpr;
|
using clang::CXXOperatorCallExpr;
|
||||||
using clang::ClassTemplateSpecializationDecl;
|
using clang::ClassTemplateSpecializationDecl;
|
||||||
using clang::ConditionalOperator;
|
using clang::ConditionalOperator;
|
||||||
|
using clang::FileEntry;
|
||||||
using clang::FunctionDecl;
|
using clang::FunctionDecl;
|
||||||
using clang::MemberExpr;
|
using clang::MemberExpr;
|
||||||
using clang::SourceLocation;
|
using clang::SourceLocation;
|
||||||
|
@ -170,4 +172,10 @@ bool IsInScratchSpace(SourceLocation loc) {
|
||||||
return StartsWith(PrintableLoc(GetSpellingLoc(loc)), "<scratch space>");
|
return StartsWith(PrintableLoc(GetSpellingLoc(loc)), "<scratch space>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
} // namespace include_what_you_use
|
||||||
|
|
|
@ -228,6 +228,9 @@ inline bool IsBeforeInSameFile(const T& a, const U& b) {
|
||||||
return IsBeforeInTranslationUnit(a, 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
|
} // namespace include_what_you_use
|
||||||
|
|
||||||
#endif // INCLUDE_WHAT_YOU_USE_IWYU_LOCATION_UTIL_H_
|
#endif // INCLUDE_WHAT_YOU_USE_IWYU_LOCATION_UTIL_H_
|
||||||
|
|
|
@ -22,6 +22,14 @@ int ImplicitCtorFn(IndirectWithImplicitCtor);
|
||||||
// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h.*for autocast
|
// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h.*for autocast
|
||||||
int ImplicitCtorRefFn(const IndirectWithImplicitCtor&);
|
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".
|
// Test parameter type uses that do not require special handling for "autocast".
|
||||||
int NoAutocastFn(
|
int NoAutocastFn(
|
||||||
// A subtle c++ point: forward-declaring is ok for nonconst, because
|
// A subtle c++ point: forward-declaring is ok for nonconst, because
|
||||||
|
|
|
@ -22,6 +22,18 @@
|
||||||
|
|
||||||
#include "tests/cxx/implicit_ctor-d1.h"
|
#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.
|
// We don't need IndirectWithImplicitCtor even though we must convert to it.
|
||||||
int a = ImplicitCtorFn(1);
|
int a = ImplicitCtorFn(1);
|
||||||
int b = ImplicitCtorRefFn(2);
|
int b = ImplicitCtorRefFn(2);
|
||||||
|
@ -32,6 +44,13 @@ int c = ImplicitCtorFn(IndirectWithImplicitCtor(3));
|
||||||
// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h
|
// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h
|
||||||
int d = ImplicitCtorRefFn(IndirectWithImplicitCtor(4));
|
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
|
// Make sure we are responsible for the conversion when it's not for a
|
||||||
// function call.
|
// function call.
|
||||||
// IWYU: IndirectWithImplicitCtor is...*implicit_ctor-i2.h
|
// 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:
|
tests/cxx/implicit_ctor.cc should remove these lines:
|
||||||
|
|
||||||
The full include-list for tests/cxx/implicit_ctor.cc:
|
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
|
#include "tests/cxx/implicit_ctor-i2.h" // for IndirectWithImplicitCtor
|
||||||
|
|
||||||
***** IWYU_SUMMARY */
|
***** IWYU_SUMMARY */
|
||||||
|
|
Loading…
Reference in New Issue