diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp | 219 |
1 files changed, 182 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 50a0cb55f736..86c508fe9b1b 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" @@ -241,7 +242,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, bool FoundElse, SourceLocation ElseLoc) { ++NumSkipped; - assert(CurTokenLexer == 0 && CurPPLexer && "Lexing a macro, not a file?"); + assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?"); CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false, FoundNonSkipPortion, FoundElse); @@ -430,7 +431,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, if (Callbacks) Callbacks->Elif(Tok.getLocation(), SourceRange(ConditionalBegin, ConditionalEnd), - CondInfo.IfLoc); + ShouldEnter, CondInfo.IfLoc); break; } } @@ -531,14 +532,97 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { } } +Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) { + ModuleMap &ModMap = HeaderInfo.getModuleMap(); + if (SourceMgr.isInMainFile(FilenameLoc)) { + if (Module *CurMod = getCurrentModule()) + return CurMod; // Compiling a module. + return HeaderInfo.getModuleMap().SourceModule; // Compiling a source. + } + // Try to determine the module of the include directive. + FileID IDOfIncl = SourceMgr.getFileID(FilenameLoc); + if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) { + // The include comes from a file. + return ModMap.findModuleForHeader(EntryOfIncl).getModule(); + } else { + // The include does not come from a file, + // so it is probably a module compilation. + return getCurrentModule(); + } +} + +bool Preprocessor::violatesPrivateInclude( + Module *RequestingModule, + const FileEntry *IncFileEnt, + ModuleMap::ModuleHeaderRole Role, + Module *RequestedModule) { + #ifndef NDEBUG + // Check for consistency between the module header role + // as obtained from the lookup and as obtained from the module. + // This check is not cheap, so enable it only for debugging. + SmallVectorImpl<const FileEntry *> &PvtHdrs + = RequestedModule->PrivateHeaders; + SmallVectorImpl<const FileEntry *>::iterator Look + = std::find(PvtHdrs.begin(), PvtHdrs.end(), IncFileEnt); + bool IsPrivate = Look != PvtHdrs.end(); + assert((IsPrivate && Role == ModuleMap::PrivateHeader) + || (!IsPrivate && Role != ModuleMap::PrivateHeader)); + #endif + return Role == ModuleMap::PrivateHeader && + RequestedModule->getTopLevelModule() != RequestingModule; +} + +bool Preprocessor::violatesUseDeclarations( + Module *RequestingModule, + Module *RequestedModule) { + ModuleMap &ModMap = HeaderInfo.getModuleMap(); + ModMap.resolveUses(RequestingModule, /*Complain=*/false); + const SmallVectorImpl<Module *> &AllowedUses = RequestingModule->DirectUses; + SmallVectorImpl<Module *>::const_iterator Declared = + std::find(AllowedUses.begin(), AllowedUses.end(), RequestedModule); + return Declared == AllowedUses.end(); +} + +void Preprocessor::verifyModuleInclude(SourceLocation FilenameLoc, + StringRef Filename, + const FileEntry *IncFileEnt) { + Module *RequestingModule = getModuleForLocation(FilenameLoc); + if (RequestingModule) + HeaderInfo.getModuleMap().resolveUses(RequestingModule, /*Complain=*/false); + ModuleMap::KnownHeader RequestedModule = + HeaderInfo.getModuleMap().findModuleForHeader(IncFileEnt, + RequestingModule); + + if (RequestingModule == RequestedModule.getModule()) + return; // No faults wihin a module, or between files both not in modules. + + if (RequestingModule != HeaderInfo.getModuleMap().SourceModule) + return; // No errors for indirect modules. + // This may be a bit of a problem for modules with no source files. + + if (RequestedModule && violatesPrivateInclude(RequestingModule, IncFileEnt, + RequestedModule.getRole(), + RequestedModule.getModule())) + Diag(FilenameLoc, diag::error_use_of_private_header_outside_module) + << Filename; + + // FIXME: Add support for FixIts in module map files and offer adding the + // required use declaration. + if (RequestingModule && getLangOpts().ModulesDeclUse && + violatesUseDeclarations(RequestingModule, RequestedModule.getModule())) + Diag(FilenameLoc, diag::error_undeclared_use_of_module) + << Filename; +} + const FileEntry *Preprocessor::LookupFile( + SourceLocation FilenameLoc, StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - Module **SuggestedModule, + ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) { // If the header lookup mechanism may be relative to the current file, pass in // info about where the current file is. @@ -564,7 +648,11 @@ const FileEntry *Preprocessor::LookupFile( const FileEntry *FE = HeaderInfo.LookupFile( Filename, isAngled, FromDir, CurDir, CurFileEnt, SearchPath, RelativePath, SuggestedModule, SkipCache); - if (FE) return FE; + if (FE) { + if (SuggestedModule) + verifyModuleInclude(FilenameLoc, Filename, FE); + return FE; + } // Otherwise, see if this is a subframework header. If so, this is relative // to one of the headers on the #include stack. Walk the list of the current @@ -626,6 +714,10 @@ void Preprocessor::HandleDirective(Token &Result) { CurPPLexer->ParsingPreprocessorDirective = true; if (CurLexer) CurLexer->SetKeepWhitespaceMode(false); + bool ImmediatelyAfterTopLevelIfndef = + CurPPLexer->MIOpt.getImmediatelyAfterTopLevelIfndef(); + CurPPLexer->MIOpt.resetImmediatelyAfterTopLevelIfndef(); + ++NumDirectives; // We are about to read a token. For the multiple-include optimization FA to @@ -713,7 +805,7 @@ void Preprocessor::HandleDirective(Token &Result) { // C99 6.10.3 - Macro Replacement. case tok::pp_define: - return HandleDefineDirective(Result); + return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef); case tok::pp_undef: return HandleUndefDirective(Result); @@ -727,7 +819,7 @@ void Preprocessor::HandleDirective(Token &Result) { // C99 6.10.6 - Pragma Directive. case tok::pp_pragma: - return HandlePragmaDirective(PIK_HashPragma); + return HandlePragmaDirective(SavedHash.getLocation(), PIK_HashPragma); // GNU Extensions. case tok::pp_import: @@ -819,6 +911,11 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, // here. Val = 0; for (unsigned i = 0; i != ActualLength; ++i) { + // C++1y [lex.fcon]p1: + // Optional separating single quotes in a digit-sequence are ignored + if (DigitTokBegin[i] == '\'') + continue; + if (!isDigit(DigitTokBegin[i])) { PP.Diag(PP.AdvanceToTokenCharacter(DigitTok.getLocation(), i), diag::err_pp_line_digit_sequence) << IsGNULineDirective; @@ -1386,11 +1483,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, SmallString<1024> RelativePath; // We get the raw path only if we have 'Callbacks' to which we later pass // the path. - Module *SuggestedModule = 0; + ModuleMap::KnownHeader SuggestedModule; + SourceLocation FilenameLoc = FilenameTok.getLocation(); const FileEntry *File = LookupFile( - Filename, isAngled, LookupFrom, CurDir, + FilenameLoc, Filename, isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL, - getLangOpts().Modules? &SuggestedModule : 0); + HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0); if (Callbacks) { if (!File) { @@ -1403,14 +1501,16 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, HeaderInfo.AddSearchPath(DL, isAngled); // Try the lookup again, skipping the cache. - File = LookupFile(Filename, isAngled, LookupFrom, CurDir, 0, 0, - getLangOpts().Modules? &SuggestedModule : 0, - /*SkipCache*/true); + File = LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir, + 0, 0, HeaderInfo.getHeaderSearchOpts().ModuleMaps + ? &SuggestedModule + : 0, + /*SkipCache*/ true); } } } - if (!SuggestedModule) { + if (!SuggestedModule || !getLangOpts().Modules) { // Notify the callback object that we've seen an inclusion directive. Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, FilenameRange, File, @@ -1425,10 +1525,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // brackets, we can attempt a lookup as though it were a quoted path to // provide the user with a possible fixit. if (isAngled) { - File = LookupFile(Filename, false, LookupFrom, CurDir, - Callbacks ? &SearchPath : 0, - Callbacks ? &RelativePath : 0, - getLangOpts().Modules ? &SuggestedModule : 0); + File = LookupFile( + FilenameLoc, Filename, false, LookupFrom, CurDir, + Callbacks ? &SearchPath : 0, Callbacks ? &RelativePath : 0, + HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0); if (File) { SourceRange Range(FilenameTok.getLocation(), CharEnd); Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) << @@ -1446,12 +1546,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // If we are supposed to import a module rather than including the header, // do so now. - if (SuggestedModule) { + if (SuggestedModule && getLangOpts().Modules) { // Compute the module access path corresponding to this module. // FIXME: Should we have a second loadModule() overload to avoid this // extra lookup step? SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path; - for (Module *Mod = SuggestedModule; Mod; Mod = Mod->Parent) + for (Module *Mod = SuggestedModule.getModule(); Mod; Mod = Mod->Parent) Path.push_back(std::make_pair(getIdentifierInfo(Mod->Name), FilenameTok.getLocation())); std::reverse(Path.begin(), Path.end()); @@ -1503,16 +1603,29 @@ 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); - assert((Imported == 0 || Imported == SuggestedModule) && + assert((Imported == 0 || Imported == SuggestedModule.getModule()) && "the imported module is different than the suggested one"); - + + if (!Imported && hadModuleLoaderFatalFailure()) { + // With a fatal failure in the module loader, we abort parsing. + Token &Result = IncludeTok; + if (CurLexer) { + Result.startToken(); + CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof); + CurLexer->cutOffLexing(); + } else { + assert(CurPTHLexer && "#include but no current lexer set!"); + CurPTHLexer->getEOF(Result); + } + return; + } + // If this header isn't part of the module we're building, we're done. if (!BuildingImportedModule && Imported) { if (Callbacks) { @@ -1520,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; } @@ -1746,7 +1873,8 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { /// HandleDefineDirective - Implements \#define. This consumes the entire macro /// line then lets the caller lex the next real token. -void Preprocessor::HandleDefineDirective(Token &DefineTok) { +void Preprocessor::HandleDefineDirective(Token &DefineTok, + bool ImmediatelyAfterHeaderGuard) { ++NumDefined; Token MacroNameTok; @@ -1772,6 +1900,11 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // marking each of the identifiers as being used as macro arguments. Also, // check other constraints on the first token of the macro body. if (Tok.is(tok::eod)) { + if (ImmediatelyAfterHeaderGuard) { + // Save this macro information since it may part of a header guard. + CurPPLexer->MIOpt.SetDefinedMacro(MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation()); + } // If there is no body to this macro, we have no special handling here. } else if (Tok.hasLeadingSpace()) { // This is a normal token with leading space. Clear the leading space @@ -1854,6 +1987,18 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { continue; } + // If we're in -traditional mode, then we should ignore stringification + // and token pasting. Mark the tokens as unknown so as not to confuse + // things. + if (getLangOpts().TraditionalCPP) { + Tok.setKind(tok::unknown); + MI->AddTokenToBody(Tok); + + // Get the next token of the macro. + LexUnexpandedToken(Tok); + continue; + } + if (Tok.is(tok::hashhash)) { // If we see token pasting, check if it looks like the gcc comma @@ -1873,13 +2018,8 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { MI->getReplacementToken(NumTokens-1).is(tok::comma)) MI->setHasCommaPasting(); - // Things look ok, add the '##' and param name tokens to the macro. + // Things look ok, add the '##' token to the macro. MI->AddTokenToBody(LastTok); - MI->AddTokenToBody(Tok); - LastTok = Tok; - - // Get the next token of the macro. - LexUnexpandedToken(Tok); continue; } @@ -1896,6 +2036,8 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // confused. if (getLangOpts().AsmPreprocessor && Tok.isNot(tok::eod)) { LastTok.setKind(tok::unknown); + MI->AddTokenToBody(LastTok); + continue; } else { Diag(Tok, diag::err_pp_stringize_not_parameter); ReleaseMacroInfo(MI); @@ -1972,7 +2114,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { assert(!MI->isUsed()); // If we need warning for not using the macro, add its location in the // warn-because-unused-macro set. If it gets used it will be removed from set. - if (isInPrimaryFile() && // don't warn for include'd macros. + if (getSourceManager().isInMainFile(MI->getDefinitionLoc()) && Diags->getDiagnosticLevel(diag::pp_macro_not_used, MI->getDefinitionLoc()) != DiagnosticsEngine::Ignored) { MI->setIsWarnIfUnused(true); @@ -2062,7 +2204,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, // handle. if (!ReadAnyTokensBeforeDirective && MI == 0) { assert(isIfndef && "#ifdef shouldn't reach here"); - CurPPLexer->MIOpt.EnterTopLevelIFNDEF(MII); + CurPPLexer->MIOpt.EnterTopLevelIfndef(MII, MacroNameTok.getLocation()); } else CurPPLexer->MIOpt.EnterTopLevelConditional(); } @@ -2108,14 +2250,16 @@ void Preprocessor::HandleIfDirective(Token &IfToken, // directive seen, handle it for the multiple-include optimization. if (CurPPLexer->getConditionalStackDepth() == 0) { if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue) - CurPPLexer->MIOpt.EnterTopLevelIFNDEF(IfNDefMacro); + // FIXME: Pass in the location of the macro name, not the 'if' token. + CurPPLexer->MIOpt.EnterTopLevelIfndef(IfNDefMacro, IfToken.getLocation()); else CurPPLexer->MIOpt.EnterTopLevelConditional(); } if (Callbacks) Callbacks->If(IfToken.getLocation(), - SourceRange(ConditionalBegin, ConditionalEnd)); + SourceRange(ConditionalBegin, ConditionalEnd), + ConditionalTrue); // Should we include the stuff contained by this directive? if (ConditionalTrue) { @@ -2211,7 +2355,8 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) { if (Callbacks) Callbacks->Elif(ElifToken.getLocation(), - SourceRange(ConditionalBegin, ConditionalEnd), CI.IfLoc); + SourceRange(ConditionalBegin, ConditionalEnd), + true, CI.IfLoc); // Finally, skip the rest of the contents of this block. SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, |