Skip to content

Commit

Permalink
Consider associated header desired includes
Browse files Browse the repository at this point in the history
The statement that IWYU doesn't change associated headers is clearly
wrong. When handling a main file, it should take into account what it
suggests to do with its associated headers, not what those headers look
like at the moment of the analysis.

It is assumed that the desired `#include`s of the associated headers
have been calculated before handling the main file, as it was already
assumed in the code.

This fixes include-what-you-use#1142.
  • Loading branch information
bolshakov-a committed Sep 4, 2024
1 parent 7e5c30a commit 0d8bfad
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 8 deletions.
16 changes: 8 additions & 8 deletions iwyu_output.cc
Original file line number Diff line number Diff line change
Expand Up @@ -828,13 +828,13 @@ bool DeclIsVisibleToUseInSameFile(const Decl* decl, const OneUse& use) {
// might be "calculate minimal-ish includes". :-) It populates
// each OneUse in uses with the best #include for that use.
// direct_includes: this file's direct includes only.
// associated_direct_includes: direct includes for 'associated'
// associated_desired_includes: desired includes for 'associated'
// files. For everything but foo.cc, this is empty; for foo.cc it's
// foo.h's includes and foo-inl.h's includes.
set<string> CalculateMinimalIncludes(
const string& use_quoted_include,
const set<string>& direct_includes,
const set<string>& associated_direct_includes,
const set<string>& associated_desired_includes,
vector<OneUse>* uses) {
set<string> desired_headers;

Expand Down Expand Up @@ -875,9 +875,8 @@ set<string> CalculateMinimalIncludes(
// Steps (2): Go through the needed private-includes that map to
// more than one public #include. Use the following priority order:
// - Ourselves.
// - An include in associated_direct_includes (those are includes
// that are not going away, since we can't change associated
// files).
// - An include in associated_desired_includes (those are includes
// that are not going away, since they should be calculated already).
// - Includes in direct_includes that are also already in
// desired_headers.
// - Includes in desired_headers.
Expand All @@ -900,7 +899,7 @@ set<string> CalculateMinimalIncludes(
for (const string& choice : public_headers) {
if (use.has_suggested_header())
break;
if (ContainsKey(associated_direct_includes, choice)) {
if (ContainsKey(associated_desired_includes, choice)) {
use.set_suggested_header(choice);
desired_headers.insert(use.suggested_header());
LogIncludeMapping("in associated header", use);
Expand Down Expand Up @@ -1697,8 +1696,9 @@ void IwyuFileInfo::CalculateIwyuViolations(vector<OneUse>* uses) {
Union(associated_direct_includes, direct_includes());

// (C2) + (C3) Find the minimal 'set cover' for all symbol uses.
const set<string>& associated_desired_includes = AssociatedDesiredIncludes();
const set<string> desired_set_cover = internal::CalculateMinimalIncludes(
quoted_file_, direct_includes(), associated_direct_includes, uses);
quoted_file_, direct_includes(), associated_desired_includes, uses);

// (C4) Remove .cc files from desired-includes unless they're in actual-inc.
for (const string& header_name : desired_set_cover) {
Expand All @@ -1714,7 +1714,7 @@ void IwyuFileInfo::CalculateIwyuViolations(vector<OneUse>* uses) {
// NOTE: this depends on our associated headers having had their
// iwyu analysis done before us.
set<string> effective_desired_includes = desired_includes();
InsertAllInto(AssociatedDesiredIncludes(), &effective_desired_includes);
InsertAllInto(associated_desired_includes, &effective_desired_includes);

// Now that we've figured out desired_includes, figure out iwyu violations.
for (OneUse& use : *uses) {
Expand Down
12 changes: 12 additions & 0 deletions tests/cxx/associated_include-d1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//===--- associated_include-d1.h - test input file for iwyu ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "tests/cxx/associated_include-i2.h" // IWYU pragma: export

class ClassFromD1 {};
10 changes: 10 additions & 0 deletions tests/cxx/associated_include-d2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//===--- associated_include-d2.h - test input file for iwyu ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "tests/cxx/associated_include-i3.h" // IWYU pragma: export
17 changes: 17 additions & 0 deletions tests/cxx/associated_include-i2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//===--- associated_include-i2.h - test input file for iwyu ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef INCLUDE_WHAT_YOU_USE_TESTS_CXX_ASSOCIATED_INCLUDE_I2_H_
#define INCLUDE_WHAT_YOU_USE_TESTS_CXX_ASSOCIATED_INCLUDE_I2_H_

#include "tests/cxx/associated_include-i3.h"

class ClassExportedThroughD1 {};

#endif // INCLUDE_WHAT_YOU_USE_TESTS_CXX_ASSOCIATED_INCLUDE_I2_H_
15 changes: 15 additions & 0 deletions tests/cxx/associated_include-i3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//===--- associated_include-i3.h - test input file for iwyu ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef INCLUDE_WHAT_YOU_USE_TESTS_CXX_ASSOCIATED_INCLUDE_I3_H_
#define INCLUDE_WHAT_YOU_USE_TESTS_CXX_ASSOCIATED_INCLUDE_I3_H_

class ClassFromI3 {};

#endif // INCLUDE_WHAT_YOU_USE_TESTS_CXX_ASSOCIATED_INCLUDE_I3_H_
14 changes: 14 additions & 0 deletions tests/cxx/associated_include.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,34 @@
// 'associated' .h file, we don't try to add it to the .cc file.

#include "tests/cxx/associated_include.h"
#include "tests/cxx/associated_include-d1.h"
#include "tests/cxx/associated_include-d2.h"

IndirectClass ic;
AssociatedIncludeClass aic;

// IWYU should not consider "*-i2.h" as being present in the associated header
// (because it should be removed from that), hence the following two types
// should be attributed to "*-d1.h".
ClassExportedThroughD1 aic2;
ClassFromD1 aic3;

// Despite "*-d2.h" reexports ClassFromI3, IWYU should suggest to remove it
// because it should also suggest to add "*-i3.h" in the associated header.
// IWYU: ClassFromI3 is...*associated_include-i3.h
ClassFromI3 cfi3;

/**** IWYU_SUMMARY
tests/cxx/associated_include.cc should add these lines:
#include "tests/cxx/indirect.h"
tests/cxx/associated_include.cc should remove these lines:
- #include "tests/cxx/associated_include-d2.h" // lines XX-XX
The full include-list for tests/cxx/associated_include.cc:
#include "tests/cxx/associated_include.h"
#include "tests/cxx/associated_include-d1.h" // for ClassExportedThroughD1, ClassFromD1
#include "tests/cxx/indirect.h" // for IndirectClass
***** IWYU_SUMMARY */
6 changes: 6 additions & 0 deletions tests/cxx/associated_include.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,25 @@

#include "tests/cxx/indirect.h"
#include "tests/cxx/associated_include-i1.h"
#include "tests/cxx/associated_include-i2.h"

namespace hfile {
AssociatedIncludeClass aic;
// IWYU: ClassFromI3 is...*associated_include-i3.h
ClassFromI3 cfi3;
}

/**** IWYU_SUMMARY
tests/cxx/associated_include.h should add these lines:
#include "tests/cxx/associated_include-i3.h"
tests/cxx/associated_include.h should remove these lines:
- #include "tests/cxx/associated_include-i2.h" // lines XX-XX
- #include "tests/cxx/indirect.h" // lines XX-XX
The full include-list for tests/cxx/associated_include.h:
#include "tests/cxx/associated_include-i1.h" // for AssociatedIncludeClass
#include "tests/cxx/associated_include-i3.h" // for ClassFromI3
***** IWYU_SUMMARY */

0 comments on commit 0d8bfad

Please sign in to comment.