summaryrefslogtreecommitdiff
path: root/lib/Lex/PPDirectives.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex/PPDirectives.cpp')
-rw-r--r--lib/Lex/PPDirectives.cpp124
1 files changed, 101 insertions, 23 deletions
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index ca3e70fd1060..d8dae73037a8 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Implements # directive processing for the Preprocessor.
+/// Implements # directive processing for the Preprocessor.
///
//===----------------------------------------------------------------------===//
@@ -78,7 +78,7 @@ Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc,
return new (BP) VisibilityMacroDirective(Loc, isPublic);
}
-/// \brief Read and discard all tokens remaining on the current line until
+/// Read and discard all tokens remaining on the current line until
/// the tok::eod token is found.
void Preprocessor::DiscardUntilEndOfDirective() {
Token Tmp;
@@ -88,14 +88,14 @@ void Preprocessor::DiscardUntilEndOfDirective() {
} while (Tmp.isNot(tok::eod));
}
-/// \brief Enumerates possible cases of #define/#undef a reserved identifier.
+/// Enumerates possible cases of #define/#undef a reserved identifier.
enum MacroDiag {
MD_NoWarn, //> Not a reserved identifier
MD_KeywordDef, //> Macro hides keyword, enabled by default
MD_ReservedMacro //> #define of #undef reserved id, disabled by default
};
-/// \brief Checks if the specified identifier is reserved in the specified
+/// Checks if the specified identifier is reserved in the specified
/// language.
/// This function does not check if the identifier is a keyword.
static bool isReservedId(StringRef Text, const LangOptions &Lang) {
@@ -115,6 +115,25 @@ static bool isReservedId(StringRef Text, const LangOptions &Lang) {
return false;
}
+// The -fmodule-name option tells the compiler to textually include headers in
+// the specified module, meaning clang won't build the specified module. This is
+// useful in a number of situations, for instance, when building a library that
+// vends a module map, one might want to avoid hitting intermediate build
+// products containig the the module map or avoid finding the system installed
+// modulemap for that library.
+static bool isForModuleBuilding(Module *M, StringRef CurrentModule,
+ StringRef ModuleName) {
+ StringRef TopLevelName = M->getTopLevelModuleName();
+
+ // When building framework Foo, we wanna make sure that Foo *and* Foo_Private
+ // are textually included and no modules are built for both.
+ if (M->getTopLevelModule()->IsFramework && CurrentModule == ModuleName &&
+ !CurrentModule.endswith("_Private") && TopLevelName.endswith("_Private"))
+ TopLevelName = TopLevelName.drop_back(8);
+
+ return TopLevelName == CurrentModule;
+}
+
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
const LangOptions &Lang = PP.getLangOpts();
StringRef Text = II->getName();
@@ -277,7 +296,7 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
return false;
}
-/// \brief Lex and validate a macro name, which occurs after a
+/// Lex and validate a macro name, which occurs after a
/// \#define or \#undef.
///
/// This sets the token kind to eod and discards the rest of the macro line if
@@ -309,7 +328,7 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
}
}
-/// \brief Ensure that the next token is a tok::eod token.
+/// Ensure that the next token is a tok::eod token.
///
/// If not, emit a diagnostic and consume up until the eod. If EnableMacros is
/// true, then we consider macros that expand to zero tokens as being ok.
@@ -558,7 +577,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
// the #if block.
CurPPLexer->LexingRawMode = false;
- if (Callbacks)
+ // The last skipped range isn't actually skipped yet if it's truncated
+ // by the end of the preamble; we'll resume parsing after the preamble.
+ if (Callbacks && (Tok.isNot(tok::eof) || !isRecordingPreamble()))
Callbacks->SourceRangeSkipped(
SourceRange(HashTokenLoc, CurPPLexer->getSourceLocation()),
Tok.getLocation());
@@ -866,6 +887,22 @@ private:
bool save;
};
+/// Process a directive while looking for the through header.
+/// Only #include (to check if it is the through header) and #define (to warn
+/// about macros that don't match the PCH) are handled. All other directives
+/// are completely discarded.
+void Preprocessor::HandleSkippedThroughHeaderDirective(Token &Result,
+ SourceLocation HashLoc) {
+ if (const IdentifierInfo *II = Result.getIdentifierInfo()) {
+ if (II->getPPKeywordID() == tok::pp_include)
+ return HandleIncludeDirective(HashLoc, Result);
+ if (II->getPPKeywordID() == tok::pp_define)
+ return HandleDefineDirective(Result,
+ /*ImmediatelyAfterHeaderGuard=*/false);
+ }
+ DiscardUntilEndOfDirective();
+}
+
/// HandleDirective - This callback is invoked when the lexer sees a # token
/// at the start of a line. This consumes the directive, modifies the
/// lexer/preprocessor state, and advances the lexer(s) so that the next token
@@ -927,6 +964,9 @@ void Preprocessor::HandleDirective(Token &Result) {
// and reset to previous state when returning from this function.
ResetMacroExpansionHelper helper(this);
+ if (SkippingUntilPCHThroughHeader)
+ return HandleSkippedThroughHeaderDirective(Result, SavedHash.getLocation());
+
switch (Result.getKind()) {
case tok::eod:
return; // null directive.
@@ -1107,7 +1147,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val,
return false;
}
-/// \brief Handle a \#line directive: C99 6.10.4.
+/// Handle a \#line directive: C99 6.10.4.
///
/// The two acceptable forms are:
/// \verbatim
@@ -1343,7 +1383,7 @@ void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
// Read the rest of the line raw. We do this because we don't want macros
// to be expanded and we don't require that the tokens be valid preprocessing
// tokens. For example, this is allowed: "#warning ` 'foo". GCC does
- // collapse multiple consequtive white space between tokens, but this isn't
+ // collapse multiple consecutive white space between tokens, but this isn't
// specified by the standard.
SmallString<128> Message;
CurLexer->ReadToEndOfLine(&Message);
@@ -1393,7 +1433,7 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
}
}
-/// \brief Handle a #public directive.
+/// Handle a #public directive.
void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
Token MacroNameTok;
ReadMacroName(MacroNameTok, MU_Undef);
@@ -1420,7 +1460,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
MacroNameTok.getLocation(), /*IsPublic=*/true));
}
-/// \brief Handle a #private directive.
+/// Handle a #private directive.
void Preprocessor::HandleMacroPrivateDirective() {
Token MacroNameTok;
ReadMacroName(MacroNameTok, MU_Undef);
@@ -1496,7 +1536,7 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
return isAngled;
}
-// \brief Handle cases where the \#include name is expanded from a macro
+// Handle cases where the \#include name is expanded from a macro
// as multiple tokens, which need to be glued together.
//
// This occurs for code like:
@@ -1557,7 +1597,7 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
return true;
}
-/// \brief Push a token onto the token stream containing an annotation.
+/// Push a token onto the token stream containing an annotation.
void Preprocessor::EnterAnnotationToken(SourceRange Range,
tok::TokenKind Kind,
void *AnnotationVal) {
@@ -1572,7 +1612,7 @@ void Preprocessor::EnterAnnotationToken(SourceRange Range,
EnterTokenStream(std::move(Tok), 1, true);
}
-/// \brief Produce a diagnostic informing the user that a #include or similar
+/// Produce a diagnostic informing the user that a #include or similar
/// was implicitly treated as a module import.
static void diagnoseAutoModuleImport(
Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok,
@@ -1655,12 +1695,18 @@ bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts,
DiagnosticsEngine &Diags, Module *M) {
Module::Requirement Requirement;
Module::UnresolvedHeaderDirective MissingHeader;
- if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader))
+ Module *ShadowingModule = nullptr;
+ if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader,
+ ShadowingModule))
return false;
if (MissingHeader.FileNameLoc.isValid()) {
Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
<< MissingHeader.IsUmbrella << MissingHeader.FileName;
+ } else if (ShadowingModule) {
+ Diags.Report(M->DefinitionLoc, diag::err_module_shadowed) << M->Name;
+ Diags.Report(ShadowingModule->DefinitionLoc,
+ diag::note_previous_definition);
} else {
// FIXME: Track the location at which the requirement was specified, and
// use it here.
@@ -1779,7 +1825,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
SmallString<128> NormalizedPath;
if (LangOpts.MSVCCompat) {
NormalizedPath = Filename.str();
-#ifndef LLVM_ON_WIN32
+#ifndef _WIN32
llvm::sys::path::native(NormalizedPath);
#endif
}
@@ -1835,6 +1881,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
}
}
+ if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
+ if (isPCHThroughHeader(File))
+ SkippingUntilPCHThroughHeader = false;
+ return;
+ }
+
// Should we enter the source file? Set to false if either the source file is
// known to have no effect beyond its effect on module visibility -- that is,
// if it's got an include guard that is already defined or is a modular header
@@ -1844,12 +1896,19 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (PPOpts->SingleFileParseMode)
ShouldEnter = false;
+ // Any diagnostics after the fatal error will not be visible. As the
+ // compilation failed already and errors in subsequently included files won't
+ // be visible, avoid preprocessing those files.
+ if (ShouldEnter && Diags->hasFatalErrorOccurred())
+ ShouldEnter = false;
+
// Determine whether we should try to import the module for this #include, if
// there is one. Don't do so if precompiled module support is disabled or we
// are processing this module textually (because we're building the module).
if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules &&
- SuggestedModule.getModule()->getTopLevelModuleName() !=
- getLangOpts().CurrentModule) {
+ !isForModuleBuilding(SuggestedModule.getModule(),
+ getLangOpts().CurrentModule,
+ getLangOpts().ModuleName)) {
// If this include corresponds to a module but that module is
// unavailable, diagnose the situation and bail out.
// FIXME: Remove this; loadModule does the same check (but produces
@@ -1940,7 +1999,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
HashLoc, IncludeTok,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
FilenameRange, File, SearchPath, RelativePath,
- ShouldEnter ? nullptr : SuggestedModule.getModule());
+ ShouldEnter ? nullptr : SuggestedModule.getModule(), FileCharacter);
if (SkipHeader && !SuggestedModule.getModule())
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
}
@@ -1996,7 +2055,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// ShouldEnter is false because we are skipping the header. In that
// case, We are not importing the specified module.
if (SkipHeader && getLangOpts().CompilingPCH &&
- M->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ isForModuleBuilding(M, getLangOpts().CurrentModule,
+ getLangOpts().ModuleName))
return;
makeModuleVisible(M, HashLoc);
@@ -2014,7 +2074,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// If the filename string was the result of macro expansions, set the include
// position on the file where it will be included and after the expansions.
if (IncludePos.isMacroID())
- IncludePos = SourceMgr.getExpansionRange(IncludePos).second;
+ IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd();
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
assert(FID.isValid() && "Expected valid file ID");
@@ -2024,11 +2084,21 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Determine if we're switching to building a new submodule, and which one.
if (auto *M = SuggestedModule.getModule()) {
+ if (M->getTopLevelModule()->ShadowingModule) {
+ // We are building a submodule that belongs to a shadowed module. This
+ // means we find header files in the shadowed module.
+ Diag(M->DefinitionLoc, diag::err_module_build_shadowed_submodule)
+ << M->getFullModuleName();
+ Diag(M->getTopLevelModule()->ShadowingModule->DefinitionLoc,
+ diag::note_previous_definition);
+ return;
+ }
// When building a pch, -fmodule-name tells the compiler to textually
// include headers in the specified module. We are not building the
// specified module.
if (getLangOpts().CompilingPCH &&
- M->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ isForModuleBuilding(M, getLangOpts().CurrentModule,
+ getLangOpts().ModuleName))
return;
assert(!CurLexerSubmodule && "should not have marked this as a module yet");
@@ -2548,7 +2618,15 @@ void Preprocessor::HandleDefineDirective(
}
}
-
+ // When skipping just warn about macros that do not match.
+ if (SkippingUntilPCHThroughHeader) {
+ const MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo());
+ if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this,
+ /*Syntactic=*/LangOpts.MicrosoftExt))
+ Diag(MI->getDefinitionLoc(), diag::warn_pp_macro_def_mismatch_with_pch)
+ << MacroNameTok.getIdentifierInfo();
+ return;
+ }
// Finally, if this identifier already had a macro defined for it, verify that
// the macro bodies are identical, and issue diagnostics if they are not.