summaryrefslogtreecommitdiffstats
path: root/lib/Lex/PPDirectives.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex/PPDirectives.cpp')
-rw-r--r--lib/Lex/PPDirectives.cpp538
1 files changed, 296 insertions, 242 deletions
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index d62a3513c7..5d5cae5fd0 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -1,9 +1,8 @@
//===--- PPDirectives.cpp - Directive Handling for Preprocessor -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
@@ -79,12 +78,18 @@ Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc,
/// Read and discard all tokens remaining on the current line until
/// the tok::eod token is found.
-void Preprocessor::DiscardUntilEndOfDirective() {
+SourceRange Preprocessor::DiscardUntilEndOfDirective() {
Token Tmp;
- do {
- LexUnexpandedToken(Tmp);
+ SourceRange Res;
+
+ LexUnexpandedToken(Tmp);
+ Res.setBegin(Tmp.getLocation());
+ while (Tmp.isNot(tok::eod)) {
assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
- } while (Tmp.isNot(tok::eod));
+ LexUnexpandedToken(Tmp);
+ }
+ Res.setEnd(Tmp.getLocation());
+ return Res;
}
/// Enumerates possible cases of #define/#undef a reserved identifier.
@@ -331,7 +336,10 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
///
/// 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.
-void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) {
+///
+/// Returns the location of the end of the directive.
+SourceLocation Preprocessor::CheckEndOfDirective(const char *DirType,
+ bool EnableMacros) {
Token Tmp;
// Lex unexpanded tokens for most directives: macros might expand to zero
// tokens, causing us to miss diagnosing invalid lines. Some directives (like
@@ -346,18 +354,19 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) {
while (Tmp.is(tok::comment)) // Skip comments in -C mode.
LexUnexpandedToken(Tmp);
- if (Tmp.isNot(tok::eod)) {
- // Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89,
- // or if this is a macro-style preprocessing directive, because it is more
- // trouble than it is worth to insert /**/ and check that there is no /**/
- // in the range also.
- FixItHint Hint;
- if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
- !CurTokenLexer)
- Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//");
- Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
- DiscardUntilEndOfDirective();
- }
+ if (Tmp.is(tok::eod))
+ return Tmp.getLocation();
+
+ // Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89,
+ // or if this is a macro-style preprocessing directive, because it is more
+ // trouble than it is worth to insert /**/ and check that there is no /**/
+ // in the range also.
+ FixItHint Hint;
+ if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
+ !CurTokenLexer)
+ Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//");
+ Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
+ return DiscardUntilEndOfDirective().getEnd();
}
/// SkipExcludedConditionalBlock - We just read a \#if or related directive and
@@ -538,19 +547,19 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) {
DiscardUntilEndOfDirective();
} else {
- const SourceLocation CondBegin = CurPPLexer->getSourceLocation();
// Restore the value of LexingRawMode so that identifiers are
// looked up, etc, inside the #elif expression.
assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
CurPPLexer->LexingRawMode = false;
IdentifierInfo *IfNDefMacro = nullptr;
- const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro).Conditional;
+ DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
+ const bool CondValue = DER.Conditional;
CurPPLexer->LexingRawMode = true;
if (Callbacks) {
- const SourceLocation CondEnd = CurPPLexer->getSourceLocation();
- Callbacks->Elif(Tok.getLocation(),
- SourceRange(CondBegin, CondEnd),
- (CondValue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False), CondInfo.IfLoc);
+ Callbacks->Elif(
+ Tok.getLocation(), DER.ExprRange,
+ (CondValue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False),
+ CondInfo.IfLoc);
}
// If this condition is true, enter it!
if (CondValue) {
@@ -605,9 +614,16 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
SourceLocation Loc) {
assert(M && "no module to include");
+ // If the context is the global module fragment of some module, we never
+ // want to return that file; instead, we want the innermost include-guarded
+ // header that it included.
+ bool InGlobalModuleFragment = M->Kind == Module::GlobalModuleFragment;
+
// If we have a module import syntax, we shouldn't include a header to
// make a particular module visible.
- if (getLangOpts().ObjC)
+ if ((getLangOpts().ObjC || getLangOpts().CPlusPlusModules ||
+ getLangOpts().ModulesTS) &&
+ !InGlobalModuleFragment)
return nullptr;
Module *TopM = M->getTopLevelModule();
@@ -624,6 +640,13 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
if (!FE)
break;
+ if (InGlobalModuleFragment) {
+ if (getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE))
+ return FE;
+ Loc = SM.getIncludeLoc(ID);
+ continue;
+ }
+
bool InTextualHeader = false;
for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) {
if (!Header.getModule()->isSubModuleOf(TopM))
@@ -660,7 +683,8 @@ const FileEntry *Preprocessor::LookupFile(
const DirectoryLookup *FromDir, const FileEntry *FromFile,
const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool SkipCache) {
+ ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
+ bool *IsFrameworkFound, bool SkipCache) {
Module *RequestingModule = getModuleForLocation(FilenameLoc);
bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc);
@@ -718,7 +742,8 @@ const FileEntry *Preprocessor::LookupFile(
while (const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir,
Includers, SearchPath, RelativePath, RequestingModule,
- SuggestedModule, /*IsMapped=*/nullptr, SkipCache)) {
+ SuggestedModule, /*IsMapped=*/nullptr,
+ /*IsFrameworkFound=*/nullptr, SkipCache)) {
// Keep looking as if this file did a #include_next.
TmpFromDir = TmpCurDir;
++TmpFromDir;
@@ -734,8 +759,8 @@ const FileEntry *Preprocessor::LookupFile(
// Do a standard file entry lookup.
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
- RelativePath, RequestingModule, SuggestedModule, IsMapped, SkipCache,
- BuildSystemModule);
+ RelativePath, RequestingModule, SuggestedModule, IsMapped,
+ IsFrameworkFound, SkipCache, BuildSystemModule);
if (FE) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
@@ -822,10 +847,10 @@ void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result,
return HandleIncludeDirective(HashLoc, Result);
}
if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
- Token P = LookAhead(0);
- auto *II = P.getIdentifierInfo();
+ Lex(Result);
+ auto *II = Result.getIdentifierInfo();
if (II && II->getName() == "hdrstop")
- return HandlePragmaDirective(HashLoc, PIK_HashPragma);
+ return HandlePragmaHdrstop(Result);
}
}
DiscardUntilEndOfDirective();
@@ -879,6 +904,8 @@ void Preprocessor::HandleDirective(Token &Result) {
case tok::pp___include_macros:
case tok::pp_pragma:
Diag(Result, diag::err_embedded_directive) << II->getName();
+ Diag(*ArgMacro, diag::note_macro_expansion_here)
+ << ArgMacro->getIdentifierInfo();
DiscardUntilEndOfDirective();
return;
default:
@@ -1116,19 +1143,24 @@ void Preprocessor::HandleLineDirective() {
; // ok
else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_line_invalid_filename);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
} else if (StrTok.hasUDSuffix()) {
Diag(StrTok, diag::err_invalid_string_udl);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
} else {
// Parse and validate the string, converting it into a unique ID.
StringLiteralParser Literal(StrTok, *this);
assert(Literal.isAscii() && "Didn't allow wide strings in");
- if (Literal.hadError)
- return DiscardUntilEndOfDirective();
+ if (Literal.hadError) {
+ DiscardUntilEndOfDirective();
+ return;
+ }
if (Literal.Pascal) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
}
FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
@@ -1261,19 +1293,24 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation());
} else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
} else if (StrTok.hasUDSuffix()) {
Diag(StrTok, diag::err_invalid_string_udl);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
} else {
// Parse and validate the string, converting it into a unique ID.
StringLiteralParser Literal(StrTok, *this);
assert(Literal.isAscii() && "Didn't allow wide strings in");
- if (Literal.hadError)
- return DiscardUntilEndOfDirective();
+ if (Literal.hadError) {
+ DiscardUntilEndOfDirective();
+ return;
+ }
if (Literal.Pascal) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
}
FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
@@ -1343,7 +1380,8 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
if (StrTok.hasUDSuffix()) {
Diag(StrTok, diag::err_invalid_string_udl);
- return DiscardUntilEndOfDirective();
+ DiscardUntilEndOfDirective();
+ return;
}
// Verify that there is nothing after the string, other than EOD.
@@ -1426,6 +1464,14 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
// Get the text form of the filename.
assert(!Buffer.empty() && "Can't have tokens with empty spellings!");
+ // FIXME: Consider warning on some of the cases described in C11 6.4.7/3 and
+ // C++20 [lex.header]/2:
+ //
+ // If `"`, `'`, `\`, `/*`, or `//` appears in a header-name, then
+ // in C: behavior is undefined
+ // in C++: program is conditionally-supported with implementation-defined
+ // semantics
+
// Make sure the filename is <x> or "x".
bool isAngled;
if (Buffer[0] == '<') {
@@ -1460,67 +1506,6 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
return isAngled;
}
-// 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:
-// \code
-// \#define FOO <a/b.h>
-// \#include FOO
-// \endcode
-// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
-//
-// This code concatenates and consumes tokens up to the '>' token. It returns
-// false if the > was found, otherwise it returns true if it finds and consumes
-// the EOD marker.
-bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
- SourceLocation &End) {
- Token CurTok;
-
- Lex(CurTok);
- while (CurTok.isNot(tok::eod)) {
- End = CurTok.getLocation();
-
- // FIXME: Provide code completion for #includes.
- if (CurTok.is(tok::code_completion)) {
- setCodeCompletionReached();
- Lex(CurTok);
- continue;
- }
-
- // Append the spelling of this token to the buffer. If there was a space
- // before it, add it now.
- if (CurTok.hasLeadingSpace())
- FilenameBuffer.push_back(' ');
-
- // Get the spelling of the token, directly into FilenameBuffer if possible.
- size_t PreAppendSize = FilenameBuffer.size();
- FilenameBuffer.resize(PreAppendSize+CurTok.getLength());
-
- const char *BufPtr = &FilenameBuffer[PreAppendSize];
- unsigned ActualLen = getSpelling(CurTok, BufPtr);
-
- // If the token was spelled somewhere else, copy it into FilenameBuffer.
- if (BufPtr != &FilenameBuffer[PreAppendSize])
- memcpy(&FilenameBuffer[PreAppendSize], BufPtr, ActualLen);
-
- // Resize FilenameBuffer to the correct size.
- if (CurTok.getLength() != ActualLen)
- FilenameBuffer.resize(PreAppendSize+ActualLen);
-
- // If we found the '>' marker, return success.
- if (CurTok.is(tok::greater))
- return false;
-
- Lex(CurTok);
- }
-
- // If we hit the eod marker, emit an error and return true so that the caller
- // knows the EOD has been read.
- Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
- return true;
-}
-
/// Push a token onto the token stream containing an annotation.
void Preprocessor::EnterAnnotationToken(SourceRange Range,
tok::TokenKind Kind,
@@ -1542,7 +1527,13 @@ static void diagnoseAutoModuleImport(
Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok,
ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
SourceLocation PathEnd) {
- assert(PP.getLangOpts().ObjC && "no import syntax available");
+ StringRef ImportKeyword;
+ if (PP.getLangOpts().ObjC)
+ ImportKeyword = "@import";
+ else if (PP.getLangOpts().ModulesTS || PP.getLangOpts().CPlusPlusModules)
+ ImportKeyword = "import";
+ else
+ return; // no import syntax available
SmallString<128> PathString;
for (size_t I = 0, N = Path.size(); I != N; ++I) {
@@ -1577,8 +1568,8 @@ static void diagnoseAutoModuleImport(
/*IsTokenRange=*/false);
PP.Diag(HashLoc, diag::warn_auto_module_import)
<< IncludeKind << PathString
- << FixItHint::CreateReplacement(ReplaceRange,
- ("@import " + PathString + ";").str());
+ << FixItHint::CreateReplacement(
+ ReplaceRange, (ImportKeyword + " " + PathString + ";").str());
}
// Given a vector of path components and a string containing the real
@@ -1648,72 +1639,79 @@ bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts,
void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
Token &IncludeTok,
const DirectoryLookup *LookupFrom,
- const FileEntry *LookupFromFile,
- bool isImport) {
+ const FileEntry *LookupFromFile) {
Token FilenameTok;
- CurPPLexer->LexIncludeFilename(FilenameTok);
-
- // Reserve a buffer to get the spelling.
- SmallString<128> FilenameBuffer;
- StringRef Filename;
- SourceLocation End;
- SourceLocation CharEnd; // the end of this directive, in characters
+ if (LexHeaderName(FilenameTok))
+ return;
- switch (FilenameTok.getKind()) {
- case tok::eod:
- // If the token kind is EOD, the error has already been diagnosed.
+ if (FilenameTok.isNot(tok::header_name)) {
+ Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+ if (FilenameTok.isNot(tok::eod))
+ DiscardUntilEndOfDirective();
return;
+ }
- case tok::angle_string_literal:
- case tok::string_literal:
- Filename = getSpelling(FilenameTok, FilenameBuffer);
- End = FilenameTok.getLocation();
- CharEnd = End.getLocWithOffset(FilenameTok.getLength());
- break;
+ // Verify that there is nothing after the filename, other than EOD. Note
+ // that we allow macros that expand to nothing after the filename, because
+ // this falls into the category of "#include pp-tokens new-line" specified
+ // in C99 6.10.2p4.
+ SourceLocation EndLoc =
+ CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getNameStart(), true);
- case tok::less:
- // This could be a <foo/bar.h> file coming from a macro expansion. In this
- // case, glue the tokens together into FilenameBuffer and interpret those.
- FilenameBuffer.push_back('<');
- if (ConcatenateIncludeName(FilenameBuffer, End))
- return; // Found <eod> but no ">"? Diagnostic already emitted.
- Filename = FilenameBuffer;
- CharEnd = End.getLocWithOffset(1);
+ auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
+ EndLoc, LookupFrom, LookupFromFile);
+ switch (Action.Kind) {
+ case ImportAction::None:
+ case ImportAction::SkippedModuleImport:
+ break;
+ case ImportAction::ModuleBegin:
+ EnterAnnotationToken(SourceRange(HashLoc, EndLoc),
+ tok::annot_module_begin, Action.ModuleForHeader);
+ break;
+ case ImportAction::ModuleImport:
+ EnterAnnotationToken(SourceRange(HashLoc, EndLoc),
+ tok::annot_module_include, Action.ModuleForHeader);
break;
- default:
- Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
- DiscardUntilEndOfDirective();
- return;
}
+}
+
+/// Handle either a #include-like directive or an import declaration that names
+/// a header file.
+///
+/// \param HashLoc The location of the '#' token for an include, or
+/// SourceLocation() for an import declaration.
+/// \param IncludeTok The include / include_next / import token.
+/// \param FilenameTok The header-name token.
+/// \param EndLoc The location at which any imported macros become visible.
+/// \param LookupFrom For #include_next, the starting directory for the
+/// directory lookup.
+/// \param LookupFromFile For #include_next, the starting file for the directory
+/// lookup.
+Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
+ SourceLocation HashLoc, Token &IncludeTok, Token &FilenameTok,
+ SourceLocation EndLoc, const DirectoryLookup *LookupFrom,
+ const FileEntry *LookupFromFile) {
+ SmallString<128> FilenameBuffer;
+ StringRef Filename = getSpelling(FilenameTok, FilenameBuffer);
+ SourceLocation CharEnd = FilenameTok.getEndLoc();
CharSourceRange FilenameRange
= CharSourceRange::getCharRange(FilenameTok.getLocation(), CharEnd);
StringRef OriginalFilename = Filename;
bool isAngled =
GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
+
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
// error.
- if (Filename.empty()) {
- DiscardUntilEndOfDirective();
- return;
- }
-
- // Verify that there is nothing after the filename, other than EOD. Note that
- // we allow macros that expand to nothing after the filename, because this
- // falls into the category of "#include pp-tokens new-line" specified in
- // C99 6.10.2p4.
- CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getNameStart(), true);
+ if (Filename.empty())
+ return {ImportAction::None};
- // Check that we don't have infinite #include recursion.
- if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
- Diag(FilenameTok, diag::err_pp_include_too_deep);
- HasReachedMaxIncludeDepth = true;
- return;
- }
+ bool IsImportDecl = HashLoc.isInvalid();
+ SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc;
// Complain about attempts to #include files in an audit pragma.
if (PragmaARCCFCodeAuditedLoc.isValid()) {
- Diag(HashLoc, diag::err_pp_include_in_arc_cf_code_audited);
+ Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
Diag(PragmaARCCFCodeAuditedLoc, diag::note_pragma_entered_here);
// Immediately leave the pragma.
@@ -1722,7 +1720,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Complain about attempts to #include files in an assume-nonnull pragma.
if (PragmaAssumeNonNullLoc.isValid()) {
- Diag(HashLoc, diag::err_pp_include_in_assume_nonnull);
+ Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
// Immediately leave the pragma.
@@ -1740,6 +1738,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Search include directories.
bool IsMapped = false;
+ bool IsFrameworkFound = false;
const DirectoryLookup *CurDir;
SmallString<1024> SearchPath;
SmallString<1024> RelativePath;
@@ -1758,7 +1757,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
isAngled, LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
- &SuggestedModule, &IsMapped);
+ &SuggestedModule, &IsMapped, &IsFrameworkFound);
if (!File) {
if (Callbacks) {
@@ -1775,7 +1774,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
LookupFrom, LookupFromFile, CurDir, nullptr, nullptr,
- &SuggestedModule, &IsMapped, /*SkipCache*/ true);
+ &SuggestedModule, &IsMapped, /*IsFrameworkFound=*/nullptr,
+ /*SkipCache*/ true);
}
}
}
@@ -1790,12 +1790,14 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false,
LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr,
- Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped);
+ Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
+ /*IsFrameworkFound=*/nullptr);
if (File) {
- SourceRange Range(FilenameTok.getLocation(), CharEnd);
- Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal) <<
- Filename <<
- FixItHint::CreateReplacement(Range, "\"" + Filename.str() + "\"");
+ Diag(FilenameTok,
+ diag::err_pp_file_not_found_angled_include_not_fatal)
+ << Filename << IsImportDecl
+ << FixItHint::CreateReplacement(FilenameRange,
+ "\"" + Filename.str() + "\"");
}
}
@@ -1826,14 +1828,15 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
: TypoCorrectionName,
isAngled, LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr,
- Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped);
+ Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
+ /*IsFrameworkFound=*/nullptr);
if (File) {
- SourceRange Range(FilenameTok.getLocation(), CharEnd);
- auto Hint = isAngled
- ? FixItHint::CreateReplacement(
- Range, "<" + TypoCorrectionName.str() + ">")
- : FixItHint::CreateReplacement(
- Range, "\"" + TypoCorrectionName.str() + "\"");
+ auto Hint =
+ isAngled
+ ? FixItHint::CreateReplacement(
+ FilenameRange, "<" + TypoCorrectionName.str() + ">")
+ : FixItHint::CreateReplacement(
+ FilenameRange, "\"" + TypoCorrectionName.str() + "\"");
Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
<< OriginalFilename << TypoCorrectionName << Hint;
// We found the file, so set the Filename to the name after typo
@@ -1843,38 +1846,51 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
}
// If the file is still not found, just go with the vanilla diagnostic
- if (!File)
+ if (!File) {
Diag(FilenameTok, diag::err_pp_file_not_found) << OriginalFilename
<< FilenameRange;
+ if (IsFrameworkFound) {
+ size_t SlashPos = OriginalFilename.find('/');
+ assert(SlashPos != StringRef::npos &&
+ "Include with framework name should have '/' in the filename");
+ StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
+ FrameworkCacheEntry &CacheEntry =
+ HeaderInfo.LookupFrameworkCache(FrameworkName);
+ assert(CacheEntry.Directory && "Found framework should be in cache");
+ Diag(FilenameTok, diag::note_pp_framework_without_header)
+ << OriginalFilename.substr(SlashPos + 1) << FrameworkName
+ << CacheEntry.Directory->getName();
+ }
+ }
}
}
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
if (isPCHThroughHeader(File))
SkippingUntilPCHThroughHeader = false;
- return;
+ return {ImportAction::None};
}
- // Should we enter the source file? Set to false if either the source file is
+ // Should we enter the source file? Set to Skip 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
- // we've imported or already built.
- bool ShouldEnter = true;
+ // if it's got an include guard that is already defined, set to Import if it
+ // is a modular header we've already built and should import.
+ enum { Enter, Import, Skip, IncludeLimitReached } Action = Enter;
if (PPOpts->SingleFileParseMode)
- ShouldEnter = false;
+ Action = IncludeLimitReached;
// If we've reached the max allowed include depth, it is usually due to an
// include cycle. Don't enter already processed files again as it can lead to
// reaching the max allowed include depth again.
- if (ShouldEnter && HasReachedMaxIncludeDepth && File &&
+ if (Action == Enter && HasReachedMaxIncludeDepth && File &&
HeaderInfo.getFileInfo(File).NumIncludes)
- ShouldEnter = false;
+ Action = IncludeLimitReached;
// 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 &&
+ if (Action == Enter && File && SuggestedModule && getLangOpts().Modules &&
!isForModuleBuilding(SuggestedModule.getModule(),
getLangOpts().CurrentModule,
getLangOpts().ModuleName)) {
@@ -1887,7 +1903,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
Diag(FilenameTok.getLocation(),
diag::note_implicit_top_level_module_import_here)
<< SuggestedModule.getModule()->getTopLevelModuleName();
- return;
+ return {ImportAction::None};
}
// Compute the module access path corresponding to this module.
@@ -1900,9 +1916,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
std::reverse(Path.begin(), Path.end());
// Warn that we're replacing the include/import with a module import.
- // We only do this in Objective-C, where we have a module-import syntax.
- if (getLangOpts().ObjC)
- diagnoseAutoModuleImport(*this, HashLoc, IncludeTok, Path, CharEnd);
+ if (!IsImportDecl)
+ diagnoseAutoModuleImport(*this, StartLoc, IncludeTok, Path, CharEnd);
// Load the module to import its macros. We'll make the declarations
// visible when the parser gets here.
@@ -1914,9 +1929,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
assert((Imported == nullptr || Imported == SuggestedModule.getModule()) &&
"the imported module is different than the suggested one");
- if (Imported)
- ShouldEnter = false;
- else if (Imported.isMissingExpected()) {
+ if (Imported) {
+ Action = Import;
+ } else if (Imported.isMissingExpected()) {
// We failed to find a submodule that we assumed would exist (because it
// was in the directory of an umbrella header, for instance), but no
// actual module containing it exists (because the umbrella header is
@@ -1935,7 +1950,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
CurLexer->cutOffLexing();
}
- return;
+ return {ImportAction::None};
}
}
@@ -1947,33 +1962,54 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (File)
FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter);
+ // If this is a '#import' or an import-declaration, don't re-enter the file.
+ //
+ // FIXME: If we have a suggested module for a '#include', and we've already
+ // visited this file, don't bother entering it again. We know it has no
+ // further effect.
+ bool EnterOnce =
+ IsImportDecl ||
+ IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import;
+
// Ask HeaderInfo if we should enter this #include file. If not, #including
// this file will have no effect.
- bool SkipHeader = false;
- if (ShouldEnter && File &&
- !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport,
+ if (Action == Enter && File &&
+ !HeaderInfo.ShouldEnterIncludeFile(*this, File, EnterOnce,
getLangOpts().Modules,
SuggestedModule.getModule())) {
- ShouldEnter = false;
- SkipHeader = true;
+ // Even if we've already preprocessed this header once and know that we
+ // don't need to see its contents again, we still need to import it if it's
+ // modular because we might not have imported it from this submodule before.
+ //
+ // FIXME: We don't do this when compiling a PCH because the AST
+ // serialization layer can't cope with it. This means we get local
+ // submodule visibility semantics wrong in that case.
+ Action = (SuggestedModule && !getLangOpts().CompilingPCH) ? Import : Skip;
}
- if (Callbacks) {
+ if (Callbacks && !IsImportDecl) {
// Notify the callback object that we've seen an inclusion directive.
+ // FIXME: Use a different callback for a pp-import?
Callbacks->InclusionDirective(
HashLoc, IncludeTok,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
FilenameRange, File, SearchPath, RelativePath,
- ShouldEnter ? nullptr : SuggestedModule.getModule(), FileCharacter);
- if (SkipHeader && !SuggestedModule.getModule())
+ Action == Import ? SuggestedModule.getModule() : nullptr,
+ FileCharacter);
+ if (Action == Skip)
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
}
if (!File)
- return;
+ return {ImportAction::None};
- // FIXME: If we have a suggested module, and we've already visited this file,
- // don't bother entering it again. We know it has no further effect.
+ // If this is a C++20 pp-import declaration, diagnose if we didn't find any
+ // module corresponding to the named header.
+ if (IsImportDecl && !SuggestedModule) {
+ Diag(FilenameTok, diag::err_header_import_not_header_unit)
+ << OriginalFilename << File->getName();
+ return {ImportAction::None};
+ }
// Issue a diagnostic if the name of the file on disk has a different case
// than the one we're about to open.
@@ -2005,37 +2041,50 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// For other system headers, we don't. They can be controlled separately.
auto DiagId = (FileCharacter == SrcMgr::C_User || warnByDefaultOnWrongCase(Name)) ?
diag::pp_nonportable_path : diag::pp_nonportable_system_path;
- SourceRange Range(FilenameTok.getLocation(), CharEnd);
Diag(FilenameTok, DiagId) << Path <<
- FixItHint::CreateReplacement(Range, Path);
+ FixItHint::CreateReplacement(FilenameRange, Path);
}
}
- // If we don't need to enter the file, stop now.
- if (!ShouldEnter) {
+ switch (Action) {
+ case Skip:
+ // If we don't need to enter the file, stop now.
+ if (Module *M = SuggestedModule.getModule())
+ return {ImportAction::SkippedModuleImport, M};
+ return {ImportAction::None};
+
+ case IncludeLimitReached:
+ // If we reached our include limit and don't want to enter any more files,
+ // don't go any further.
+ return {ImportAction::None};
+
+ case Import: {
// If this is a module import, make it visible if needed.
- if (auto *M = SuggestedModule.getModule()) {
- // When building a pch, -fmodule-name tells the compiler to textually
- // include headers in the specified module. But it is possible that
- // ShouldEnter is false because we are skipping the header. In that
- // case, We are not importing the specified module.
- if (SkipHeader && getLangOpts().CompilingPCH &&
- isForModuleBuilding(M, getLangOpts().CurrentModule,
- getLangOpts().ModuleName))
- return;
+ Module *M = SuggestedModule.getModule();
+ assert(M && "no module to import");
- makeModuleVisible(M, HashLoc);
+ makeModuleVisible(M, EndLoc);
- if (IncludeTok.getIdentifierInfo()->getPPKeywordID() !=
- tok::pp___include_macros)
- EnterAnnotationToken(SourceRange(HashLoc, End),
- tok::annot_module_include, M);
- }
- return;
+ if (IncludeTok.getIdentifierInfo()->getPPKeywordID() ==
+ tok::pp___include_macros)
+ return {ImportAction::None};
+
+ return {ImportAction::ModuleImport, M};
+ }
+
+ case Enter:
+ break;
+ }
+
+ // Check that we don't have infinite #include recursion.
+ if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
+ Diag(FilenameTok, diag::err_pp_include_too_deep);
+ HasReachedMaxIncludeDepth = true;
+ return {ImportAction::None};
}
// Look up the file, create a File ID for it.
- SourceLocation IncludePos = End;
+ SourceLocation IncludePos = FilenameTok.getLocation();
// 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())
@@ -2045,7 +2094,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// If all is good, enter the new file!
if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation()))
- return;
+ return {ImportAction::None};
// Determine if we're switching to building a new submodule, and which one.
if (auto *M = SuggestedModule.getModule()) {
@@ -2056,29 +2105,37 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
<< M->getFullModuleName();
Diag(M->getTopLevelModule()->ShadowingModule->DefinitionLoc,
diag::note_previous_definition);
- return;
+ return {ImportAction::None};
}
// When building a pch, -fmodule-name tells the compiler to textually
// include headers in the specified module. We are not building the
// specified module.
+ //
+ // FIXME: This is the wrong way to handle this. We should produce a PCH
+ // that behaves the same as the header would behave in a compilation using
+ // that PCH, which means we should enter the submodule. We need to teach
+ // the AST serialization layer to deal with the resulting AST.
if (getLangOpts().CompilingPCH &&
isForModuleBuilding(M, getLangOpts().CurrentModule,
getLangOpts().ModuleName))
- return;
+ return {ImportAction::None};
assert(!CurLexerSubmodule && "should not have marked this as a module yet");
CurLexerSubmodule = M;
// Let the macro handling code know that any future macros are within
// the new submodule.
- EnterSubmodule(M, HashLoc, /*ForPragma*/false);
+ EnterSubmodule(M, EndLoc, /*ForPragma*/false);
// Let the parser know that any future declarations are within the new
// submodule.
// FIXME: There's no point doing this if we're handling a #__include_macros
// directive.
- EnterAnnotationToken(SourceRange(HashLoc, End), tok::annot_module_begin, M);
+ return {ImportAction::ModuleBegin, M};
}
+
+ assert(!IsImportDecl && "failed to diagnose missing module for import decl");
+ return {ImportAction::None};
}
/// HandleIncludeNextDirective - Implements \#include_next.
@@ -2106,6 +2163,10 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,
LookupFromFile = CurPPLexer->getFileEntry();
Lookup = nullptr;
} else if (!Lookup) {
+ // The current file was not found by walking the include path. Either it
+ // is the primary file (handled above), or it was found by absolute path,
+ // or it was found relative to such a file.
+ // FIXME: Track enough information so we know which case we're in.
Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
} else {
// Start looking up in the next directory.
@@ -2139,7 +2200,7 @@ void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
return HandleMicrosoftImportDirective(ImportTok);
Diag(ImportTok, diag::ext_pp_import_directive);
}
- return HandleIncludeDirective(HashLoc, ImportTok, nullptr, nullptr, true);
+ return HandleIncludeDirective(HashLoc, ImportTok);
}
/// HandleIncludeMacrosDirective - The -imacros command line option turns into a
@@ -2198,8 +2259,7 @@ bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
// OpenCL v1.2 s6.9.e: variadic macros are not supported.
if (LangOpts.OpenCL) {
- Diag(Tok, diag::err_pp_opencl_variadic_macros);
- return true;
+ Diag(Tok, diag::ext_pp_opencl_variadic_macros);
}
// Lex the token after the identifier.
@@ -2228,8 +2288,7 @@ bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
// If this is already used as a parameter, it is used multiple times (e.g.
// #define X(A,A.
- if (std::find(Parameters.begin(), Parameters.end(), II) !=
- Parameters.end()) { // C99 6.10.3p6
+ if (llvm::find(Parameters, II) != Parameters.end()) { // C99 6.10.3p6
Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
return true;
}
@@ -2791,10 +2850,8 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
// Parse and evaluate the conditional expression.
IdentifierInfo *IfNDefMacro = nullptr;
- const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
const bool ConditionalTrue = DER.Conditional;
- const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
// If this condition is equivalent to #ifndef X, and if this is the first
// directive seen, handle it for the multiple-include optimization.
@@ -2807,9 +2864,9 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
}
if (Callbacks)
- Callbacks->If(IfToken.getLocation(),
- SourceRange(ConditionalBegin, ConditionalEnd),
- (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
+ Callbacks->If(
+ IfToken.getLocation(), DER.ExprRange,
+ (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
// Should we include the stuff contained by this directive?
if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
@@ -2902,9 +2959,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken,
// #elif directive in a non-skipping conditional... start skipping.
// We don't care what the condition is, because we will always skip it (since
// the block immediately before it was included).
- const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
- DiscardUntilEndOfDirective();
- const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
+ SourceRange ConditionRange = DiscardUntilEndOfDirective();
PPConditionalInfo CI;
if (CurPPLexer->popConditionalLevel(CI)) {
@@ -2920,8 +2975,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken,
if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else);
if (Callbacks)
- Callbacks->Elif(ElifToken.getLocation(),
- SourceRange(ConditionalBegin, ConditionalEnd),
+ Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {