diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-15 04:24:58 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-15 04:24:58 +0000 |
commit | ce587f5eb96477e4c357e49b7d55aa175485b367 (patch) | |
tree | 13772f05719330d7fbed0723840e40e106203120 /clang/lib | |
parent | 6519801a6e773eda9e64a7e573ed062965f1e6c5 (diff) | |
download | bcm5719-llvm-ce587f5eb96477e4c357e49b7d55aa175485b367.tar.gz bcm5719-llvm-ce587f5eb96477e4c357e49b7d55aa175485b367.zip |
When we hit a #include directive that maps to a module import, emit a token
representing the module import rather than making the module immediately
visible. This serves two goals:
* It avoids making declarations in the module visible prematurely, if we
walk past the #include during a tentative parse, for instance, and
* It gives a diagnostic (although, admittedly, not a very nice one) if
a header with a corresponding module is included anywhere other than
at the top level.
llvm-svn: 194782
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Frontend/PrintPreprocessedOutput.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 6 |
4 files changed, 44 insertions, 9 deletions
diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp index 3545d70744f..55a66d87f8b 100644 --- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp @@ -657,6 +657,11 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, // -traditional-cpp the lexer keeps /all/ whitespace, including comments. SourceLocation StartLoc = Tok.getLocation(); Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); + } else if (Tok.is(tok::annot_module_include)) { + // PrintPPOutputPPCallbacks::InclusionDirective handles producing + // appropriate output here. Ignore this token entirely. + PP.Lex(Tok); + continue; } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { OS << II->getName(); } else if (Tok.isLiteral() && !Tok.needsCleaning() && diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 9ba65a57a84..86c508fe9b1 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1603,10 +1603,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, "@import " + PathString.str().str() + ";"); } - // Load the module. - // If this was an #__include_macros directive, only make macros visible. - Module::NameVisibilityKind Visibility - = (IncludeKind == 3)? Module::MacrosVisible : Module::AllVisible; + // Load the module. Only make macros visible. We'll make the declarations + // visible when the parser gets here. + Module::NameVisibilityKind Visibility = Module::MacrosVisible; ModuleLoadResult Imported = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility, /*IsIncludeDirective=*/true); @@ -1626,7 +1625,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } return; } - + // If this header isn't part of the module we're building, we're done. if (!BuildingImportedModule && Imported) { if (Callbacks) { @@ -1634,6 +1633,20 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, FilenameRange, File, SearchPath, RelativePath, Imported); } + + if (IncludeKind != 3) { + // Let the parser know that we hit a module import, and it should + // make the module visible. + // FIXME: Produce this as the current token directly, rather than + // allocating a new token for it. + Token *Tok = new Token[1]; + Tok[0].startToken(); + Tok[0].setKind(tok::annot_module_include); + Tok[0].setLocation(HashLoc); + Tok[0].setAnnotationEndLoc(End); + Tok[0].setAnnotationValue(Imported); + EnterTokenStream(Tok, 1, true, true); + } return; } diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 84aad4101fb..c6eac18aa49 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -566,19 +566,30 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) ConsumeToken(); - while (Tok.is(tok::annot_pragma_unused)) + Result = DeclGroupPtrTy(); + switch (Tok.getKind()) { + case tok::annot_pragma_unused: HandlePragmaUnused(); + return false; - Result = DeclGroupPtrTy(); - if (Tok.is(tok::eof)) { + case tok::annot_module_include: + Actions.ActOnModuleInclude(Tok.getLocation(), + reinterpret_cast<Module *>( + Tok.getAnnotationValue())); + ConsumeToken(); + return false; + + case tok::eof: // Late template parsing can begin. if (getLangOpts().DelayedTemplateParsing) Actions.SetLateTemplateParser(LateTemplateParserCallback, this); if (!PP.isIncrementalProcessingEnabled()) Actions.ActOnEndOfTranslationUnit(); //else don't tell Sema that we ended parsing: more input might come. - return true; + + default: + break; } ParsedAttributesWithRange attrs(AttrFactory); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 211e8587d16..f5507791e7f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12913,6 +12913,12 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, return Import; } +void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { + // FIXME: Should we synthesize an ImportDecl here? + PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc, + /*Complain=*/true); +} + void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) { // Create the implicit import declaration. TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); |