erikjv created this revision.
erikjv added reviewers: klimek, rsmith.
erikjv added a subscriber: cfe-commits.
When generating pre-compiled headers, or when opening a header file with
libclang, suppress the warnings "#pragma once in main file" and
"#include_next in primary source file".
Fixes PR16686 and PR24390.
http://reviews.llvm.org/D15926
Files:
include/clang/Basic/SourceManager.h
include/clang/Frontend/FrontendOptions.h
lib/Frontend/CompilerInstance.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/FrontendActions.cpp
lib/Lex/PPDirectives.cpp
lib/Lex/PPMacroExpansion.cpp
lib/Lex/Pragma.cpp
test/Preprocessor/header_is_main_file.c
Index: test/Preprocessor/header_is_main_file.c
===================================================================
--- /dev/null
+++ test/Preprocessor/header_is_main_file.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -x c-header -ffreestanding -Eonly -verify %s
+// expected-no-diagnostics
+
+#pragma once
+#include_next "stdint.h"
+#if !__has_include_next("stdint.h")
+#error "__has_include_next failed"
+#endif
Index: lib/Lex/Pragma.cpp
===================================================================
--- lib/Lex/Pragma.cpp
+++ lib/Lex/Pragma.cpp
@@ -354,7 +354,9 @@
/// HandlePragmaOnce - Handle \#pragma once. OnceTok is the 'once'.
///
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
- if (isInPrimaryFile()) {
+ // If the main file is a header, then it's either for PCH/AST generation,
+ // or libclang opened it. Allow #pragma once either way.
+ if (isInPrimaryFile() && !SourceMgr.isMainFileHeader()) {
Diag(OnceTok, diag::pp_pragma_once_in_main_file);
return;
}
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1389,7 +1389,10 @@
// Preprocessor::HandleIncludeNextDirective.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
const FileEntry *LookupFromFile = nullptr;
- if (PP.isInPrimaryFile()) {
+ if (PP.isInPrimaryFile() && PP.getSourceManager().isMainFileHeader()) {
+ // If the main file is a header, then it's either for PCH/AST generation,
+ // or libclang opened it. Either way, handle it as a normal include below.
+ } else if (PP.isInPrimaryFile()) {
Lookup = nullptr;
PP.Diag(Tok, diag::pp_include_next_in_primary);
} else if (PP.getCurrentSubmodule()) {
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -1834,7 +1834,10 @@
// diagnostic.
const DirectoryLookup *Lookup = CurDirLookup;
const FileEntry *LookupFromFile = nullptr;
- if (isInPrimaryFile()) {
+ if (isInPrimaryFile() && SourceMgr.isMainFileHeader()) {
+ // If the main file is a header, then it's either for PCH/AST generation,
+ // or libclang opened it. Either way, handle it as a normal include below.
+ } else if (isInPrimaryFile()) {
Lookup = nullptr;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
} else if (CurSubmodule) {
Index: lib/Frontend/FrontendActions.cpp
===================================================================
--- lib/Frontend/FrontendActions.cpp
+++ lib/Frontend/FrontendActions.cpp
@@ -375,7 +375,7 @@
Module::getModuleInputBufferName());
// Ownership of InputBuffer will be transferred to the SourceManager.
setCurrentInput(FrontendInputFile(InputBuffer.release(), getCurrentFileKind(),
- Module->IsSystem));
+ false, Module->IsSystem));
return true;
}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1141,6 +1141,7 @@
}
InputKind DashX = IK_None;
+ bool IsHeader = false;
if (const Arg *A = Args.getLastArg(OPT_x)) {
DashX = llvm::StringSwitch<InputKind>(A->getValue())
.Case("c", IK_C)
@@ -1168,6 +1169,13 @@
if (DashX == IK_None)
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
+ IsHeader = llvm::StringSwitch<bool>(A->getValue())
+ .Case("c-header", true)
+ .Case("cl-header", true)
+ .Case("objective-c-header", true)
+ .Case("c++-header", true)
+ .Case("objective-c++-header", true)
+ .Default(false);
}
// '-' is the default input if none is given.
@@ -1184,7 +1192,7 @@
if (i == 0)
DashX = IK;
}
- Opts.Inputs.emplace_back(std::move(Inputs[i]), IK);
+ Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsHeader);
}
return DashX;
Index: lib/Frontend/CompilerInstance.cpp
===================================================================
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -724,6 +724,7 @@
const FrontendOptions &Opts) {
SrcMgr::CharacteristicKind
Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
+ SourceMgr.setMainFileHeader(Input.isHeader());
if (Input.isBuffer()) {
SourceMgr.setMainFileID(SourceMgr.createFileID(
Index: include/clang/Frontend/FrontendOptions.h
===================================================================
--- include/clang/Frontend/FrontendOptions.h
+++ include/clang/Frontend/FrontendOptions.h
@@ -88,18 +88,23 @@
/// \brief The kind of input, e.g., C source, AST file, LLVM IR.
InputKind Kind;
+ bool IsHeader;
+
/// \brief Whether we're dealing with a 'system' input (vs. a 'user' input).
bool IsSystem;
public:
FrontendInputFile() : Buffer(nullptr), Kind(IK_None), IsSystem(false) { }
- FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
- : File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { }
- FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind,
+ FrontendInputFile(StringRef File, InputKind Kind, bool IsHeader = false,
bool IsSystem = false)
- : Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { }
+ : File(File.str()), Buffer(nullptr), Kind(Kind), IsHeader(IsHeader)
+ , IsSystem(IsSystem) { }
+ FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind,
+ bool IsHeader = false, bool IsSystem = false)
+ : Buffer(buffer), Kind(Kind), IsHeader(IsHeader), IsSystem(IsSystem) { }
InputKind getKind() const { return Kind; }
+ bool isHeader() const { return IsHeader; }
bool isSystem() const { return IsSystem; }
bool isEmpty() const { return File.empty() && Buffer == nullptr; }
Index: include/clang/Basic/SourceManager.h
===================================================================
--- include/clang/Basic/SourceManager.h
+++ include/clang/Basic/SourceManager.h
@@ -657,6 +657,8 @@
/// \brief The file ID for the main source file of the translation unit.
FileID MainFileID;
+ bool MainFileIsHeader = false;
+
/// \brief The file ID for the precompiled preamble there is one.
FileID PreambleFileID;
@@ -759,6 +761,14 @@
MainFileID = FID;
}
+ void setMainFileHeader(bool mainFileIsHeader) {
+ MainFileIsHeader = mainFileIsHeader;
+ }
+
+ bool isMainFileHeader() const {
+ return MainFileIsHeader;
+ }
+
/// \brief Set the file ID for the precompiled preamble.
void setPreambleFileID(FileID Preamble) {
assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits