Revert "[ObjC][Preprocessor] Handle @import directive as a pp-directive" (#188806)
Reverts llvm/llvm-project#157726 This is causing a number of lldb test failures, specifically tests that do `@import ...` expression evaluation. See https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/as-lldb-cmake/
This commit is contained in:
parent
b51dfdec47
commit
e93c18ca2a
@ -503,7 +503,7 @@ def warn_cxx98_compat_variadic_macro : Warning<
|
||||
InGroup<CXX98CompatPedantic>, DefaultIgnore;
|
||||
def ext_named_variadic_macro : Extension<
|
||||
"named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
|
||||
def err_embedded_directive : Error<"embedding a %select{|#}0%1 directive "
|
||||
def err_embedded_directive : Error<"embedding a %select{#|C++ }0%1 directive "
|
||||
"within macro arguments is not supported">;
|
||||
def ext_embedded_directive : Extension<
|
||||
"embedding a directive within macro arguments has undefined behavior">,
|
||||
|
||||
@ -168,10 +168,13 @@ class CompilerInstance : public ModuleLoader {
|
||||
/// Should we delete the BuiltModules when we're done?
|
||||
bool DeleteBuiltModules = true;
|
||||
|
||||
/// Cache of module import results keyed by import location.
|
||||
/// It is important to eliminate redundant diagnostics
|
||||
/// when both the preprocessor and parser see the same import declaration.
|
||||
llvm::SmallDenseMap<SourceLocation, ModuleLoadResult, 4> ModuleImportResults;
|
||||
/// The location of the module-import keyword for the last module
|
||||
/// import.
|
||||
SourceLocation LastModuleImportLoc;
|
||||
|
||||
/// The result of the last module import.
|
||||
///
|
||||
ModuleLoadResult LastModuleImportResult;
|
||||
|
||||
/// Whether we should (re)build the global module index once we
|
||||
/// have finished with this translation unit.
|
||||
|
||||
@ -381,6 +381,12 @@ private:
|
||||
llvm::DenseMap<FileID, SmallVector<const char *>> CheckPoints;
|
||||
unsigned CheckPointCounter = 0;
|
||||
|
||||
/// Whether the import is an `@import` or a standard c++ modules import.
|
||||
bool IsAtImport = false;
|
||||
|
||||
/// Whether the last token we lexed was an '@'.
|
||||
bool LastTokenWasAt = false;
|
||||
|
||||
/// Whether we're importing a standard C++20 named Modules.
|
||||
bool ImportingCXXNamedModules = false;
|
||||
|
||||
@ -1851,6 +1857,7 @@ public:
|
||||
return FirstPPTokenLoc;
|
||||
}
|
||||
|
||||
bool LexAfterModuleImport(Token &Result);
|
||||
void CollectPPImportSuffix(SmallVectorImpl<Token> &Toks,
|
||||
bool StopUntilEOD = false);
|
||||
bool CollectPPImportSuffixAndEnterStream(SmallVectorImpl<Token> &Toks,
|
||||
@ -2907,7 +2914,6 @@ private:
|
||||
void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
|
||||
void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
|
||||
void HandleMicrosoftImportDirective(Token &Tok);
|
||||
void HandleObjCImportDirective(Token &AtTok, Token &ImportTok);
|
||||
|
||||
public:
|
||||
/// Check that the given module is available, producing a diagnostic if not.
|
||||
@ -3171,6 +3177,9 @@ private:
|
||||
static bool CLK_DependencyDirectivesLexer(Preprocessor &P, Token &Result) {
|
||||
return P.CurLexer->LexDependencyDirectiveToken(Result);
|
||||
}
|
||||
static bool CLK_LexAfterModuleImport(Preprocessor &P, Token &Result) {
|
||||
return P.LexAfterModuleImport(Result);
|
||||
}
|
||||
};
|
||||
|
||||
/// Abstract base class that describes a handler that will receive
|
||||
|
||||
@ -985,8 +985,6 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
|
||||
if (hasSourceManager() && !Act.isModelParsingAction())
|
||||
getSourceManager().clearIDTables();
|
||||
|
||||
ModuleImportResults.clear();
|
||||
|
||||
if (Act.BeginSourceFile(*this, FIF)) {
|
||||
if (llvm::Error Err = Act.Execute()) {
|
||||
consumeError(std::move(Err)); // FIXME this drops errors on the floor.
|
||||
@ -1982,15 +1980,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
||||
SourceLocation ModuleNameLoc = Path[0].getLoc();
|
||||
|
||||
// If we've already handled this import, just return the cached result.
|
||||
// This cache eliminates redundant diagnostics when both the preprocessor
|
||||
// and parser see the same import declaration.
|
||||
if (ImportLoc.isValid()) {
|
||||
auto CacheIt = ModuleImportResults.find(ImportLoc);
|
||||
if (CacheIt != ModuleImportResults.end()) {
|
||||
if (CacheIt->second && ModuleName != getLangOpts().CurrentModule)
|
||||
TheASTReader->makeModuleVisible(CacheIt->second, Visibility, ImportLoc);
|
||||
return CacheIt->second;
|
||||
}
|
||||
// This one-element cache is important to eliminate redundant diagnostics
|
||||
// when both the preprocessor and parser see the same import declaration.
|
||||
if (ImportLoc.isValid() && LastModuleImportLoc == ImportLoc) {
|
||||
// Make the named module visible.
|
||||
if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule)
|
||||
TheASTReader->makeModuleVisible(LastModuleImportResult, Visibility,
|
||||
ImportLoc);
|
||||
return LastModuleImportResult;
|
||||
}
|
||||
|
||||
// If we don't already have information on this module, load the module now.
|
||||
@ -2166,7 +2163,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
||||
*Module, getDiagnostics())) {
|
||||
getDiagnostics().Report(ImportLoc, diag::note_module_import_here)
|
||||
<< SourceRange(Path.front().getLoc(), Path.back().getLoc());
|
||||
ModuleImportResults[ImportLoc] = ModuleLoadResult();
|
||||
LastModuleImportLoc = ImportLoc;
|
||||
LastModuleImportResult = ModuleLoadResult();
|
||||
return ModuleLoadResult();
|
||||
}
|
||||
|
||||
@ -2179,8 +2177,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
||||
.getModuleMap()
|
||||
.resolveLinkAsDependencies(Module->getTopLevelModule());
|
||||
|
||||
ModuleImportResults[ImportLoc] = ModuleLoadResult(Module);
|
||||
return ModuleLoadResult(Module);
|
||||
LastModuleImportLoc = ImportLoc;
|
||||
LastModuleImportResult = ModuleLoadResult(Module);
|
||||
return LastModuleImportResult;
|
||||
}
|
||||
|
||||
void CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
|
||||
|
||||
@ -582,12 +582,15 @@ bool Scanner::lexModuleDirectiveBody(DirectiveKind Kind, const char *&First,
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &Tok = lexToken(First, End);
|
||||
pushDirective(Kind);
|
||||
if (Tok.is(tok::eof) || Tok.is(tok::eod))
|
||||
skipWhitespace(First, End);
|
||||
if (First == End)
|
||||
return false;
|
||||
return reportError(DirectiveLoc,
|
||||
diag::err_dep_source_scanner_unexpected_tokens_at_import);
|
||||
if (!isVerticalWhitespace(*First))
|
||||
return reportError(
|
||||
DirectiveLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import);
|
||||
skipNewline(First, End);
|
||||
return false;
|
||||
}
|
||||
|
||||
dependency_directives_scan::Token &Scanner::lexToken(const char *&First,
|
||||
@ -949,6 +952,10 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) {
|
||||
CurDirToks.clear();
|
||||
});
|
||||
|
||||
// FIXME: Shoule we handle @import as a preprocessing directive?
|
||||
if (*First == '@')
|
||||
return lexAt(First, End);
|
||||
|
||||
bool IsPreprocessedModule =
|
||||
isStartWithPreprocessedModuleDirective(First, End);
|
||||
if (*First == '_' && !IsPreprocessedModule) {
|
||||
@ -963,9 +970,6 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) {
|
||||
llvm::scope_exit ScEx2(
|
||||
[&]() { TheLexer.setParsingPreprocessorDirective(false); });
|
||||
|
||||
if (*First == '@')
|
||||
return lexAt(First, End);
|
||||
|
||||
// Handle module directives for C++20 modules.
|
||||
if (*First == 'i' || *First == 'e' || *First == 'm' || IsPreprocessedModule)
|
||||
return lexModule(First, End);
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
#include "llvm/Support/MemoryBufferRef.h"
|
||||
#include "llvm/Support/NativeFormatting.h"
|
||||
#include "llvm/Support/SaveAndRestore.h"
|
||||
#include "llvm/Support/Unicode.h"
|
||||
#include "llvm/Support/UnicodeCharRanges.h"
|
||||
#include <algorithm>
|
||||
@ -4449,28 +4448,9 @@ LexStart:
|
||||
|
||||
case '@':
|
||||
// Objective C support.
|
||||
if (CurPtr[-1] == '@' && LangOpts.ObjC) {
|
||||
FormTokenWithChars(Result, CurPtr, tok::at);
|
||||
if (PP && Result.isAtPhysicalStartOfLine() && !LexingRawMode &&
|
||||
!Is_PragmaLexer) {
|
||||
Token NextPPTok;
|
||||
NextPPTok.startToken();
|
||||
{
|
||||
llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
|
||||
this->ParsingPreprocessorDirective, true);
|
||||
auto NextTokOr = peekNextPPToken();
|
||||
if (NextTokOr.has_value()) {
|
||||
NextPPTok = *NextTokOr;
|
||||
}
|
||||
}
|
||||
if (NextPPTok.is(tok::raw_identifier) &&
|
||||
NextPPTok.getRawIdentifier() == "import") {
|
||||
PP->HandleDirective(Result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
if (CurPtr[-1] == '@' && LangOpts.ObjC)
|
||||
Kind = tok::at;
|
||||
else
|
||||
Kind = tok::unknown;
|
||||
break;
|
||||
|
||||
@ -4632,16 +4612,6 @@ bool Lexer::LexDependencyDirectiveToken(Token &Result) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (Result.is(tok::at) && Result.isAtStartOfLine()) {
|
||||
auto NextTok = peekNextPPToken();
|
||||
if (NextTok && NextTok->is(tok::raw_identifier) &&
|
||||
NextTok->getRawIdentifier() == "import") {
|
||||
PP->HandleDirective(Result);
|
||||
if (PP->hadModuleLoaderFatalFailure())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (Result.is(tok::raw_identifier)) {
|
||||
Result.setRawIdentifierData(TokPtr);
|
||||
if (!isLexingRawMode()) {
|
||||
|
||||
@ -1313,9 +1313,9 @@ void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result,
|
||||
void Preprocessor::HandleDirective(Token &Result) {
|
||||
// FIXME: Traditional: # with whitespace before it not recognized by K&R?
|
||||
|
||||
// We just parsed a # or @ character at the start of a line, so we're in
|
||||
// directive mode. Tell the lexer this so any newlines we see will be
|
||||
// converted into an EOD token (which terminates the directive).
|
||||
// We just parsed a # character at the start of a line, so we're in directive
|
||||
// mode. Tell the lexer this so any newlines we see will be converted into an
|
||||
// EOD token (which terminates the directive).
|
||||
CurPPLexer->ParsingPreprocessorDirective = true;
|
||||
if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
|
||||
|
||||
@ -1330,13 +1330,13 @@ void Preprocessor::HandleDirective(Token &Result) {
|
||||
// pp-directive.
|
||||
bool ReadAnyTokensBeforeDirective =CurPPLexer->MIOpt.getHasReadAnyTokensVal();
|
||||
|
||||
// Save the directive-introducing token ('#', '@', or import/module in C++20)
|
||||
// in case we need to return it later.
|
||||
// Save the directive-introducing token('#' and import/module in C++20) in
|
||||
// case we need to return it later.
|
||||
Token Introducer = Result;
|
||||
|
||||
// Read the next token, the directive flavor. This isn't expanded due to
|
||||
// C99 6.10.3p8.
|
||||
if (Introducer.isOneOf(tok::hash, tok::at))
|
||||
if (Introducer.is(tok::hash))
|
||||
LexUnexpandedToken(Result);
|
||||
|
||||
// C99 6.10.3p11: Is this preprocessor directive in macro invocation? e.g.:
|
||||
@ -1360,7 +1360,10 @@ void Preprocessor::HandleDirective(Token &Result) {
|
||||
case tok::pp___preprocessed_module:
|
||||
case tok::pp___preprocessed_import:
|
||||
Diag(Result, diag::err_embedded_directive)
|
||||
<< Introducer.is(tok::hash) << II->getName();
|
||||
<< (getLangOpts().CPlusPlusModules &&
|
||||
Introducer.isModuleContextualKeyword(
|
||||
/*AllowExport=*/false))
|
||||
<< II->getName();
|
||||
Diag(*ArgMacro, diag::note_macro_expansion_here)
|
||||
<< ArgMacro->getIdentifierInfo();
|
||||
DiscardUntilEndOfDirective();
|
||||
@ -1461,16 +1464,11 @@ void Preprocessor::HandleDirective(Token &Result) {
|
||||
return HandleCXXImportDirective(Result);
|
||||
// GNU Extensions.
|
||||
case tok::pp_import:
|
||||
switch (Introducer.getKind()) {
|
||||
case tok::hash:
|
||||
return HandleImportDirective(Introducer.getLocation(), Result);
|
||||
case tok::at:
|
||||
return HandleObjCImportDirective(Introducer, Result);
|
||||
case tok::kw_import:
|
||||
if (getLangOpts().CPlusPlusModules &&
|
||||
Introducer.isModuleContextualKeyword(
|
||||
/*AllowExport=*/false))
|
||||
return HandleCXXImportDirective(Result);
|
||||
default:
|
||||
llvm_unreachable("not a valid import directive");
|
||||
}
|
||||
return HandleImportDirective(Introducer.getLocation(), Result);
|
||||
case tok::pp_include_next:
|
||||
return HandleIncludeNextDirective(Introducer.getLocation(), Result);
|
||||
|
||||
@ -4194,6 +4192,9 @@ void Preprocessor::HandleCXXImportDirective(Token ImportTok) {
|
||||
llvm::SaveAndRestore<bool> SaveImportingCXXModules(
|
||||
this->ImportingCXXNamedModules, true);
|
||||
|
||||
if (LastExportKeyword.is(tok::kw_export))
|
||||
LastExportKeyword.startToken();
|
||||
|
||||
Token Tok;
|
||||
if (LexHeaderName(Tok)) {
|
||||
if (Tok.isNot(tok::eod))
|
||||
@ -4334,7 +4335,13 @@ void Preprocessor::HandleCXXImportDirective(Token ImportTok) {
|
||||
/// The lexed module name are replaced by annot_module_name token.
|
||||
void Preprocessor::HandleCXXModuleDirective(Token ModuleTok) {
|
||||
assert(getLangOpts().CPlusPlusModules && ModuleTok.is(tok::kw_module));
|
||||
SourceLocation StartLoc = ModuleTok.getLocation();
|
||||
Token Introducer = ModuleTok;
|
||||
if (LastExportKeyword.is(tok::kw_export)) {
|
||||
Introducer = LastExportKeyword;
|
||||
LastExportKeyword.startToken();
|
||||
}
|
||||
|
||||
SourceLocation StartLoc = Introducer.getLocation();
|
||||
|
||||
Token Tok;
|
||||
SourceLocation UseLoc = ModuleTok.getLocation();
|
||||
@ -4438,62 +4445,3 @@ void Preprocessor::HandleCXXModuleDirective(Token ModuleTok) {
|
||||
}
|
||||
EnterModuleSuffixTokenStream(DirToks);
|
||||
}
|
||||
|
||||
/// Lex a token following the 'import' contextual keyword.
|
||||
///
|
||||
/// pp-import:
|
||||
/// [ObjC] @ import module-name ;
|
||||
///
|
||||
/// module-name:
|
||||
/// module-name-qualifier[opt] identifier
|
||||
///
|
||||
/// module-name-qualifier
|
||||
/// module-name-qualifier[opt] identifier .
|
||||
///
|
||||
/// We respond to a pp-import by importing macros from the named module.
|
||||
void Preprocessor::HandleObjCImportDirective(Token &AtTok, Token &ImportTok) {
|
||||
assert(getLangOpts().ObjC && AtTok.is(tok::at) &&
|
||||
ImportTok.isObjCAtKeyword(tok::objc_import));
|
||||
ImportTok.setKind(tok::kw_import);
|
||||
SmallVector<Token, 32> DirToks{AtTok, ImportTok};
|
||||
SmallVector<IdentifierLoc, 3> Path;
|
||||
SourceLocation UseLoc = ImportTok.getLocation();
|
||||
ModuleImportLoc = ImportTok.getLocation();
|
||||
Token Tok;
|
||||
Lex(Tok);
|
||||
if (HandleModuleName(ImportTok.getIdentifierInfo()->getName(), UseLoc, Tok,
|
||||
Path, DirToks,
|
||||
/*AllowMacroExpansion=*/true,
|
||||
/*IsPartition=*/false))
|
||||
return;
|
||||
|
||||
// Consume the pp-import-suffix and expand any macros in it now, if we're not
|
||||
// at the semicolon already.
|
||||
if (!DirToks.back().isOneOf(tok::semi, tok::eod))
|
||||
CollectPPImportSuffix(DirToks);
|
||||
|
||||
if (DirToks.back().isNot(tok::eod))
|
||||
CheckEndOfDirective(ImportTok.getIdentifierInfo()->getName());
|
||||
else
|
||||
DirToks.pop_back();
|
||||
|
||||
// This is not a pp-import after all.
|
||||
if (DirToks.back().isNot(tok::semi)) {
|
||||
EnterModuleSuffixTokenStream(DirToks);
|
||||
return;
|
||||
}
|
||||
|
||||
Module *Imported = nullptr;
|
||||
SourceLocation SemiLoc = DirToks.back().getLocation();
|
||||
if (getLangOpts().Modules) {
|
||||
Imported = TheModuleLoader.loadModule(ModuleImportLoc, Path, Module::Hidden,
|
||||
/*IsInclusionDirective=*/false);
|
||||
if (Imported)
|
||||
makeModuleVisible(Imported, SemiLoc);
|
||||
}
|
||||
|
||||
if (Callbacks)
|
||||
Callbacks->moduleImport(ModuleImportLoc, Path, Imported);
|
||||
|
||||
EnterModuleSuffixTokenStream(DirToks);
|
||||
}
|
||||
|
||||
@ -115,9 +115,10 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
||||
CurPPLexer = TheLexer;
|
||||
CurDirLookup = CurDir;
|
||||
CurLexerSubmodule = nullptr;
|
||||
CurLexerCallback = TheLexer->isDependencyDirectivesLexer()
|
||||
? CLK_DependencyDirectivesLexer
|
||||
: CLK_Lexer;
|
||||
if (CurLexerCallback != CLK_LexAfterModuleImport)
|
||||
CurLexerCallback = TheLexer->isDependencyDirectivesLexer()
|
||||
? CLK_DependencyDirectivesLexer
|
||||
: CLK_Lexer;
|
||||
|
||||
// Notify the client, if desired, that we are in a new source file.
|
||||
if (Callbacks && !CurLexer->Is_PragmaLexer) {
|
||||
@ -153,7 +154,8 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
|
||||
PushIncludeMacroStack();
|
||||
CurDirLookup = nullptr;
|
||||
CurTokenLexer = std::move(TokLexer);
|
||||
CurLexerCallback = CLK_TokenLexer;
|
||||
if (CurLexerCallback != CLK_LexAfterModuleImport)
|
||||
CurLexerCallback = CLK_TokenLexer;
|
||||
}
|
||||
|
||||
/// EnterTokenStream - Add a "macro" context to the top of the include stack,
|
||||
@ -207,7 +209,8 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
|
||||
PushIncludeMacroStack();
|
||||
CurDirLookup = nullptr;
|
||||
CurTokenLexer = std::move(TokLexer);
|
||||
CurLexerCallback = CLK_TokenLexer;
|
||||
if (CurLexerCallback != CLK_LexAfterModuleImport)
|
||||
CurLexerCallback = CLK_TokenLexer;
|
||||
}
|
||||
|
||||
/// Compute the relative path that names the given file relative to
|
||||
|
||||
@ -889,6 +889,23 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
|
||||
return hadModuleLoaderFatalFailure();
|
||||
}
|
||||
|
||||
// If this is the 'import' contextual keyword following an '@', note
|
||||
// that the next token indicates a module name.
|
||||
//
|
||||
// Note that we do not treat 'import' as a contextual
|
||||
// keyword when we're in a caching lexer, because caching lexers only get
|
||||
// used in contexts where import declarations are disallowed.
|
||||
//
|
||||
// Likewise if this is the standard C++ import keyword.
|
||||
if (((LastTokenWasAt && II.isImportKeyword()) ||
|
||||
Identifier.is(tok::kw_import)) &&
|
||||
!InMacroArgs &&
|
||||
(!DisableMacroExpansion || MacroExpansionInDirectivesOverride) &&
|
||||
CurLexerCallback != CLK_CachingLexer) {
|
||||
ModuleImportLoc = Identifier.getLocation();
|
||||
IsAtImport = true;
|
||||
CurLexerCallback = CLK_LexAfterModuleImport;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -988,6 +1005,7 @@ void Preprocessor::Lex(Token &Result) {
|
||||
CheckPointCounter = 0;
|
||||
}
|
||||
|
||||
LastTokenWasAt = Result.is(tok::at);
|
||||
if (Result.isNot(tok::kw_export))
|
||||
LastExportKeyword.startToken();
|
||||
|
||||
@ -1326,7 +1344,8 @@ bool Preprocessor::HandleModuleContextualKeyword(Token &Result) {
|
||||
CurPPLexer->ParsingFilename,
|
||||
Result.getIdentifierInfo()->isImportKeyword());
|
||||
|
||||
std::optional<Token> NextTok = peekNextPPToken();
|
||||
std::optional<Token> NextTok =
|
||||
CurLexer ? CurLexer->peekNextPPToken() : CurTokenLexer->peekNextPPToken();
|
||||
if (!NextTok)
|
||||
return false;
|
||||
|
||||
@ -1338,6 +1357,7 @@ bool Preprocessor::HandleModuleContextualKeyword(Token &Result) {
|
||||
tok::header_name)) {
|
||||
Result.setKind(tok::kw_import);
|
||||
ModuleImportLoc = Result.getLocation();
|
||||
IsAtImport = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1394,6 +1414,77 @@ void Preprocessor::EnterModuleSuffixTokenStream(ArrayRef<Token> Toks) {
|
||||
CurTokenLexer->setLexingCXXModuleDirective();
|
||||
}
|
||||
|
||||
/// Lex a token following the 'import' contextual keyword.
|
||||
///
|
||||
/// pp-import: [C++20]
|
||||
/// import header-name pp-import-suffix[opt] ;
|
||||
/// import header-name-tokens pp-import-suffix[opt] ;
|
||||
/// [ObjC] @ import module-name ;
|
||||
/// [Clang] import module-name ;
|
||||
///
|
||||
/// header-name-tokens:
|
||||
/// string-literal
|
||||
/// < [any sequence of preprocessing-tokens other than >] >
|
||||
///
|
||||
/// module-name:
|
||||
/// module-name-qualifier[opt] identifier
|
||||
///
|
||||
/// module-name-qualifier
|
||||
/// module-name-qualifier[opt] identifier .
|
||||
///
|
||||
/// We respond to a pp-import by importing macros from the named module.
|
||||
bool Preprocessor::LexAfterModuleImport(Token &Result) {
|
||||
// Figure out what kind of lexer we actually have.
|
||||
recomputeCurLexerKind();
|
||||
|
||||
SmallVector<Token, 32> Suffix;
|
||||
SmallVector<IdentifierLoc, 3> Path;
|
||||
Lex(Result);
|
||||
if (LexModuleNameContinue(Result, ModuleImportLoc, Suffix, Path,
|
||||
/*AllowMacroExpansion=*/true,
|
||||
/*IsPartition=*/false))
|
||||
return CollectPPImportSuffixAndEnterStream(Suffix);
|
||||
|
||||
ModuleNameLoc *NameLoc = ModuleNameLoc::Create(*this, Path);
|
||||
Suffix.clear();
|
||||
Suffix.emplace_back();
|
||||
Suffix.back().setKind(tok::annot_module_name);
|
||||
Suffix.back().setAnnotationRange(NameLoc->getRange());
|
||||
Suffix.back().setAnnotationValue(static_cast<void *>(NameLoc));
|
||||
Suffix.push_back(Result);
|
||||
|
||||
// Consume the pp-import-suffix and expand any macros in it now, if we're not
|
||||
// at the semicolon already.
|
||||
SourceLocation SemiLoc = Result.getLocation();
|
||||
if (Suffix.back().isNot(tok::semi)) {
|
||||
if (Suffix.back().isNot(tok::eof))
|
||||
CollectPPImportSuffix(Suffix);
|
||||
if (Suffix.back().isNot(tok::semi)) {
|
||||
// This is not an import after all.
|
||||
EnterModuleSuffixTokenStream(Suffix);
|
||||
return false;
|
||||
}
|
||||
SemiLoc = Suffix.back().getLocation();
|
||||
}
|
||||
|
||||
Module *Imported = nullptr;
|
||||
if (getLangOpts().Modules) {
|
||||
Imported = TheModuleLoader.loadModule(ModuleImportLoc, Path, Module::Hidden,
|
||||
/*IsInclusionDirective=*/false);
|
||||
if (Imported)
|
||||
makeModuleVisible(Imported, SemiLoc);
|
||||
}
|
||||
|
||||
if (Callbacks)
|
||||
Callbacks->moduleImport(ModuleImportLoc, Path, Imported);
|
||||
|
||||
if (!Suffix.empty()) {
|
||||
EnterModuleSuffixTokenStream(Suffix);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc,
|
||||
bool IncludeExports) {
|
||||
CurSubmoduleState->VisibleModules.setVisible(
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
|
||||
@import lookup_left_cxx;
|
||||
@import lookup_right_cxx;
|
||||
#define import @import
|
||||
import lookup_left_cxx;
|
||||
#undef import
|
||||
#define IMPORT(X) @import X
|
||||
IMPORT(lookup_right_cxx);
|
||||
|
||||
// expected-warning@Inputs/lookup_left.hpp:3 {{weak identifier 'weak_identifier' never declared}}
|
||||
|
||||
|
||||
@ -23,8 +23,7 @@
|
||||
// RUN: -I %t -fsyntax-only %t/main.m -Rmodule-build -verify
|
||||
|
||||
//--- b.h
|
||||
@import l;
|
||||
@import r;
|
||||
@import l; @import r;
|
||||
|
||||
//--- l.h
|
||||
@import t; // fromt l
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fimplicit-module-maps \
|
||||
// RUN: -I%S/Inputs -verify -x objective-c %t/macro-module-name.m
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fimplicit-module-maps \
|
||||
// RUN: -I%S/Inputs -verify -x objective-c %t/macro-at-import.m
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fimplicit-module-maps \
|
||||
// RUN: -I%S/Inputs -verify -x objective-c %t/macro-func-import.m
|
||||
|
||||
//--- macro-module-name.m
|
||||
// expected-no-diagnostics
|
||||
#define M dummy
|
||||
@import M;
|
||||
|
||||
#ifndef DUMMY_H
|
||||
#error "macros from module not visible after @import with macro module name"
|
||||
#endif
|
||||
|
||||
void *p = &dummy1;
|
||||
|
||||
//--- macro-at-import.m
|
||||
#define imp @import
|
||||
imp dummy;
|
||||
|
||||
#ifdef DUMMY_H
|
||||
#error "module should not be imported via macro-constructed @import"
|
||||
#endif
|
||||
|
||||
void *p = &dummy1; // expected-error {{use of undeclared identifier 'dummy1'}}
|
||||
|
||||
//--- macro-func-import.m
|
||||
#define IMPORT(X) @import X
|
||||
IMPORT(dummy);
|
||||
|
||||
#ifdef DUMMY_H
|
||||
#error "module should not be imported via function-like macro @import"
|
||||
#endif
|
||||
|
||||
void *p = &dummy1; // expected-error {{use of undeclared identifier 'dummy1'}}
|
||||
@ -640,7 +640,7 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AtImport) {
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives(" @ import A;\n", Out));
|
||||
EXPECT_STREQ("@import A;\n", Out.data());
|
||||
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A;\n", Out));
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A\n;", Out));
|
||||
EXPECT_STREQ("@import A;\n", Out.data());
|
||||
|
||||
ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A.B;\n", Out));
|
||||
|
||||
@ -807,6 +807,7 @@ For later versions of Visual Studio, no setup is required-->
|
||||
<DisplayString Condition="IncludeMacroStack._Mypair._Myval2._Mylast - IncludeMacroStack._Mypair._Myval2._Myfirst">
|
||||
{this,view(cached)}
|
||||
</DisplayString>
|
||||
<DisplayString>CLK_LexAfterModuleImport</DisplayString>
|
||||
</Type>
|
||||
<Type Name="clang::Parser">
|
||||
<DisplayString>[{Tok}] {PP,na}</DisplayString>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user