diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 19:17:14 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 19:17:14 +0000 | 
| commit | db17bf38c59bc172953ed66cfe1b10c03c6bc383 (patch) | |
| tree | 2712281fec99b99c2fcafd5b46439dfdd93261aa /contrib/llvm/tools/clang/lib/Lex | |
| parent | 686fb94a00297bf9ff49d93b948925552a2ce8e0 (diff) | |
| parent | 7ab83427af0f77b59941ceba41d509d7d097b065 (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp | 44 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 131 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp | 10 | 
3 files changed, 155 insertions, 30 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 2d3ad690987e..89c2ebd00a68 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -30,6 +30,7 @@  #include "clang/Lex/PPCallbacks.h"  #include "clang/Lex/Pragma.h"  #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h"  #include "clang/Lex/PTHLexer.h"  #include "clang/Lex/Token.h"  #include "llvm/ADT/ArrayRef.h" @@ -1654,6 +1655,26 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components,    return SuggestReplacement;  } +bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts, +                                          const TargetInfo &TargetInfo, +                                          DiagnosticsEngine &Diags, Module *M) { +  Module::Requirement Requirement; +  Module::UnresolvedHeaderDirective MissingHeader; +  if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader)) +    return false; + +  if (MissingHeader.FileNameLoc.isValid()) { +    Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) +        << MissingHeader.IsUmbrella << MissingHeader.FileName; +  } else { +    // FIXME: Track the location at which the requirement was specified, and +    // use it here. +    Diags.Report(M->DefinitionLoc, diag::err_module_unavailable) +        << M->getFullModuleName() << Requirement.second << Requirement.first; +  } +  return true; +} +  /// HandleIncludeDirective - The "\#include" tokens have just been read, read  /// the file to be included from the lexer, then include it!  This is a common  /// routine with functionality shared between \#include, \#include_next and @@ -1825,33 +1846,24 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,    // we've imported or already built.    bool ShouldEnter = true; +  if (PPOpts->SingleFileParseMode) +    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 (File && SuggestedModule && getLangOpts().Modules && +  if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules &&        SuggestedModule.getModule()->getTopLevelModuleName() !=            getLangOpts().CurrentModule) {      // 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      // slightly worse diagnostics). -    if (!SuggestedModule.getModule()->isAvailable()) { -      Module::Requirement Requirement; -      Module::UnresolvedHeaderDirective MissingHeader; -      Module *M = SuggestedModule.getModule(); -      // Identify the cause. -      (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement, -                           MissingHeader); -      if (MissingHeader.FileNameLoc.isValid()) { -        Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) -            << MissingHeader.IsUmbrella << MissingHeader.FileName; -      } else { -        Diag(M->DefinitionLoc, diag::err_module_unavailable) -            << M->getFullModuleName() << Requirement.second << Requirement.first; -      } +    if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), getDiagnostics(), +                               SuggestedModule.getModule())) {        Diag(FilenameTok.getLocation(),             diag::note_implicit_top_level_module_import_here) -          << M->getTopLevelModuleName(); +          << SuggestedModule.getModule()->getTopLevelModuleName();        return;      } diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index e1d981527bec..c16478dd2be4 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -754,6 +754,88 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {    getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);  } +void Preprocessor::HandlePragmaModuleBuild(Token &Tok) { +  SourceLocation Loc = Tok.getLocation(); + +  LexUnexpandedToken(Tok); +  if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) { +    Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << true; +    return; +  } +  IdentifierInfo *ModuleName = Tok.getIdentifierInfo(); + +  LexUnexpandedToken(Tok); +  if (Tok.isNot(tok::eod)) { +    Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; +    DiscardUntilEndOfDirective(); +  } + +  if (CurPTHLexer) { +    // FIXME: Support this somehow? +    Diag(Loc, diag::err_pp_module_build_pth); +    return; +  } + +  CurLexer->LexingRawMode = true; + +  auto TryConsumeIdentifier = [&](StringRef Ident) -> bool { +    if (Tok.getKind() != tok::raw_identifier || +        Tok.getRawIdentifier() != Ident) +      return false; +    CurLexer->Lex(Tok); +    return true; +  }; + +  // Scan forward looking for the end of the module. +  const char *Start = CurLexer->getBufferLocation(); +  const char *End = nullptr; +  unsigned NestingLevel = 1; +  while (true) { +    End = CurLexer->getBufferLocation(); +    CurLexer->Lex(Tok); + +    if (Tok.is(tok::eof)) { +      Diag(Loc, diag::err_pp_module_build_missing_end); +      break; +    } + +    if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine()) { +      // Token was part of module; keep going. +      continue; +    } + +    // We hit something directive-shaped; check to see if this is the end +    // of the module build. +    CurLexer->ParsingPreprocessorDirective = true; +    CurLexer->Lex(Tok); +    if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") && +        TryConsumeIdentifier("module")) { +      if (TryConsumeIdentifier("build")) +        // #pragma clang module build -> entering a nested module build. +        ++NestingLevel; +      else if (TryConsumeIdentifier("endbuild")) { +        // #pragma clang module endbuild -> leaving a module build. +        if (--NestingLevel == 0) +          break; +      } +      // We should either be looking at the EOD or more of the current directive +      // preceding the EOD. Either way we can ignore this token and keep going. +      assert(Tok.getKind() != tok::eof && "missing EOD before EOF"); +    } +  } + +  CurLexer->LexingRawMode = false; + +  // Load the extracted text as a preprocessed module. +  assert(CurLexer->getBuffer().begin() <= Start && +         Start <= CurLexer->getBuffer().end() && +         CurLexer->getBuffer().begin() <= End && +         End <= CurLexer->getBuffer().end() && +         "module source range not contained within same file buffer"); +  TheModuleLoader.loadModuleFromSource(Loc, ModuleName->getName(), +                                       StringRef(Start, End - Start)); +} +  /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.  /// If 'Namespace' is non-null, then it is a token required to exist on the  /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". @@ -1408,18 +1490,8 @@ struct PragmaModuleBeginHandler : public PragmaHandler {      }      // If the module isn't available, it doesn't make sense to enter it. -    if (!M->isAvailable()) { -      Module::Requirement Requirement; -      Module::UnresolvedHeaderDirective MissingHeader; -      (void)M->isAvailable(PP.getLangOpts(), PP.getTargetInfo(), -                           Requirement, MissingHeader); -      if (MissingHeader.FileNameLoc.isValid()) { -        PP.Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) -          << MissingHeader.IsUmbrella << MissingHeader.FileName; -      } else { -        PP.Diag(M->DefinitionLoc, diag::err_module_unavailable) -          << M->getFullModuleName() << Requirement.second << Requirement.first; -      } +    if (Preprocessor::checkModuleIsAvailable( +            PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) {        PP.Diag(BeginLoc, diag::note_pp_module_begin_here)          << M->getTopLevelModuleName();        return; @@ -1452,6 +1524,39 @@ struct PragmaModuleEndHandler : public PragmaHandler {    }  }; +/// Handle the clang \#pragma module build extension. +struct PragmaModuleBuildHandler : public PragmaHandler { +  PragmaModuleBuildHandler() : PragmaHandler("build") {} + +  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, +                    Token &Tok) override { +    PP.HandlePragmaModuleBuild(Tok); +  } +}; + +/// Handle the clang \#pragma module load extension. +struct PragmaModuleLoadHandler : public PragmaHandler { +  PragmaModuleLoadHandler() : PragmaHandler("load") {} + +  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, +                    Token &Tok) override { +    SourceLocation Loc = Tok.getLocation(); + +    // Read the module name. +    llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> +        ModuleName; +    if (LexModuleName(PP, Tok, ModuleName)) +      return; + +    if (Tok.isNot(tok::eod)) +      PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + +    // Load the module, don't make it visible. +    PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden, +                                    /*IsIncludeDirective=*/false); +  } +}; +  /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the  /// macro on the top of the stack.  struct PragmaPushMacroHandler : public PragmaHandler { @@ -1681,6 +1786,8 @@ void Preprocessor::RegisterBuiltinPragmas() {    ModuleHandler->AddPragma(new PragmaModuleImportHandler());    ModuleHandler->AddPragma(new PragmaModuleBeginHandler());    ModuleHandler->AddPragma(new PragmaModuleEndHandler()); +  ModuleHandler->AddPragma(new PragmaModuleBuildHandler()); +  ModuleHandler->AddPragma(new PragmaModuleLoadHandler());    AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());    AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp index 3596337c245e..f9a399cd7fd7 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp @@ -580,7 +580,11 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {    // Update the token info (identifier info and appropriate token kind).    Identifier.setIdentifierInfo(II); -  Identifier.setKind(II->getTokenID()); +  if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() && +      getSourceManager().isInSystemHeader(Identifier.getLocation())) +    Identifier.setKind(clang::tok::identifier); +  else +    Identifier.setKind(II->getTokenID());    return II;  } @@ -709,7 +713,9 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {    // C++ 2.11p2: If this is an alternative representation of a C++ operator,    // then we act as if it is the actual operator and not the textual    // representation of it. -  if (II.isCPlusPlusOperatorKeyword()) +  if (II.isCPlusPlusOperatorKeyword() && +      !(getLangOpts().MSVCCompat && +        getSourceManager().isInSystemHeader(Identifier.getLocation())))      Identifier.setIdentifierInfo(nullptr);    // If this is an extension token, diagnose its use.  | 
