Skip to content

Commit ad9d39a

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 f0696f3 commit ad9d39a

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
@@ -2000,13 +2000,41 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
20002000
auto Include = CActions->handleIncludeDirective(
20012001
*this, IncludePos, CurLexer->getSourceLocation());
20022002

2003+
auto InclusionCallback = [&](OptionalFileEntryRef FileRef,
2004+
const Module *SuggestedModule) {
2005+
if (!Callbacks || HashLoc.isInvalid())
2006+
return;
2007+
2008+
SmallString<128> FilenameBuffer;
2009+
StringRef Filename = getSpelling(FilenameTok, FilenameBuffer);
2010+
SourceLocation CharEnd = FilenameTok.getEndLoc();
2011+
CharSourceRange FilenameRange =
2012+
CharSourceRange::getCharRange(FilenameTok.getLocation(), CharEnd);
2013+
bool isAngled =
2014+
GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
2015+
SrcMgr::CharacteristicKind FileCharacter =
2016+
SourceMgr.getFileCharacteristic(FilenameTok.getLocation());
2017+
if (SuggestedModule)
2018+
Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
2019+
FilenameRange, OptionalFileEntryRef(),
2020+
/*SearchPath=*/"", /*RelativePath=*/"",
2021+
SuggestedModule,
2022+
/*ModuleImported=*/true, FileCharacter);
2023+
else
2024+
Callbacks->InclusionDirective(
2025+
HashLoc, IncludeTok, Filename, isAngled, FilenameRange, FileRef,
2026+
/*SearchPath=*/"", /*RelativePath=*/"", /*SuggestedModule=*/nullptr,
2027+
/*ModuleImported=*/false, FileCharacter);
2028+
};
2029+
20032030
auto HandleIncludeFile = [&](const PPCachedActions::IncludeFile *File) {
20042031
OptionalFileEntryRef FE = SourceMgr.getFileEntryRefForID(File->FID);
20052032
bool IsImport =
20062033
IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import;
20072034
if (FE && IsImport) {
20082035
HeaderInfo.getFileInfo(*FE).isImport = true;
20092036
}
2037+
InclusionCallback(SourceMgr.getFileEntryRefForID(File->FID), nullptr);
20102038
EnterSourceFile(File->FID, nullptr, FilenameTok.getLocation(),
20112039
/*IsFirstIncludeOfFile*/ true);
20122040

@@ -2073,6 +2101,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
20732101
return;
20742102
}
20752103

2104+
InclusionCallback({}, Imported);
20762105
makeModuleVisible(Imported, EndLoc);
20772106
if (IncludeTok.getIdentifierInfo()->getPPKeywordID() !=
20782107
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)