Skip to content

Commit 0871954

Browse files
committed
Revert "Revert "[clang][pp] adds '#pragma include_instead'""
Includes regression test for problem noted by @hans. This reverts commit 973de71. Differential Revision: https://reviews.llvm.org/D106898
1 parent d8e4cb9 commit 0871954

21 files changed

+230
-23
lines changed

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">,
300300
def pp_pragma_sysheader_in_main_file : Warning<
301301
"#pragma system_header ignored in main file">,
302302
InGroup<DiagGroup<"pragma-system-header-outside-header">>;
303+
304+
def err_pragma_include_instead_not_sysheader : Error<
305+
"'#pragma clang include_instead' cannot be used outside of system headers">;
306+
def err_pragma_include_instead_system_reserved : Error<
307+
"header '%0' is an implementation detail; #include %select{'%2'|either '%2' "
308+
"or '%3'|one of %2}1 instead">;
309+
303310
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
304311
def pp_out_of_date_dependency : Warning<
305312
"current file is older than dependency %0">;

clang/include/clang/Lex/HeaderSearch.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020
#include "clang/Lex/ModuleMap.h"
2121
#include "llvm/ADT/ArrayRef.h"
2222
#include "llvm/ADT/DenseMap.h"
23+
#include "llvm/ADT/SetVector.h"
24+
#include "llvm/ADT/SmallSet.h"
25+
#include "llvm/ADT/SmallString.h"
2326
#include "llvm/ADT/StringMap.h"
24-
#include "llvm/ADT/StringSet.h"
2527
#include "llvm/ADT/StringRef.h"
28+
#include "llvm/ADT/StringSet.h"
2629
#include "llvm/Support/Allocator.h"
2730
#include <cassert>
2831
#include <cstddef>
@@ -110,6 +113,14 @@ struct HeaderFileInfo {
110113
/// of the framework.
111114
StringRef Framework;
112115

116+
/// List of aliases that this header is known as.
117+
/// Most headers should only have at most one alias, but a handful
118+
/// have two.
119+
llvm::SetVector<llvm::SmallString<32>,
120+
llvm::SmallVector<llvm::SmallString<32>, 2>,
121+
llvm::SmallSet<llvm::SmallString<32>, 2>>
122+
Aliases;
123+
113124
HeaderFileInfo()
114125
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
115126
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
@@ -453,6 +464,10 @@ class HeaderSearch {
453464
getFileInfo(File).DirInfo = SrcMgr::C_System;
454465
}
455466

467+
void AddFileAlias(const FileEntry *File, StringRef Alias) {
468+
getFileInfo(File).Aliases.insert(Alias);
469+
}
470+
456471
/// Mark the specified file as part of a module.
457472
void MarkFileModuleHeader(const FileEntry *FE,
458473
ModuleMap::ModuleHeaderRole Role,

clang/include/clang/Lex/Preprocessor.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1961,7 +1961,8 @@ class Preprocessor {
19611961
/// This either returns the EOF token and returns true, or
19621962
/// pops a level off the include stack and returns false, at which point the
19631963
/// client should call lex again.
1964-
bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
1964+
bool HandleEndOfFile(Token &Result, SourceLocation Loc,
1965+
bool isEndOfMacro = false);
19651966

19661967
/// Callback invoked when the current TokenLexer hits the end of its
19671968
/// token stream.
@@ -2373,12 +2374,14 @@ class Preprocessor {
23732374

23742375
// Pragmas.
23752376
void HandlePragmaDirective(PragmaIntroducer Introducer);
2377+
void ResolvePragmaIncludeInstead(SourceLocation Location) const;
23762378

23772379
public:
23782380
void HandlePragmaOnce(Token &OnceTok);
23792381
void HandlePragmaMark(Token &MarkTok);
23802382
void HandlePragmaPoison();
23812383
void HandlePragmaSystemHeader(Token &SysHeaderTok);
2384+
void HandlePragmaIncludeInstead(Token &Tok);
23822385
void HandlePragmaDependency(Token &DependencyTok);
23832386
void HandlePragmaPushMacro(Token &Tok);
23842387
void HandlePragmaPopMacro(Token &Tok);

clang/include/clang/Lex/PreprocessorLexer.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
1515
#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
1616

17+
#include "clang/Basic/SourceLocation.h"
18+
#include "clang/Lex/HeaderSearch.h"
1719
#include "clang/Lex/MultipleIncludeOpt.h"
1820
#include "clang/Lex/Token.h"
19-
#include "clang/Basic/SourceLocation.h"
2021
#include "llvm/ADT/ArrayRef.h"
2122
#include "llvm/ADT/SmallVector.h"
23+
#include "llvm/ADT/StringMap.h"
2224
#include <cassert>
2325

2426
namespace clang {
@@ -74,6 +76,13 @@ class PreprocessorLexer {
7476
/// we are currently in.
7577
SmallVector<PPConditionalInfo, 4> ConditionalStack;
7678

79+
struct IncludeInfo {
80+
const FileEntry *File;
81+
SourceLocation Location;
82+
};
83+
// A complete history of all the files included by the current file.
84+
llvm::StringMap<IncludeInfo> IncludeHistory;
85+
7786
PreprocessorLexer() : FID() {}
7887
PreprocessorLexer(Preprocessor *pp, FileID fid);
7988
virtual ~PreprocessorLexer() = default;
@@ -175,6 +184,15 @@ class PreprocessorLexer {
175184
ConditionalStack.clear();
176185
ConditionalStack.append(CL.begin(), CL.end());
177186
}
187+
188+
void addInclude(StringRef Filename, const FileEntry &File,
189+
SourceLocation Location) {
190+
IncludeHistory.insert({Filename, {&File, Location}});
191+
}
192+
193+
const llvm::StringMap<IncludeInfo> &getIncludeHistory() const {
194+
return IncludeHistory;
195+
}
178196
};
179197

180198
} // namespace clang

clang/lib/Lex/Lexer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,11 +2811,11 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
28112811
ConditionalStack.pop_back();
28122812
}
28132813

2814+
SourceLocation EndLoc = getSourceLocation(BufferEnd);
28142815
// C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
28152816
// a pedwarn.
28162817
if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
28172818
DiagnosticsEngine &Diags = PP->getDiagnostics();
2818-
SourceLocation EndLoc = getSourceLocation(BufferEnd);
28192819
unsigned DiagID;
28202820

28212821
if (LangOpts.CPlusPlus11) {
@@ -2838,7 +2838,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
28382838
BufferPtr = CurPtr;
28392839

28402840
// Finally, let the preprocessor handle this.
2841-
return PP->HandleEndOfFile(Result, isPragmaLexer());
2841+
return PP->HandleEndOfFile(Result, EndLoc, isPragmaLexer());
28422842
}
28432843

28442844
/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from

clang/lib/Lex/PPDirectives.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,10 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
20322032
IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
20332033
LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
20342034

2035+
// Record the header's filename for later use.
2036+
if (File)
2037+
CurLexer->addInclude(OriginalFilename, File->getFileEntry(), FilenameLoc);
2038+
20352039
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
20362040
if (File && isPCHThroughHeader(&File->getFileEntry()))
20372041
SkippingUntilPCHThroughHeader = false;

clang/lib/Lex/PPLexerChange.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "clang/Basic/FileManager.h"
15+
#include "clang/Basic/SourceLocation.h"
1516
#include "clang/Basic/SourceManager.h"
1617
#include "clang/Lex/HeaderSearch.h"
1718
#include "clang/Lex/LexDiagnostic.h"
@@ -22,6 +23,7 @@
2223
#include "llvm/Support/FileSystem.h"
2324
#include "llvm/Support/MemoryBufferRef.h"
2425
#include "llvm/Support/Path.h"
26+
2527
using namespace clang;
2628

2729
//===----------------------------------------------------------------------===//
@@ -299,10 +301,46 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
299301
}
300302
}
301303

304+
void Preprocessor::ResolvePragmaIncludeInstead(
305+
const SourceLocation Location) const {
306+
assert(Location.isValid());
307+
if (CurLexer == nullptr)
308+
return;
309+
310+
if (SourceMgr.isInSystemHeader(Location))
311+
return;
312+
313+
for (const auto &Include : CurLexer->getIncludeHistory()) {
314+
StringRef Filename = Include.getKey();
315+
const PreprocessorLexer::IncludeInfo &Info = Include.getValue();
316+
ArrayRef<SmallString<32>> Aliases =
317+
HeaderInfo.getFileInfo(Info.File).Aliases.getArrayRef();
318+
319+
if (Aliases.empty())
320+
continue;
321+
322+
switch (Aliases.size()) {
323+
case 1:
324+
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
325+
<< Filename << 0 << Aliases[0];
326+
continue;
327+
case 2:
328+
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
329+
<< Filename << 1 << Aliases[0] << Aliases[1];
330+
continue;
331+
default: {
332+
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
333+
<< Filename << 2 << ("{'" + llvm::join(Aliases, "', '") + "'}");
334+
}
335+
}
336+
}
337+
}
338+
302339
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
303340
/// the current file. This either returns the EOF token or pops a level off
304341
/// the include stack and keeps going.
305-
bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
342+
bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc,
343+
bool isEndOfMacro) {
306344
assert(!CurTokenLexer &&
307345
"Ending a file when currently in a macro!");
308346

@@ -372,6 +410,9 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
372410
}
373411
}
374412

413+
if (EndLoc.isValid())
414+
ResolvePragmaIncludeInstead(EndLoc);
415+
375416
// Complain about reaching a true EOF within arc_cf_code_audited.
376417
// We don't want to complain about reaching the end of a macro
377418
// instantiation or a _Pragma.
@@ -560,7 +601,7 @@ bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
560601
TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);
561602

562603
// Handle this like a #include file being popped off the stack.
563-
return HandleEndOfFile(Result, true);
604+
return HandleEndOfFile(Result, {}, true);
564605
}
565606

566607
/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the

0 commit comments

Comments
 (0)