diff options
Diffstat (limited to 'lib/Lex/Preprocessor.cpp')
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 78179dd7988d..0f7473b8c1ff 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -43,18 +43,27 @@ #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/ScratchBuffer.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Capacity.h" -#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <memory> +#include <string> #include <utility> +#include <vector> + using namespace clang; -template class llvm::Registry<clang::PragmaHandler>; +LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry) //===----------------------------------------------------------------------===// ExternalPreprocessorSource::~ExternalPreprocessorSource() { } @@ -74,11 +83,12 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr), CodeCompletionFile(nullptr), CodeCompletionOffset(0), LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), - CodeCompletionReached(0), MainFileDir(nullptr), - SkipMainFilePreamble(0, true), CurPPLexer(nullptr), CurDirLookup(nullptr), - CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), Callbacks(nullptr), - CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr), - Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { + CodeCompletionReached(false), CodeCompletionII(nullptr), + MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), + CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), + Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState), + MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr), + DeserialMIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. @@ -480,7 +490,7 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok, } Module *Preprocessor::getCurrentModule() { - if (!getLangOpts().CompilingModule) + if (!getLangOpts().isCompilingModule()) return nullptr; return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule); @@ -490,7 +500,6 @@ Module *Preprocessor::getCurrentModule() { // Preprocessor Initialization Methods //===----------------------------------------------------------------------===// - /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void Preprocessor::EnterMainSourceFile() { @@ -618,6 +627,11 @@ static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II, "Keyword not known to come from a newer Standard or proposed Standard"); } +void Preprocessor::updateOutOfDateIdentifier(IdentifierInfo &II) const { + assert(II.isOutOfDate() && "not out of date"); + getExternalSource()->updateOutOfDateIdentifier(II); +} + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or /// potentially macro expands it or turns it into a named token (like 'for'). @@ -642,7 +656,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { if (&II == Ident__VA_ARGS__) CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned(); - ExternalSource->updateOutOfDateIdentifier(II); + updateOutOfDateIdentifier(II); Identifier.setKind(II.getTokenID()); if (&II == Ident__VA_ARGS__) @@ -707,9 +721,12 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { // 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. - if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs && - !DisableMacroExpansion && - (getLangOpts().Modules || getLangOpts().DebuggerSupport) && + // + // Likewise if this is the C++ Modules TS import keyword. + if (((LastTokenWasAt && II.isModulesImport()) || + Identifier.is(tok::kw_import)) && + !InMacroArgs && !DisableMacroExpansion && + (getLangOpts().Modules || getLangOpts().DebuggerSupport) && CurLexerKind != CLK_CachingLexer) { ModuleImportLoc = Identifier.getLocation(); ModuleImportPath.clear(); @@ -744,10 +761,12 @@ void Preprocessor::Lex(Token &Result) { } } while (!ReturnedToken); + if (Result.is(tok::code_completion)) + setCodeCompletionIdentifierInfo(Result.getIdentifierInfo()); + LastTokenWasAt = Result.is(tok::at); } - /// \brief Lex a token following the 'import' contextual keyword. /// void Preprocessor::LexAfterModuleImport(Token &Result) { @@ -774,7 +793,8 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { } // If we're expecting a '.' or a ';', and we got a '.', then wait until we - // see the next identifier. + // see the next identifier. (We can also see a '[[' that begins an + // attribute-specifier-seq here under the C++ Modules TS.) if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) { ModuleImportExpectsIdentifier = true; CurLexerKind = CLK_LexAfterModuleImport; @@ -783,6 +803,23 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { // If we have a non-empty module path, load the named module. if (!ModuleImportPath.empty()) { + // Under the Modules TS, the dot is just part of the module name, and not + // a real hierarachy separator. Flatten such module names now. + // + // FIXME: Is this the right level to be performing this transformation? + std::string FlatModuleName; + if (getLangOpts().ModulesTS) { + for (auto &Piece : ModuleImportPath) { + if (!FlatModuleName.empty()) + FlatModuleName += "."; + FlatModuleName += Piece.first->getName(); + } + SourceLocation FirstPathLoc = ModuleImportPath[0].second; + ModuleImportPath.clear(); + ModuleImportPath.push_back( + std::make_pair(getIdentifierInfo(FlatModuleName), FirstPathLoc)); + } + Module *Imported = nullptr; if (getLangOpts().Modules) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, |