forked from OSchip/llvm-project
Revert "[clang][pp] adds '#pragma include_instead'"
> `#pragma clang include_instead(<header>)` is a pragma that can be used
> by system headers (and only system headers) to indicate to a tool that
> the file containing said pragma is an implementation-detail header and
> should not be directly included by user code.
>
> The library alternative is very messy code that can be seen in the first
> diff of D106124, and we'd rather avoid that with something more
> universal.
>
> This patch takes the first step by warning a user when they include a
> detail header in their code, and suggests alternative headers that the
> user should include instead. Future work will involve adding a fixit to
> automate the process, as well as cleaning up modules diagnostics to not
> suggest said detail headers. Other tools, such as clangd can also take
> advantage of this pragma to add the correct user headers.
>
> Differential Revision: https://reviews.llvm.org/D106394
This caused compiler crashes in Chromium builds involving PCH and an include
directive with macro expansion, when Token::getLiteralData() returned null. See
the code review for details.
This reverts commit e8a64e5491
.
This commit is contained in:
parent
a8cfa4b9bd
commit
973de71856
|
@ -300,12 +300,6 @@ def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">,
|
||||||
def pp_pragma_sysheader_in_main_file : Warning<
|
def pp_pragma_sysheader_in_main_file : Warning<
|
||||||
"#pragma system_header ignored in main file">,
|
"#pragma system_header ignored in main file">,
|
||||||
InGroup<DiagGroup<"pragma-system-header-outside-header">>;
|
InGroup<DiagGroup<"pragma-system-header-outside-header">>;
|
||||||
|
|
||||||
def err_pragma_include_instead_not_sysheader : Error<
|
|
||||||
"'#pragma clang include_instead' cannot be used outside of system headers">;
|
|
||||||
def err_pragma_include_instead_system_reserved : Error<
|
|
||||||
"header '%0' is an implementation detail; #include %select{'%2'|either '%2' or '%3'|one of %2}1 instead">;
|
|
||||||
|
|
||||||
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
|
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
|
||||||
def pp_out_of_date_dependency : Warning<
|
def pp_out_of_date_dependency : Warning<
|
||||||
"current file is older than dependency %0">;
|
"current file is older than dependency %0">;
|
||||||
|
|
|
@ -20,12 +20,9 @@
|
||||||
#include "clang/Lex/ModuleMap.h"
|
#include "clang/Lex/ModuleMap.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
|
||||||
#include "llvm/ADT/SmallSet.h"
|
|
||||||
#include "llvm/ADT/SmallString.h"
|
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
|
||||||
#include "llvm/ADT/StringSet.h"
|
#include "llvm/ADT/StringSet.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/Allocator.h"
|
#include "llvm/Support/Allocator.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
@ -113,14 +110,6 @@ struct HeaderFileInfo {
|
||||||
/// of the framework.
|
/// of the framework.
|
||||||
StringRef Framework;
|
StringRef Framework;
|
||||||
|
|
||||||
/// List of aliases that this header is known as.
|
|
||||||
/// Most headers should only have at most one alias, but a handful
|
|
||||||
/// have two.
|
|
||||||
llvm::SetVector<llvm::SmallString<32>,
|
|
||||||
llvm::SmallVector<llvm::SmallString<32>, 2>,
|
|
||||||
llvm::SmallSet<llvm::SmallString<32>, 2>>
|
|
||||||
Aliases;
|
|
||||||
|
|
||||||
HeaderFileInfo()
|
HeaderFileInfo()
|
||||||
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
|
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
|
||||||
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
|
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
|
||||||
|
@ -464,10 +453,6 @@ public:
|
||||||
getFileInfo(File).DirInfo = SrcMgr::C_System;
|
getFileInfo(File).DirInfo = SrcMgr::C_System;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFileAlias(const FileEntry *File, StringRef Alias) {
|
|
||||||
getFileInfo(File).Aliases.insert(Alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mark the specified file as part of a module.
|
/// Mark the specified file as part of a module.
|
||||||
void MarkFileModuleHeader(const FileEntry *FE,
|
void MarkFileModuleHeader(const FileEntry *FE,
|
||||||
ModuleMap::ModuleHeaderRole Role,
|
ModuleMap::ModuleHeaderRole Role,
|
||||||
|
|
|
@ -1953,8 +1953,7 @@ public:
|
||||||
/// This either returns the EOF token and returns true, or
|
/// This either returns the EOF token and returns true, or
|
||||||
/// pops a level off the include stack and returns false, at which point the
|
/// pops a level off the include stack and returns false, at which point the
|
||||||
/// client should call lex again.
|
/// client should call lex again.
|
||||||
bool HandleEndOfFile(Token &Result, SourceLocation Loc,
|
bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
|
||||||
bool isEndOfMacro = false);
|
|
||||||
|
|
||||||
/// Callback invoked when the current TokenLexer hits the end of its
|
/// Callback invoked when the current TokenLexer hits the end of its
|
||||||
/// token stream.
|
/// token stream.
|
||||||
|
@ -2364,14 +2363,12 @@ private:
|
||||||
|
|
||||||
// Pragmas.
|
// Pragmas.
|
||||||
void HandlePragmaDirective(PragmaIntroducer Introducer);
|
void HandlePragmaDirective(PragmaIntroducer Introducer);
|
||||||
void ResolvePragmaIncludeInstead(SourceLocation Location) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void HandlePragmaOnce(Token &OnceTok);
|
void HandlePragmaOnce(Token &OnceTok);
|
||||||
void HandlePragmaMark(Token &MarkTok);
|
void HandlePragmaMark(Token &MarkTok);
|
||||||
void HandlePragmaPoison();
|
void HandlePragmaPoison();
|
||||||
void HandlePragmaSystemHeader(Token &SysHeaderTok);
|
void HandlePragmaSystemHeader(Token &SysHeaderTok);
|
||||||
void HandlePragmaIncludeInstead(Token &Tok);
|
|
||||||
void HandlePragmaDependency(Token &DependencyTok);
|
void HandlePragmaDependency(Token &DependencyTok);
|
||||||
void HandlePragmaPushMacro(Token &Tok);
|
void HandlePragmaPushMacro(Token &Tok);
|
||||||
void HandlePragmaPopMacro(Token &Tok);
|
void HandlePragmaPopMacro(Token &Tok);
|
||||||
|
|
|
@ -14,13 +14,11 @@
|
||||||
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
|
#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
|
||||||
#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
|
#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
|
||||||
|
|
||||||
#include "clang/Basic/SourceLocation.h"
|
|
||||||
#include "clang/Lex/HeaderSearch.h"
|
|
||||||
#include "clang/Lex/MultipleIncludeOpt.h"
|
#include "clang/Lex/MultipleIncludeOpt.h"
|
||||||
#include "clang/Lex/Token.h"
|
#include "clang/Lex/Token.h"
|
||||||
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
@ -76,13 +74,6 @@ protected:
|
||||||
/// we are currently in.
|
/// we are currently in.
|
||||||
SmallVector<PPConditionalInfo, 4> ConditionalStack;
|
SmallVector<PPConditionalInfo, 4> ConditionalStack;
|
||||||
|
|
||||||
struct IncludeInfo {
|
|
||||||
const FileEntry *File;
|
|
||||||
SourceLocation Location;
|
|
||||||
};
|
|
||||||
// A complete history of all the files included by the current file.
|
|
||||||
llvm::StringMap<IncludeInfo> IncludeHistory;
|
|
||||||
|
|
||||||
PreprocessorLexer() : FID() {}
|
PreprocessorLexer() : FID() {}
|
||||||
PreprocessorLexer(Preprocessor *pp, FileID fid);
|
PreprocessorLexer(Preprocessor *pp, FileID fid);
|
||||||
virtual ~PreprocessorLexer() = default;
|
virtual ~PreprocessorLexer() = default;
|
||||||
|
@ -184,15 +175,6 @@ public:
|
||||||
ConditionalStack.clear();
|
ConditionalStack.clear();
|
||||||
ConditionalStack.append(CL.begin(), CL.end());
|
ConditionalStack.append(CL.begin(), CL.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addInclude(StringRef Filename, const FileEntry &File,
|
|
||||||
SourceLocation Location) {
|
|
||||||
IncludeHistory.insert({Filename, {&File, Location}});
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm::StringMap<IncludeInfo> &getIncludeHistory() const {
|
|
||||||
return IncludeHistory;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
|
@ -2811,11 +2811,11 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
|
||||||
ConditionalStack.pop_back();
|
ConditionalStack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation EndLoc = getSourceLocation(BufferEnd);
|
|
||||||
// C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
|
// C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
|
||||||
// a pedwarn.
|
// a pedwarn.
|
||||||
if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
|
if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
|
||||||
DiagnosticsEngine &Diags = PP->getDiagnostics();
|
DiagnosticsEngine &Diags = PP->getDiagnostics();
|
||||||
|
SourceLocation EndLoc = getSourceLocation(BufferEnd);
|
||||||
unsigned DiagID;
|
unsigned DiagID;
|
||||||
|
|
||||||
if (LangOpts.CPlusPlus11) {
|
if (LangOpts.CPlusPlus11) {
|
||||||
|
@ -2838,7 +2838,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
|
||||||
BufferPtr = CurPtr;
|
BufferPtr = CurPtr;
|
||||||
|
|
||||||
// Finally, let the preprocessor handle this.
|
// Finally, let the preprocessor handle this.
|
||||||
return PP->HandleEndOfFile(Result, EndLoc, isPragmaLexer());
|
return PP->HandleEndOfFile(Result, isPragmaLexer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from
|
/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from
|
||||||
|
|
|
@ -2022,12 +2022,6 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
|
||||||
IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
|
IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
|
||||||
LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
|
LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
|
||||||
|
|
||||||
// Record the header's filename for later use.
|
|
||||||
if (File)
|
|
||||||
CurLexer->addInclude(
|
|
||||||
{FilenameTok.getLiteralData(), FilenameTok.getLength()},
|
|
||||||
File->getFileEntry(), FilenameLoc);
|
|
||||||
|
|
||||||
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
|
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
|
||||||
if (File && isPCHThroughHeader(&File->getFileEntry()))
|
if (File && isPCHThroughHeader(&File->getFileEntry()))
|
||||||
SkippingUntilPCHThroughHeader = false;
|
SkippingUntilPCHThroughHeader = false;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "clang/Basic/FileManager.h"
|
#include "clang/Basic/FileManager.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Lex/HeaderSearch.h"
|
#include "clang/Lex/HeaderSearch.h"
|
||||||
#include "clang/Lex/LexDiagnostic.h"
|
#include "clang/Lex/LexDiagnostic.h"
|
||||||
|
@ -23,7 +22,6 @@
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/MemoryBufferRef.h"
|
#include "llvm/Support/MemoryBufferRef.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -301,46 +299,10 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preprocessor::ResolvePragmaIncludeInstead(
|
|
||||||
const SourceLocation Location) const {
|
|
||||||
assert(Location.isValid());
|
|
||||||
if (CurLexer == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (SourceMgr.isInSystemHeader(Location))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const auto &Include : CurLexer->getIncludeHistory()) {
|
|
||||||
StringRef Filename = Include.getKey();
|
|
||||||
const PreprocessorLexer::IncludeInfo &Info = Include.getValue();
|
|
||||||
ArrayRef<SmallString<32>> Aliases =
|
|
||||||
HeaderInfo.getFileInfo(Info.File).Aliases.getArrayRef();
|
|
||||||
|
|
||||||
if (Aliases.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (Aliases.size()) {
|
|
||||||
case 1:
|
|
||||||
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
|
|
||||||
<< Filename << 0 << Aliases[0];
|
|
||||||
continue;
|
|
||||||
case 2:
|
|
||||||
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
|
|
||||||
<< Filename << 1 << Aliases[0] << Aliases[1];
|
|
||||||
continue;
|
|
||||||
default: {
|
|
||||||
Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
|
|
||||||
<< Filename << 2 << ("{'" + llvm::join(Aliases, "', '") + "'}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
|
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
|
||||||
/// the current file. This either returns the EOF token or pops a level off
|
/// the current file. This either returns the EOF token or pops a level off
|
||||||
/// the include stack and keeps going.
|
/// the include stack and keeps going.
|
||||||
bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc,
|
bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||||
bool isEndOfMacro) {
|
|
||||||
assert(!CurTokenLexer &&
|
assert(!CurTokenLexer &&
|
||||||
"Ending a file when currently in a macro!");
|
"Ending a file when currently in a macro!");
|
||||||
|
|
||||||
|
@ -410,9 +372,6 @@ bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EndLoc.isValid())
|
|
||||||
ResolvePragmaIncludeInstead(EndLoc);
|
|
||||||
|
|
||||||
// Complain about reaching a true EOF within arc_cf_code_audited.
|
// Complain about reaching a true EOF within arc_cf_code_audited.
|
||||||
// We don't want to complain about reaching the end of a macro
|
// We don't want to complain about reaching the end of a macro
|
||||||
// instantiation or a _Pragma.
|
// instantiation or a _Pragma.
|
||||||
|
@ -601,7 +560,7 @@ bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
|
||||||
TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);
|
TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);
|
||||||
|
|
||||||
// Handle this like a #include file being popped off the stack.
|
// Handle this like a #include file being popped off the stack.
|
||||||
return HandleEndOfFile(Result, {}, true);
|
return HandleEndOfFile(Result, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
|
/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
#include "clang/Lex/Pragma.h"
|
#include "clang/Lex/Pragma.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "clang/Basic/DiagnosticLex.h"
|
|
||||||
#include "clang/Basic/FileManager.h"
|
#include "clang/Basic/FileManager.h"
|
||||||
#include "clang/Basic/IdentifierTable.h"
|
#include "clang/Basic/IdentifierTable.h"
|
||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
|
@ -36,12 +35,11 @@
|
||||||
#include "clang/Lex/TokenLexer.h"
|
#include "clang/Lex/TokenLexer.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/Timer.h"
|
#include "llvm/Support/Timer.h"
|
||||||
|
@ -497,88 +495,43 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
|
||||||
SrcMgr::C_System);
|
SrcMgr::C_System);
|
||||||
}
|
}
|
||||||
|
|
||||||
static llvm::Optional<Token> LexHeader(Preprocessor &PP,
|
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
|
||||||
Optional<FileEntryRef> &File,
|
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
|
||||||
bool SuppressIncludeNotFoundError) {
|
|
||||||
Token FilenameTok;
|
Token FilenameTok;
|
||||||
if (PP.LexHeaderName(FilenameTok, /*AllowConcatenation*/ false))
|
if (LexHeaderName(FilenameTok, /*AllowConcatenation*/false))
|
||||||
return llvm::None;
|
return;
|
||||||
|
|
||||||
// If the next token wasn't a header-name, diagnose the error.
|
// If the next token wasn't a header-name, diagnose the error.
|
||||||
if (FilenameTok.isNot(tok::header_name)) {
|
if (FilenameTok.isNot(tok::header_name)) {
|
||||||
PP.Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
|
Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
|
||||||
return llvm::None;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve a buffer to get the spelling.
|
// Reserve a buffer to get the spelling.
|
||||||
SmallString<128> FilenameBuffer;
|
SmallString<128> FilenameBuffer;
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
StringRef Filename = PP.getSpelling(FilenameTok, FilenameBuffer, &Invalid);
|
StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
|
||||||
if (Invalid)
|
if (Invalid)
|
||||||
return llvm::None;
|
return;
|
||||||
|
|
||||||
bool isAngled =
|
bool isAngled =
|
||||||
PP.GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
|
GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
|
||||||
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
|
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
|
||||||
// error.
|
// error.
|
||||||
if (Filename.empty())
|
if (Filename.empty())
|
||||||
return llvm::None;
|
return;
|
||||||
|
|
||||||
// Search include directories for this file.
|
// Search include directories for this file.
|
||||||
const DirectoryLookup *CurDir;
|
const DirectoryLookup *CurDir;
|
||||||
File = PP.LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
|
Optional<FileEntryRef> File =
|
||||||
nullptr, CurDir, nullptr, nullptr, nullptr, nullptr,
|
LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
|
||||||
nullptr);
|
nullptr, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||||
if (!File) {
|
if (!File) {
|
||||||
if (!SuppressIncludeNotFoundError)
|
if (!SuppressIncludeNotFoundError)
|
||||||
PP.Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
|
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
|
||||||
return llvm::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FilenameTok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// HandlePragmaIncludeInstead - Handle \#pragma clang include_instead(header).
|
|
||||||
void Preprocessor::HandlePragmaIncludeInstead(Token &Tok) {
|
|
||||||
// Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
|
|
||||||
PreprocessorLexer *TheLexer = getCurrentFileLexer();
|
|
||||||
|
|
||||||
if (!SourceMgr.isInSystemHeader(Tok.getLocation())) {
|
|
||||||
Diag(Tok, diag::err_pragma_include_instead_not_sysheader);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lex(Tok);
|
|
||||||
if (Tok.isNot(tok::l_paren)) {
|
|
||||||
Diag(Tok, diag::err_expected) << "(";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<FileEntryRef> File;
|
|
||||||
llvm::Optional<Token> FilenameTok =
|
|
||||||
LexHeader(*this, File, SuppressIncludeNotFoundError);
|
|
||||||
if (!FilenameTok)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Lex(Tok);
|
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
|
||||||
Diag(Tok, diag::err_expected) << ")";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeaderInfo.AddFileAlias(
|
|
||||||
TheLexer->getFileEntry(),
|
|
||||||
{FilenameTok->getLiteralData(), FilenameTok->getLength()});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
|
|
||||||
void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
|
|
||||||
Optional<FileEntryRef> File;
|
|
||||||
llvm::Optional<Token> FilenameTok =
|
|
||||||
LexHeader(*this, File, SuppressIncludeNotFoundError);
|
|
||||||
if (!FilenameTok)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
|
const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
|
||||||
|
|
||||||
// If this file is older than the file it depends on, emit a diagnostic.
|
// If this file is older than the file it depends on, emit a diagnostic.
|
||||||
|
@ -594,7 +547,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
|
||||||
// Remove the trailing ' ' if present.
|
// Remove the trailing ' ' if present.
|
||||||
if (!Message.empty())
|
if (!Message.empty())
|
||||||
Message.erase(Message.end()-1);
|
Message.erase(Message.end()-1);
|
||||||
Diag(*FilenameTok, diag::pp_out_of_date_dependency) << Message;
|
Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,18 +1022,6 @@ struct PragmaSystemHeaderHandler : public PragmaHandler {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// PragmaIncludeInsteadHandler - "\#pragma clang include_instead(header)" marks
|
|
||||||
/// the current file as non-includable if the including header is not a system
|
|
||||||
/// header.
|
|
||||||
struct PragmaIncludeInsteadHandler : public PragmaHandler {
|
|
||||||
PragmaIncludeInsteadHandler() : PragmaHandler("include_instead") {}
|
|
||||||
|
|
||||||
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
|
|
||||||
Token &IIToken) override {
|
|
||||||
PP.HandlePragmaIncludeInstead(IIToken);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PragmaDependencyHandler : public PragmaHandler {
|
struct PragmaDependencyHandler : public PragmaHandler {
|
||||||
PragmaDependencyHandler() : PragmaHandler("dependency") {}
|
PragmaDependencyHandler() : PragmaHandler("dependency") {}
|
||||||
|
|
||||||
|
@ -1993,7 +1934,6 @@ void Preprocessor::RegisterBuiltinPragmas() {
|
||||||
// #pragma clang ...
|
// #pragma clang ...
|
||||||
AddPragmaHandler("clang", new PragmaPoisonHandler());
|
AddPragmaHandler("clang", new PragmaPoisonHandler());
|
||||||
AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
|
AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
|
||||||
AddPragmaHandler("clang", new PragmaIncludeInsteadHandler());
|
|
||||||
AddPragmaHandler("clang", new PragmaDebugHandler());
|
AddPragmaHandler("clang", new PragmaDebugHandler());
|
||||||
AddPragmaHandler("clang", new PragmaDependencyHandler());
|
AddPragmaHandler("clang", new PragmaDependencyHandler());
|
||||||
AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
|
AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma GCC system_header
|
|
||||||
|
|
||||||
#pragma clang include_instead <include_instead/public-before.h>
|
|
||||||
// expected-error@-1{{expected (}}
|
|
||||||
|
|
||||||
#pragma clang include_instead(<include_instead/public-after.h>]
|
|
||||||
// expected-error@-1{{expected )}}
|
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma GCC system_header
|
|
||||||
#pragma clang include_instead(<include_instead/does_not_exist.h>)
|
|
||||||
// expected-error@-1{{'include_instead/does_not_exist.h' file not found}}
|
|
|
@ -1,2 +0,0 @@
|
||||||
#pragma clang include_instead(<include_instead/public1.h>)
|
|
||||||
// expected-error@-1{{'#pragma clang include_instead' cannot be used outside of system headers}}
|
|
|
@ -1,4 +0,0 @@
|
||||||
#include <include_instead/private1.h>
|
|
||||||
|
|
||||||
#pragma GCC system_header
|
|
||||||
#pragma clang include_instead(<include_instead/public-gcc-system-header-before-includes.h>)
|
|
|
@ -1,2 +0,0 @@
|
||||||
#pragma GCC system_header
|
|
||||||
#pragma clang include_instead(<include_instead/public-before.h>)
|
|
|
@ -1,4 +0,0 @@
|
||||||
#pragma GCC system_header
|
|
||||||
|
|
||||||
#pragma clang include_instead(<include_instead/public-before.h>)
|
|
||||||
#pragma clang include_instead("include_instead/public-after.h")
|
|
|
@ -1,5 +0,0 @@
|
||||||
#pragma GCC system_header
|
|
||||||
|
|
||||||
#pragma clang include_instead(<include_instead/public-after.h>)
|
|
||||||
#pragma clang include_instead(<include_instead/public-empty.h>)
|
|
||||||
#pragma clang include_instead("include_instead/public-before.h")
|
|
|
@ -1,2 +0,0 @@
|
||||||
#include <include_instead/private2.h>
|
|
||||||
#pragma GCC system_header
|
|
|
@ -1,5 +0,0 @@
|
||||||
#pragma GCC system_header
|
|
||||||
|
|
||||||
#include <include_instead/private1.h> // no warning expected
|
|
||||||
#include <include_instead/private2.h> // no warning expected
|
|
||||||
#include <include_instead/private3.h> // no warning expected
|
|
|
@ -1 +0,0 @@
|
||||||
// This file simply needs to exist.
|
|
|
@ -1,16 +0,0 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
|
|
||||||
|
|
||||||
#include <include_instead/bad-syntax.h>
|
|
||||||
#include <include_instead/non-system-header.h>
|
|
||||||
|
|
||||||
#include <include_instead/private1.h>
|
|
||||||
// expected-error@-1{{header '<include_instead/private1.h>' is an implementation detail; #include '<include_instead/public-before.h>' instead}}
|
|
||||||
|
|
||||||
#include "include_instead/private2.h"
|
|
||||||
// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '<include_instead/public-before.h>' or '"include_instead/public-after.h"' instead}}
|
|
||||||
|
|
||||||
#include <include_instead/private3.h>
|
|
||||||
// expected-error@-1{{header '<include_instead/private3.h>' is an implementation detail; #include one of {'<include_instead/public-after.h>', '<include_instead/public-empty.h>', '"include_instead/public-before.h"'} instead}}
|
|
||||||
|
|
||||||
#include <include_instead/public-before.h>
|
|
||||||
#include <include_instead/public-after.h>
|
|
|
@ -1,2 +0,0 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
|
|
||||||
#include <include_instead/file-not-found.h>
|
|
Loading…
Reference in New Issue