diff options
Diffstat (limited to 'lib/Lex/PPDirectives.cpp')
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 354 |
1 files changed, 275 insertions, 79 deletions
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index de50c750e4d6..625a204af995 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -22,6 +22,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/APInt.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -119,8 +120,15 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) { std::string Spelling = getSpelling(MacroNameTok, &Invalid); if (Invalid) return; - + const IdentifierInfo &Info = Identifiers.get(Spelling); + + // Allow #defining |and| and friends in microsoft mode. + if (Info.isCPlusPlusOperatorKeyword() && getLangOpts().MicrosoftMode) { + MacroNameTok.setIdentifierInfo(getIdentifierInfo(Spelling)); + return; + } + if (Info.isCPlusPlusOperatorKeyword()) // C++ 2.5p2: Alternative tokens behave the same as its primary token // except for their spellings. @@ -173,7 +181,7 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { // trouble than it is worth to insert /**/ and check that there is no /**/ // in the range also. FixItHint Hint; - if ((Features.GNUMode || Features.C99 || Features.CPlusPlus) && + if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) && !CurTokenLexer) Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//"); Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint; @@ -305,9 +313,6 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, CurPPLexer->pushConditionalLevel(Tok.getLocation(), /*wasskipping*/true, /*foundnonskip*/false, /*foundelse*/false); - - if (Callbacks) - Callbacks->Endif(); } } else if (Directive[0] == 'e') { StringRef Sub = Directive.substr(1); @@ -320,8 +325,11 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, assert(!InCond && "Can't be skipping if not in a conditional!"); // If we popped the outermost skipping block, we're done skipping! - if (!CondInfo.WasSkipping) + if (!CondInfo.WasSkipping) { + if (Callbacks) + Callbacks->Endif(Tok.getLocation(), CondInfo.IfLoc); break; + } } else if (Sub == "lse") { // "else". // #else directive in a skipping conditional. If not in some other // skipping conditional, and if #else hasn't already been seen, enter it @@ -334,14 +342,13 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // Note that we've seen a #else in this conditional. CondInfo.FoundElse = true; - if (Callbacks) - Callbacks->Else(); - // If the conditional is at the top level, and the #if block wasn't // entered, enter the #else block now. if (!CondInfo.WasSkipping && !CondInfo.FoundNonSkip) { CondInfo.FoundNonSkip = true; CheckEndOfDirective("else"); + if (Callbacks) + Callbacks->Else(Tok.getLocation(), CondInfo.IfLoc); break; } else { DiscardUntilEndOfDirective(); // C99 6.10p4. @@ -370,12 +377,13 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // If this is a #elif with a #else before it, report the error. if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else); - if (Callbacks) - Callbacks->Elif(SourceRange(ConditionalBegin, ConditionalEnd)); - // If this condition is true, enter it! if (ShouldEnter) { CondInfo.FoundNonSkip = true; + if (Callbacks) + Callbacks->Elif(Tok.getLocation(), + SourceRange(ConditionalBegin, ConditionalEnd), + CondInfo.IfLoc); break; } } @@ -486,7 +494,8 @@ const FileEntry *Preprocessor::LookupFile( const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef *SuggestedModule) { + Module **SuggestedModule, + bool SkipCache) { // If the header lookup mechanism may be relative to the current file, pass in // info about where the current file is. const FileEntry *CurFileEnt = 0; @@ -510,7 +519,7 @@ const FileEntry *Preprocessor::LookupFile( CurDir = CurDirLookup; const FileEntry *FE = HeaderInfo.LookupFile( Filename, isAngled, FromDir, CurDir, CurFileEnt, - SearchPath, RelativePath, SuggestedModule); + SearchPath, RelativePath, SuggestedModule, SkipCache); if (FE) return FE; // Otherwise, see if this is a subframework header. If so, this is relative @@ -575,9 +584,25 @@ void Preprocessor::HandleDirective(Token &Result) { // A(abc // #warning blah // def) - // If so, the user is relying on non-portable behavior, emit a diagnostic. - if (InMacroArgs) + // If so, the user is relying on undefined behavior, emit a diagnostic. Do + // not support this for #include-like directives, since that can result in + // terrible diagnostics, and does not work in GCC. + if (InMacroArgs) { + if (IdentifierInfo *II = Result.getIdentifierInfo()) { + switch (II->getPPKeywordID()) { + case tok::pp_include: + case tok::pp_import: + case tok::pp_include_next: + case tok::pp___include_macros: + Diag(Result, diag::err_embedded_include) << II->getName(); + DiscardUntilEndOfDirective(); + return; + default: + break; + } + } Diag(Result, diag::ext_embedded_directive); + } TryAgain: switch (Result.getKind()) { @@ -594,7 +619,7 @@ TryAgain: setCodeCompletionReached(); return; case tok::numeric_constant: // # 7 GNU line marker directive. - if (getLangOptions().AsmPreprocessor) + if (getLangOpts().AsmPreprocessor) break; // # 4 is not a preprocessor directive in .S files. return HandleDigitDirective(Result); default: @@ -664,8 +689,15 @@ TryAgain: //isExtension = true; // FIXME: implement #unassert break; - case tok::pp___export_macro__: - return HandleMacroExportDirective(Result); + case tok::pp___public_macro: + if (getLangOpts().Modules) + return HandleMacroPublicDirective(Result); + break; + + case tok::pp___private_macro: + if (getLangOpts().Modules) + return HandleMacroPrivateDirective(Result); + break; } break; } @@ -674,7 +706,7 @@ TryAgain: // directives. This is important because # may be a comment or introduce // various pseudo-ops. Just return the # token and push back the following // token to be lexed next time. - if (getLangOptions().AsmPreprocessor) { + if (getLangOpts().AsmPreprocessor) { Token *Toks = new Token[2]; // Return the # and the token after it. Toks[0] = SavedHash; @@ -713,7 +745,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, return true; } - llvm::SmallString<64> IntegerBuffer; + SmallString<64> IntegerBuffer; IntegerBuffer.resize(DigitTok.getLength()); const char *DigitTokBegin = &IntegerBuffer[0]; bool Invalid = false; @@ -773,11 +805,11 @@ void Preprocessor::HandleLineDirective(Token &Tok) { // Enforce C99 6.10.4p3: "The digit sequence shall not specify ... a // number greater than 2147483647". C90 requires that the line # be <= 32767. unsigned LineLimit = 32768U; - if (Features.C99 || Features.CPlusPlus0x) + if (LangOpts.C99 || LangOpts.CPlusPlus0x) LineLimit = 2147483648U; if (LineNo >= LineLimit) Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit; - else if (Features.CPlusPlus0x && LineNo >= 32768U) + else if (LangOpts.CPlusPlus0x && LineNo >= 32768U) Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big); int FilenameID = -1; @@ -790,8 +822,10 @@ void Preprocessor::HandleLineDirective(Token &Tok) { ; // ok else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_line_invalid_filename); - DiscardUntilEndOfDirective(); - return; + return DiscardUntilEndOfDirective(); + } else if (StrTok.hasUDSuffix()) { + Diag(StrTok, diag::err_invalid_string_udl); + return DiscardUntilEndOfDirective(); } else { // Parse and validate the string, converting it into a unique ID. StringLiteralParser Literal(&StrTok, 1, *this); @@ -925,6 +959,9 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_linemarker_invalid_filename); return DiscardUntilEndOfDirective(); + } else if (StrTok.hasUDSuffix()) { + Diag(StrTok, diag::err_invalid_string_udl); + return DiscardUntilEndOfDirective(); } else { // Parse and validate the string, converting it into a unique ID. StringLiteralParser Literal(&StrTok, 1, *this); @@ -982,10 +1019,18 @@ void Preprocessor::HandleUserDiagnosticDirective(Token &Tok, // collapse multiple consequtive white space between tokens, but this isn't // specified by the standard. std::string Message = CurLexer->ReadToEndOfLine(); + + // Find the first non-whitespace character, so that we can make the + // diagnostic more succinct. + StringRef Msg(Message); + size_t i = Msg.find_first_not_of(' '); + if (i < Msg.size()) + Msg = Msg.substr(i); + if (isWarning) - Diag(Tok, diag::pp_hash_warning) << Message; + Diag(Tok, diag::pp_hash_warning) << Msg; else - Diag(Tok, diag::err_pp_hash_error) << Message; + Diag(Tok, diag::err_pp_hash_error) << Msg; } /// HandleIdentSCCSDirective - Handle a #ident/#sccs directive. @@ -1007,6 +1052,11 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) { return; } + if (StrTok.hasUDSuffix()) { + Diag(StrTok, diag::err_invalid_string_udl); + return DiscardUntilEndOfDirective(); + } + // Verify that there is nothing after the string, other than EOD. CheckEndOfDirective("ident"); @@ -1018,8 +1068,8 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) { } } -/// \brief Handle a #__export_macro__ directive. -void Preprocessor::HandleMacroExportDirective(Token &Tok) { +/// \brief Handle a #public directive. +void Preprocessor::HandleMacroPublicDirective(Token &Tok) { Token MacroNameTok; ReadMacroName(MacroNameTok, 2); @@ -1027,21 +1077,52 @@ void Preprocessor::HandleMacroExportDirective(Token &Tok) { if (MacroNameTok.is(tok::eod)) return; - // Check to see if this is the last token on the #__export_macro__ line. - CheckEndOfDirective("__export_macro__"); + // Check to see if this is the last token on the #__public_macro line. + CheckEndOfDirective("__public_macro"); // Okay, we finally have a valid identifier to undef. MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo()); // If the macro is not defined, this is an error. if (MI == 0) { - Diag(MacroNameTok, diag::err_pp_export_non_macro) + Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << MacroNameTok.getIdentifierInfo(); return; } // Note that this macro has now been exported. - MI->setExportLocation(MacroNameTok.getLocation()); + MI->setVisibility(/*IsPublic=*/true, MacroNameTok.getLocation()); + + // If this macro definition came from a PCH file, mark it + // as having changed since serialization. + if (MI->isFromAST()) + MI->setChangedAfterLoad(); +} + +/// \brief Handle a #private directive. +void Preprocessor::HandleMacroPrivateDirective(Token &Tok) { + Token MacroNameTok; + ReadMacroName(MacroNameTok, 2); + + // Error reading macro name? If so, diagnostic already issued. + if (MacroNameTok.is(tok::eod)) + return; + + // Check to see if this is the last token on the #__private_macro line. + CheckEndOfDirective("__private_macro"); + + // Okay, we finally have a valid identifier to undef. + MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo()); + + // If the macro is not defined, this is an error. + if (MI == 0) { + Diag(MacroNameTok, diag::err_pp_visibility_non_macro) + << MacroNameTok.getIdentifierInfo(); + return; + } + + // Note that this macro has now been marked private. + MI->setVisibility(/*IsPublic=*/false, MacroNameTok.getLocation()); // If this macro definition came from a PCH file, mark it // as having changed since serialization. @@ -1109,7 +1190,7 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, /// false if the > was found, otherwise it returns true if it finds and consumes /// the EOD marker. bool Preprocessor::ConcatenateIncludeName( - llvm::SmallString<128> &FilenameBuffer, + SmallString<128> &FilenameBuffer, SourceLocation &End) { Token CurTok; @@ -1171,9 +1252,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, CurPPLexer->LexIncludeFilename(FilenameTok); // Reserve a buffer to get the spelling. - llvm::SmallString<128> FilenameBuffer; + SmallString<128> FilenameBuffer; StringRef Filename; SourceLocation End; + SourceLocation CharEnd; // the end of this directive, in characters switch (FilenameTok.getKind()) { case tok::eod: @@ -1184,6 +1266,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, case tok::string_literal: Filename = getSpelling(FilenameTok, FilenameBuffer); End = FilenameTok.getLocation(); + CharEnd = End.getLocWithOffset(Filename.size()); break; case tok::less: @@ -1193,6 +1276,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (ConcatenateIncludeName(FilenameBuffer, End)) return; // Found <eod> but no ">"? Diagnostic already emitted. Filename = FilenameBuffer.str(); + CharEnd = getLocForEndOfToken(End); break; default: Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); @@ -1200,6 +1284,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, return; } + StringRef OriginalFilename = Filename; bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); // If GetIncludeFilenameSpelling set the start ptr to null, there was an @@ -1230,38 +1315,128 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, PragmaARCCFCodeAuditedLoc = SourceLocation(); } + if (HeaderInfo.HasIncludeAliasMap()) { + // Map the filename with the brackets still attached. If the name doesn't + // map to anything, fall back on the filename we've already gotten the + // spelling for. + StringRef NewName = HeaderInfo.MapHeaderToIncludeAlias(OriginalFilename); + if (!NewName.empty()) + Filename = NewName; + } + // Search include directories. const DirectoryLookup *CurDir; - llvm::SmallString<1024> SearchPath; - llvm::SmallString<1024> RelativePath; + SmallString<1024> SearchPath; + SmallString<1024> RelativePath; // We get the raw path only if we have 'Callbacks' to which we later pass // the path. - StringRef SuggestedModule; + Module *SuggestedModule = 0; const FileEntry *File = LookupFile( Filename, isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL, - AutoModuleImport? &SuggestedModule : 0); + getLangOpts().Modules? &SuggestedModule : 0); - // If we are supposed to import a module rather than including the header, - // do so now. - if (!SuggestedModule.empty()) { - TheModuleLoader.loadModule(IncludeTok.getLocation(), - Identifiers.get(SuggestedModule), - FilenameTok.getLocation()); - return; - } - - // Notify the callback object that we've seen an inclusion directive. - if (Callbacks) + if (Callbacks) { + if (!File) { + // Give the clients a chance to recover. + SmallString<128> RecoveryPath; + if (Callbacks->FileNotFound(Filename, RecoveryPath)) { + if (const DirectoryEntry *DE = FileMgr.getDirectory(RecoveryPath)) { + // Add the recovery path to the list of search paths. + DirectoryLookup DL(DE, SrcMgr::C_User, true, false); + 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); + } + } + } + + // Notify the callback object that we've seen an inclusion directive. Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, End, SearchPath, RelativePath); - + } + if (File == 0) { if (!SuppressIncludeNotFoundError) Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; } + // If we are supposed to import a module rather than including the header, + // do so now. + if (SuggestedModule) { + // Compute the module access path corresponding to this module. + // FIXME: Should we have a second loadModule() overload to avoid this + // extra lookup step? + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path; + for (Module *Mod = SuggestedModule; Mod; Mod = Mod->Parent) + Path.push_back(std::make_pair(getIdentifierInfo(Mod->Name), + FilenameTok.getLocation())); + std::reverse(Path.begin(), Path.end()); + + // Warn that we're replacing the include/import with a module import. + SmallString<128> PathString; + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + if (I) + PathString += '.'; + PathString += Path[I].first->getName(); + } + int IncludeKind = 0; + + switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { + case tok::pp_include: + IncludeKind = 0; + break; + + case tok::pp_import: + IncludeKind = 1; + break; + + case tok::pp_include_next: + IncludeKind = 2; + break; + + case tok::pp___include_macros: + IncludeKind = 3; + break; + + default: + llvm_unreachable("unknown include directive kind"); + } + + // Determine whether we are actually building the module that this + // include directive maps to. + bool BuildingImportedModule + = Path[0].first->getName() == getLangOpts().CurrentModule; + + if (!BuildingImportedModule && getLangOpts().ObjC2) { + // If we're not building the imported module, warn that we're going + // to automatically turn this inclusion directive into a module import. + // We only do this in Objective-C, where we have a module-import syntax. + CharSourceRange ReplaceRange(SourceRange(HashLoc, CharEnd), + /*IsTokenRange=*/false); + Diag(HashLoc, diag::warn_auto_module_import) + << IncludeKind << PathString + << FixItHint::CreateReplacement(ReplaceRange, + "@__experimental_modules_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; + Module *Imported + = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility, + /*IsIncludeDirective=*/true); + + // If this header isn't part of the module we're building, we're done. + if (!BuildingImportedModule && Imported) + return; + } + // The #included file will be considered to be a system header if either it is // in a system include directory, or if the #includer is a system include // header. @@ -1278,8 +1453,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } // Look up the file, create a File ID for it. - FileID FID = SourceMgr.createFileID(File, FilenameTok.getLocation(), - FileCharacter); + SourceLocation IncludePos = End; + // If the filename string was the result of macro expansions, set the include + // position on the file where it will be included and after the expansions. + if (IncludePos.isMacroID()) + IncludePos = SourceMgr.getExpansionRange(IncludePos).second; + FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter); assert(!FID.isInvalid() && "Expected valid file ID"); // Finally, if all is good, enter the new file! @@ -1309,13 +1488,29 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc, return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup); } +/// HandleMicrosoftImportDirective - Implements #import for Microsoft Mode +void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) { + // The Microsoft #import directive takes a type library and generates header + // files from it, and includes those. This is beyond the scope of what clang + // does, so we ignore it and error out. However, #import can optionally have + // trailing attributes that span multiple lines. We're going to eat those + // so we can continue processing from there. + Diag(Tok, diag::err_pp_import_directive_ms ); + + // Read tokens until we get to the end of the directive. Note that the + // directive can be split over multiple lines using the backslash character. + DiscardUntilEndOfDirective(); +} + /// HandleImportDirective - Implements #import. /// void Preprocessor::HandleImportDirective(SourceLocation HashLoc, Token &ImportTok) { - if (!Features.ObjC1) // #import is standard for ObjC. + if (!LangOpts.ObjC1) { // #import is standard for ObjC. + if (LangOpts.MicrosoftMode) + return HandleMicrosoftImportDirective(ImportTok); Diag(ImportTok, diag::ext_pp_import_directive); - + } return HandleIncludeDirective(HashLoc, ImportTok, 0, true); } @@ -1354,10 +1549,9 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc, /// definition has just been read. Lex the rest of the arguments and the /// closing ), updating MI with what we learn. Return true if an error occurs /// parsing the arg list. -bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { +bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { SmallVector<IdentifierInfo*, 32> Arguments; - Token Tok; while (1) { LexUnexpandedToken(Tok); switch (Tok.getKind()) { @@ -1369,8 +1563,8 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { Diag(Tok, diag::err_pp_expected_ident_in_arg_list); return true; case tok::ellipsis: // #define X(... -> C99 varargs - if (!Features.C99) - Diag(Tok, Features.CPlusPlus0x ? + if (!LangOpts.C99) + Diag(Tok, LangOpts.CPlusPlus0x ? diag::warn_cxx98_compat_variadic_macro : diag::ext_variadic_macro); @@ -1476,7 +1670,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { } else if (Tok.is(tok::l_paren)) { // This is a function-like macro definition. Read the argument list. MI->setIsFunctionLike(); - if (ReadMacroDefinitionArgList(MI)) { + if (ReadMacroDefinitionArgList(MI, LastTok)) { // Forget about MI. ReleaseMacroInfo(MI); // Throw away the rest of the line. @@ -1496,7 +1690,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // Read the first token after the arg list for down below. LexUnexpandedToken(Tok); - } else if (Features.C99 || Features.CPlusPlus0x) { + } else if (LangOpts.C99 || LangOpts.CPlusPlus0x) { // C99 requires whitespace between the macro definition and the body. Emit // a diagnostic for something like "#define X+". Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name); @@ -1561,7 +1755,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // the '#' because '#' is often a comment character. However, change // the kind of the token to tok::unknown so that the preprocessor isn't // confused. - if (getLangOptions().AsmPreprocessor && Tok.isNot(tok::eod)) { + if (getLangOpts().AsmPreprocessor && Tok.isNot(tok::eod)) { LastTok.setKind(tok::unknown); } else { Diag(Tok, diag::err_pp_stringize_not_parameter); @@ -1732,6 +1926,13 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, if (MI) // Mark it used. markMacroAsUsed(MI); + if (Callbacks) { + if (isIfndef) + Callbacks->Ifndef(DirectiveTok.getLocation(), MacroNameTok); + else + Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok); + } + // Should we include the stuff contained by this directive? if (!MI == isIfndef) { // Yes, remember that we are inside a conditional, then lex the next token. @@ -1744,13 +1945,6 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, /*Foundnonskip*/false, /*FoundElse*/false); } - - if (Callbacks) { - if (isIfndef) - Callbacks->Ifndef(MacroNameTok); - else - Callbacks->Ifdef(MacroNameTok); - } } /// HandleIfDirective - Implements the #if directive. @@ -1774,6 +1968,10 @@ void Preprocessor::HandleIfDirective(Token &IfToken, CurPPLexer->MIOpt.EnterTopLevelConditional(); } + if (Callbacks) + Callbacks->If(IfToken.getLocation(), + SourceRange(ConditionalBegin, ConditionalEnd)); + // Should we include the stuff contained by this directive? if (ConditionalTrue) { // Yes, remember that we are inside a conditional, then lex the next token. @@ -1784,9 +1982,6 @@ void Preprocessor::HandleIfDirective(Token &IfToken, SkipExcludedConditionalBlock(IfToken.getLocation(), /*Foundnonskip*/false, /*FoundElse*/false); } - - if (Callbacks) - Callbacks->If(SourceRange(ConditionalBegin, ConditionalEnd)); } /// HandleEndifDirective - Implements the #endif directive. @@ -1812,7 +2007,7 @@ void Preprocessor::HandleEndifDirective(Token &EndifToken) { "This code should only be reachable in the non-skipping case!"); if (Callbacks) - Callbacks->Endif(); + Callbacks->Endif(EndifToken.getLocation(), CondInfo.IfLoc); } /// HandleElseDirective - Implements the #else directive. @@ -1836,12 +2031,12 @@ void Preprocessor::HandleElseDirective(Token &Result) { // If this is a #else with a #else before it, report the error. if (CI.FoundElse) Diag(Result, diag::pp_err_else_after_else); + if (Callbacks) + Callbacks->Else(Result.getLocation(), CI.IfLoc); + // Finally, skip the rest of the contents of this block. SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, /*FoundElse*/true, Result.getLocation()); - - if (Callbacks) - Callbacks->Else(); } /// HandleElifDirective - Implements the #elif directive. @@ -1868,12 +2063,13 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) { // If this is a #elif with a #else before it, report the error. if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else); + + if (Callbacks) + Callbacks->Elif(ElifToken.getLocation(), + SourceRange(ConditionalBegin, ConditionalEnd), CI.IfLoc); // Finally, skip the rest of the contents of this block. SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, /*FoundElse*/CI.FoundElse, ElifToken.getLocation()); - - if (Callbacks) - Callbacks->Elif(SourceRange(ConditionalBegin, ConditionalEnd)); } |