From cb203b4a0ed3f55553bdc65ef25263e5b7e3ce51 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Wed, 3 Apr 2024 08:36:05 -0700 Subject: [PATCH] [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 (cherry picked from commit ad9d39a8c46444d31eb3a62a663cc2316d684f59) --- clang/lib/Lex/PPDirectives.cpp | 29 +++++++++++ clang/test/CAS/rewrite-includes.c | 84 +++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 clang/test/CAS/rewrite-includes.c diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index e30f47f762478..cb964bd5e451f 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1995,6 +1995,33 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, auto Include = CActions->handleIncludeDirective( *this, IncludePos, CurLexer->getSourceLocation()); + auto InclusionCallback = [&](OptionalFileEntryRef FileRef, + const Module *SuggestedModule) { + if (!Callbacks || HashLoc.isInvalid()) + return; + + SmallString<128> FilenameBuffer; + StringRef Filename = getSpelling(FilenameTok, FilenameBuffer); + SourceLocation CharEnd = FilenameTok.getEndLoc(); + CharSourceRange FilenameRange = + CharSourceRange::getCharRange(FilenameTok.getLocation(), CharEnd); + bool isAngled = + GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); + SrcMgr::CharacteristicKind FileCharacter = + SourceMgr.getFileCharacteristic(FilenameTok.getLocation()); + if (SuggestedModule) + Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, + FilenameRange, OptionalFileEntryRef(), + /*SearchPath=*/"", /*RelativePath=*/"", + SuggestedModule, + /*ModuleImported=*/true, FileCharacter); + else + Callbacks->InclusionDirective( + HashLoc, IncludeTok, Filename, isAngled, FilenameRange, FileRef, + /*SearchPath=*/"", /*RelativePath=*/"", /*SuggestedModule=*/nullptr, + /*ModuleImported=*/false, FileCharacter); + }; + auto HandleIncludeFile = [&](const PPCachedActions::IncludeFile *File) { const FileEntry *FE = SourceMgr.getFileEntryForID(File->FID); bool IsImport = @@ -2002,6 +2029,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (FE && IsImport) { HeaderInfo.getFileInfo(FE).isImport = true; } + InclusionCallback(SourceMgr.getFileEntryRefForID(File->FID), nullptr); EnterSourceFile(File->FID, nullptr, FilenameTok.getLocation(), /*IsFirstIncludeOfFile*/ true); @@ -2068,6 +2096,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, return; } + InclusionCallback({}, Imported); makeModuleVisible(Imported, EndLoc); if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp___include_macros) diff --git a/clang/test/CAS/rewrite-includes.c b/clang/test/CAS/rewrite-includes.c new file mode 100644 index 0000000000000..b927e734f187f --- /dev/null +++ b/clang/test/CAS/rewrite-includes.c @@ -0,0 +1,84 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree-full -cas-path %t/cas > %t/deps.json + +// RUN: %deps-to-rsp %t/deps.json --module-name dummy > %t/dummy.rsp +// RUN: %deps-to-rsp %t/deps.json --module-name Mod > %t/mod.rsp +// RUN: %deps-to-rsp %t/deps.json --module-name Spurious > %t/spurious.rsp +// RUN: %deps-to-rsp %t/deps.json --tu-index 0 > %t/tu.rsp +// RUN: %clang @%t/dummy.rsp +// RUN: %clang @%t/mod.rsp +// RUN: %clang @%t/spurious.rsp +// RUN: %clang @%t/tu.rsp -frewrite-includes -w -E -o - | FileCheck %s + +// CHECK: int bar();{{$}} +// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: #include "test.h"{{$}} +// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: # 2 "{{.*[/\\]}}main.c"{{$}} +// CHECK-NEXT: # 1 "{{.*[/\\]}}test.h" 1{{$}} +// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: #include "dummy.h"{{$}} +// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: # 1 "{{.*[/\\]}}test.h"{{$}} +// CHECK-NEXT: #pragma clang module import dummy /* clang -frewrite-includes: implicit import */{{$}} +// CHECK-NEXT: # 2 "{{.*[/\\]}}test.h"{{$}} +// CHECK-NEXT: # 3 "{{.*[/\\]}}main.c" 2{{$}} +// CHECK-NEXT: int foo();{{$}} +// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: #include "dummy.h"{{$}} +// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: # 4 "{{.*[/\\]}}main.c"{{$}} +// CHECK-NEXT: #pragma clang module import dummy /* clang -frewrite-includes: implicit import */{{$}} +// CHECK-NEXT: # 5 "{{.*[/\\]}}main.c"{{$}} +// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: #include {{$}} +// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: # 5 "{{.*[/\\]}}main.c"{{$}} +// CHECK-NEXT: # 1 "{{.*[/\\]}}Missing.h" 1{{$}} +// CHECK-NEXT: /* empty */ +// CHECK-NEXT: # 6 "{{.*[/\\]}}main.c" 2{{$}} +// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: #include {{$}} +// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}} +// CHECK-NEXT: # 6 "{{.*[/\\]}}main.c"{{$}} +// CHECK-NEXT: #pragma clang module import Mod /* clang -frewrite-includes: implicit import */{{$}} +// CHECK-NEXT: # 7 "{{.*[/\\]}}main.c"{{$}} + +//--- cdb.json.template +[ + { + "directory": "DIR", + "command": "clang -fsyntax-only -fmodules DIR/main.c -F DIR/frameworks -I DIR -fmodules-cache-path=DIR/module-cache", + "file": "DIR/t.c" + } +] + +//--- dummy.h +extern int dummy; + +//--- module.modulemap +module dummy { header "dummy.h" } +module Mod { header "Mod.h" } +//--- frameworks/Spurious.framework/Modules/module.modulemap +framework module Spurious { + umbrella header "Spurious.h" + module * { export * } +} +//--- frameworks/Spurious.framework/Headers/Spurious.h +#include +//--- frameworks/Spurious.framework/Headers/Missing.h +/* empty */ +//--- Mod.h +typedef int mod_int; +//--- test.h +#include "dummy.h" +//--- main.c +int bar(); +#include "test.h" +int foo(); +#include "dummy.h" +#include +#include