diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/IdentifierTable.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Format/UnwrappedLineParser.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Index/IndexingAction.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Lex/Lexer.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Lex/PPConditionalDirectiveRecord.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 102 | ||||
-rw-r--r-- | clang/lib/Lex/PreprocessingRecord.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 12 |
10 files changed, 171 insertions, 13 deletions
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index e591530..3c18219 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -341,9 +341,11 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { CASE( 6, 'p', 'a', pragma); CASE( 7, 'd', 'f', defined); + CASE( 7, 'e', 'i', elifdef); CASE( 7, 'i', 'c', include); CASE( 7, 'w', 'r', warning); + CASE( 8, 'e', 'i', elifndef); CASE( 8, 'u', 'a', unassert); CASE(12, 'i', 'c', include_next); diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 4edfe7c..0fb5428 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -751,6 +751,8 @@ void UnwrappedLineParser::parsePPDirective() { case tok::pp_else: parsePPElse(); break; + case tok::pp_elifdef: + case tok::pp_elifndef: case tok::pp_elif: parsePPElIf(); break; diff --git a/clang/lib/Index/IndexingAction.cpp b/clang/lib/Index/IndexingAction.cpp index 6152e2c..65479a4 100644 --- a/clang/lib/Index/IndexingAction.cpp +++ b/clang/lib/Index/IndexingAction.cpp @@ -77,6 +77,23 @@ public: MacroNameTok.getLocation(), *MD.getMacroInfo()); } + + void Elifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + if (!MD.getMacroInfo()) // Ignore non-existent macro. + return; + IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation(), + *MD.getMacroInfo()); + } + void Elifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + if (!MD.getMacroInfo()) // Ignore non-existent macro. + return; + IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation(), + *MD.getMacroInfo()); + } }; class IndexASTConsumer final : public ASTConsumer { diff --git a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp index cdb4a79..cfca167 100644 --- a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp +++ b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp @@ -846,6 +846,8 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) { .Case("ifdef", pp_ifdef) .Case("ifndef", pp_ifndef) .Case("elif", pp_elif) + .Case("elifdef", pp_elifdef) + .Case("elifndef", pp_elifndef) .Case("else", pp_else) .Case("endif", pp_endif) .Case("pragma", pp_pragma_import) @@ -904,7 +906,7 @@ bool clang::minimize_source_to_dependency_directives::computeSkippedRanges( struct Directive { enum DirectiveKind { If, // if/ifdef/ifndef - Else // elif,else + Else // elif/elifdef/elifndef, else }; int Offset; DirectiveKind Kind; @@ -919,6 +921,8 @@ bool clang::minimize_source_to_dependency_directives::computeSkippedRanges( break; case pp_elif: + case pp_elifdef: + case pp_elifndef: case pp_else: { if (Offsets.empty()) return true; diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index d31987a..cb2b19b 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -682,6 +682,8 @@ PreambleBounds Lexer::ComputePreamble(StringRef Buffer, .Case("ifdef", PDK_Skipped) .Case("ifndef", PDK_Skipped) .Case("elif", PDK_Skipped) + .Case("elifdef", PDK_Skipped) + .Case("elifndef", PDK_Skipped) .Case("else", PDK_Skipped) .Case("endif", PDK_Skipped) .Default(PDK_Unknown); diff --git a/clang/lib/Lex/PPConditionalDirectiveRecord.cpp b/clang/lib/Lex/PPConditionalDirectiveRecord.cpp index facee28..ddc88f8 100644 --- a/clang/lib/Lex/PPConditionalDirectiveRecord.cpp +++ b/clang/lib/Lex/PPConditionalDirectiveRecord.cpp @@ -101,6 +101,28 @@ void PPConditionalDirectiveRecord::Elif(SourceLocation Loc, CondDirectiveStack.back() = Loc; } +void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, const Token &, + const MacroDefinition &) { + addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); + CondDirectiveStack.back() = Loc; +} +void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, SourceRange, + SourceLocation) { + addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); + CondDirectiveStack.back() = Loc; +} + +void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, const Token &, + const MacroDefinition &) { + addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); + CondDirectiveStack.back() = Loc; +} +void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, SourceRange, + SourceLocation) { + addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); + CondDirectiveStack.back() = Loc; +} + void PPConditionalDirectiveRecord::Else(SourceLocation Loc, SourceLocation IfLoc) { addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index a74b42a..1ccf24c 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -100,6 +100,14 @@ enum MacroDiag { MD_ReservedMacro //> #define of #undef reserved id, disabled by default }; +/// Enumerates possible %select values for the pp_err_elif_after_else and +/// pp_err_elif_without_if diagnostics. +enum PPElifDiag { + PED_Elif, + PED_Elifdef, + PED_Elifndef +}; + // The -fmodule-name option tells the compiler to textually include headers in // the specified module, meaning clang won't build the specified module. This is // useful in a number of situations, for instance, when building a library that @@ -578,7 +586,8 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel(); // If this is a #else with a #else before it, report the error. - if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_else_after_else); + if (CondInfo.FoundElse) + Diag(Tok, diag::pp_err_else_after_else) << PED_Elif; // Note that we've seen a #else in this conditional. CondInfo.FoundElse = true; @@ -632,6 +641,59 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, break; } } + } else if (Sub == "lifdef" || // "elifdef" + Sub == "lifndef") { // "elifndef" + bool IsElifDef = Sub == "lifdef"; + PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel(); + Token DirectiveToken = Tok; + + // If this is a #elif with a #else before it, report the error. + if (CondInfo.FoundElse) + Diag(Tok, diag::pp_err_elif_after_else) + << (IsElifDef ? PED_Elifdef : PED_Elifndef); + + // If this is in a skipping block or if we're already handled this #if + // block, don't bother parsing the condition. + if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) { + DiscardUntilEndOfDirective(); + } else { + // Restore the value of LexingRawMode so that identifiers are + // looked up, etc, inside the #elif[n]def expression. + assert(CurPPLexer->LexingRawMode && "We have to be skipping here!"); + CurPPLexer->LexingRawMode = false; + Token MacroNameTok; + ReadMacroName(MacroNameTok); + CurPPLexer->LexingRawMode = true; + + // If the macro name token is tok::eod, there was an error that was + // already reported. + if (MacroNameTok.is(tok::eod)) { + // Skip code until we get to #endif. This helps with recovery by + // not emitting an error when the #endif is reached. + continue; + } + + CheckEndOfDirective(IsElifDef ? "elifdef" : "elifndef"); + + IdentifierInfo *MII = MacroNameTok.getIdentifierInfo(); + auto MD = getMacroDefinition(MII); + MacroInfo *MI = MD.getMacroInfo(); + + if (Callbacks) { + if (IsElifDef) { + Callbacks->Elifdef(DirectiveToken.getLocation(), MacroNameTok, + MD); + } else { + Callbacks->Elifndef(DirectiveToken.getLocation(), MacroNameTok, + MD); + } + } + // If this condition is true, enter it! + if (static_cast<bool>(MI) == IsElifDef) { + CondInfo.FoundNonSkip = true; + break; + } + } } } @@ -1015,7 +1077,10 @@ void Preprocessor::HandleDirective(Token &Result) { return HandleIfdefDirective(Result, SavedHash, true, ReadAnyTokensBeforeDirective); case tok::pp_elif: - return HandleElifDirective(Result, SavedHash); + case tok::pp_elifdef: + case tok::pp_elifndef: + return HandleElifFamilyDirective(Result, SavedHash, II->getPPKeywordID()); + case tok::pp_else: return HandleElseDirective(Result, SavedHash); case tok::pp_endif: @@ -3154,10 +3219,13 @@ void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) { /*FoundElse*/ true, Result.getLocation()); } -/// HandleElifDirective - Implements the \#elif directive. -/// -void Preprocessor::HandleElifDirective(Token &ElifToken, - const Token &HashToken) { +/// Implements the \#elif, \#elifdef, and \#elifndef directives. +void Preprocessor::HandleElifFamilyDirective(Token &ElifToken, + const Token &HashToken, + tok::PPKeywordKind Kind) { + PPElifDiag DirKind = Kind == tok::pp_elif ? PED_Elif + : Kind == tok::pp_elifdef ? PED_Elifdef + : PED_Elifndef; ++NumElse; // #elif directive in a non-skipping conditional... start skipping. @@ -3167,7 +3235,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken, PPConditionalInfo CI; if (CurPPLexer->popConditionalLevel(CI)) { - Diag(ElifToken, diag::pp_err_elif_without_if); + Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind; return; } @@ -3176,11 +3244,23 @@ void Preprocessor::HandleElifDirective(Token &ElifToken, CurPPLexer->MIOpt.EnterTopLevelConditional(); // 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 (CI.FoundElse) + Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind; - if (Callbacks) - Callbacks->Elif(ElifToken.getLocation(), ConditionRange, - PPCallbacks::CVK_NotEvaluated, CI.IfLoc); + if (Callbacks) { + switch (Kind) { + case tok::pp_elif: + Callbacks->Elif(ElifToken.getLocation(), ConditionRange, + PPCallbacks::CVK_NotEvaluated, CI.IfLoc); + break; + case tok::pp_elifdef: + Callbacks->Elifdef(ElifToken.getLocation(), ConditionRange, CI.IfLoc); + break; + case tok::pp_elifndef: + Callbacks->Elifndef(ElifToken.getLocation(), ConditionRange, CI.IfLoc); + break; + } + } bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks && getSourceManager().isInMainFile(ElifToken.getLocation()); diff --git a/clang/lib/Lex/PreprocessingRecord.cpp b/clang/lib/Lex/PreprocessingRecord.cpp index 115256d..ed59dbd 100644 --- a/clang/lib/Lex/PreprocessingRecord.cpp +++ b/clang/lib/Lex/PreprocessingRecord.cpp @@ -411,6 +411,14 @@ void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok, MacroNameTok.getLocation()); } +void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) { + // This is not actually a macro expansion but record it as a macro reference. + if (MD) + addMacroExpansion(MacroNameTok, MD.getMacroInfo(), + MacroNameTok.getLocation()); +} + void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) { // This is not actually a macro expansion but record it as a macro reference. @@ -419,6 +427,15 @@ void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok, MacroNameTok.getLocation()); } +void PreprocessingRecord::Elifndef(SourceLocation Loc, + const Token &MacroNameTok, + const MacroDefinition &MD) { + // This is not actually a macro expansion but record it as a macro reference. + if (MD) + addMacroExpansion(MacroNameTok, MD.getMacroInfo(), + MacroNameTok.getLocation()); +} + void PreprocessingRecord::Defined(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range) { diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index e39b78d..e376fff 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -274,7 +274,7 @@ void Preprocessor::PrintStats() { llvm::errs() << " " << NumEnteredSourceFiles << " source files entered.\n"; llvm::errs() << " " << MaxIncludeStackDepth << " max include stack depth\n"; llvm::errs() << " " << NumIf << " #if/#ifndef/#ifdef.\n"; - llvm::errs() << " " << NumElse << " #else/#elif.\n"; + llvm::errs() << " " << NumElse << " #else/#elif/#elifdef/#elifndef.\n"; llvm::errs() << " " << NumEndif << " #endif.\n"; llvm::errs() << " " << NumPragma << " #pragma.\n"; llvm::errs() << NumSkipped << " #if/#ifndef#ifdef regions skipped\n"; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 8893bd2..0bde8ea 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -9198,6 +9198,18 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("condition"); Results.AddResult(Builder.TakeString()); + // #elifdef <macro> + Builder.AddTypedTextChunk("elifdef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #elifndef <macro> + Builder.AddTypedTextChunk("elifndef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + // #else Builder.AddTypedTextChunk("else"); Results.AddResult(Builder.TakeString()); |