Skip to content

Commit d7f1b25

Browse files
[IncludeTree] Support -frewrite-includes with include-tree
Add necessary PPCallbacks for include directives when the input file is include tree so -frewrite-includes can generate the correct output. rdar://125719747
1 parent 01231f5 commit d7f1b25

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

clang/lib/Lex/PPDirectives.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,13 +1995,41 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
19951995
auto Include = CActions->handleIncludeDirective(
19961996
*this, IncludePos, CurLexer->getSourceLocation());
19971997

1998+
auto InclusionCallback = [&](OptionalFileEntryRef FileRef,
1999+
const Module *SuggestedModule) {
2000+
if (!Callbacks || HashLoc.isInvalid())
2001+
return;
2002+
2003+
SmallString<128> FilenameBuffer;
2004+
StringRef Filename = getSpelling(FilenameTok, FilenameBuffer);
2005+
SourceLocation CharEnd = FilenameTok.getEndLoc();
2006+
CharSourceRange FilenameRange =
2007+
CharSourceRange::getCharRange(FilenameTok.getLocation(), CharEnd);
2008+
bool isAngled =
2009+
GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
2010+
SrcMgr::CharacteristicKind FileCharacter =
2011+
SourceMgr.getFileCharacteristic(FilenameTok.getLocation());
2012+
if (SuggestedModule)
2013+
Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
2014+
FilenameRange, OptionalFileEntryRef(),
2015+
/*SearchPath=*/"", /*RelativePath=*/"",
2016+
SuggestedModule,
2017+
/*ModuleImported=*/true, FileCharacter);
2018+
else
2019+
Callbacks->InclusionDirective(
2020+
HashLoc, IncludeTok, Filename, isAngled, FilenameRange, FileRef,
2021+
/*SearchPath=*/"", /*RelativePath=*/"", /*SuggestedModule=*/nullptr,
2022+
/*ModuleImported=*/false, FileCharacter);
2023+
};
2024+
19982025
auto HandleIncludeFile = [&](const PPCachedActions::IncludeFile *File) {
19992026
const FileEntry *FE = SourceMgr.getFileEntryForID(File->FID);
20002027
bool IsImport =
20012028
IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import;
20022029
if (FE && IsImport) {
20032030
HeaderInfo.getFileInfo(FE).isImport = true;
20042031
}
2032+
InclusionCallback(SourceMgr.getFileEntryRefForID(File->FID), nullptr);
20052033
EnterSourceFile(File->FID, nullptr, FilenameTok.getLocation(),
20062034
/*IsFirstIncludeOfFile*/ true);
20072035

@@ -2068,6 +2096,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
20682096
return;
20692097
}
20702098

2099+
InclusionCallback({}, Imported);
20712100
makeModuleVisible(Imported, EndLoc);
20722101
if (IncludeTok.getIdentifierInfo()->getPPKeywordID() !=
20732102
tok::pp___include_macros)

clang/test/CAS/rewrite-includes.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
4+
// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
5+
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree-full -cas-path %t/cas > %t/deps.json
6+
7+
// RUN: %deps-to-rsp %t/deps.json --module-name dummy > %t/dummy.rsp
8+
// RUN: %deps-to-rsp %t/deps.json --module-name Mod > %t/mod.rsp
9+
// RUN: %deps-to-rsp %t/deps.json --module-name Spurious > %t/spurious.rsp
10+
// RUN: %deps-to-rsp %t/deps.json --tu-index 0 > %t/tu.rsp
11+
// RUN: %clang @%t/dummy.rsp
12+
// RUN: %clang @%t/mod.rsp
13+
// RUN: %clang @%t/spurious.rsp
14+
// RUN: %clang @%t/tu.rsp -frewrite-includes -w -E -o - | FileCheck %s
15+
16+
// CHECK: int bar();{{$}}
17+
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
18+
// CHECK-NEXT: #include "test.h"{{$}}
19+
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
20+
// CHECK-NEXT: # 2 "{{.*[/\\]}}main.c"{{$}}
21+
// CHECK-NEXT: # 1 "{{.*[/\\]}}test.h" 1{{$}}
22+
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
23+
// CHECK-NEXT: #include "dummy.h"{{$}}
24+
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
25+
// CHECK-NEXT: # 1 "{{.*[/\\]}}test.h"{{$}}
26+
// CHECK-NEXT: #pragma clang module import dummy /* clang -frewrite-includes: implicit import */{{$}}
27+
// CHECK-NEXT: # 2 "{{.*[/\\]}}test.h"{{$}}
28+
// CHECK-NEXT: # 3 "{{.*[/\\]}}main.c" 2{{$}}
29+
// CHECK-NEXT: int foo();{{$}}
30+
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
31+
// CHECK-NEXT: #include "dummy.h"{{$}}
32+
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
33+
// CHECK-NEXT: # 4 "{{.*[/\\]}}main.c"{{$}}
34+
// CHECK-NEXT: #pragma clang module import dummy /* clang -frewrite-includes: implicit import */{{$}}
35+
// CHECK-NEXT: # 5 "{{.*[/\\]}}main.c"{{$}}
36+
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
37+
// CHECK-NEXT: #include <Spurious/Missing.h>{{$}}
38+
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
39+
// CHECK-NEXT: # 5 "{{.*[/\\]}}main.c"{{$}}
40+
// CHECK-NEXT: # 1 "{{.*[/\\]}}Missing.h" 1{{$}}
41+
// CHECK-NEXT: /* empty */
42+
// CHECK-NEXT: # 6 "{{.*[/\\]}}main.c" 2{{$}}
43+
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
44+
// CHECK-NEXT: #include <Mod.h>{{$}}
45+
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
46+
// CHECK-NEXT: # 6 "{{.*[/\\]}}main.c"{{$}}
47+
// CHECK-NEXT: #pragma clang module import Mod /* clang -frewrite-includes: implicit import */{{$}}
48+
// CHECK-NEXT: # 7 "{{.*[/\\]}}main.c"{{$}}
49+
50+
//--- cdb.json.template
51+
[
52+
{
53+
"directory": "DIR",
54+
"command": "clang -fsyntax-only -fmodules DIR/main.c -F DIR/frameworks -I DIR -fmodules-cache-path=DIR/module-cache",
55+
"file": "DIR/t.c"
56+
}
57+
]
58+
59+
//--- dummy.h
60+
extern int dummy;
61+
62+
//--- module.modulemap
63+
module dummy { header "dummy.h" }
64+
module Mod { header "Mod.h" }
65+
//--- frameworks/Spurious.framework/Modules/module.modulemap
66+
framework module Spurious {
67+
umbrella header "Spurious.h"
68+
module * { export * }
69+
}
70+
//--- frameworks/Spurious.framework/Headers/Spurious.h
71+
#include <Mod.h>
72+
//--- frameworks/Spurious.framework/Headers/Missing.h
73+
/* empty */
74+
//--- Mod.h
75+
typedef int mod_int;
76+
//--- test.h
77+
#include "dummy.h"
78+
//--- main.c
79+
int bar();
80+
#include "test.h"
81+
int foo();
82+
#include "dummy.h"
83+
#include <Spurious/Missing.h>
84+
#include <Mod.h>

0 commit comments

Comments
 (0)