Index: clang/include/clang/Basic/DiagnosticLexKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticLexKinds.td
+++ clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -455,9 +455,11 @@
 def err_pp_unterminated_conditional : Error<
   "unterminated conditional directive">;
 def pp_err_else_after_else : Error<"#else after #else">;
-def pp_err_elif_after_else : Error<"#elif after #else">;
+def pp_err_elif_after_else : Error<
+  "%select{#elif|#elifdef|#elifndef}0 after #else">;
 def pp_err_else_without_if : Error<"#else without #if">;
-def pp_err_elif_without_if : Error<"#elif without #if">;
+def pp_err_elif_without_if : Error<
+  "%select{#elif|#elifdef|#elifndef}0 without #if">;
 def err_pp_endif_without_if : Error<"#endif without #if">;
 def err_pp_expected_value_in_expr : Error<"expected value in expression">;
 def err_pp_expected_rparen : Error<"expected ')' in preprocessor expression">;
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -98,6 +98,8 @@
 PPKEYWORD(ifdef)
 PPKEYWORD(ifndef)
 PPKEYWORD(elif)
+PPKEYWORD(elifdef)
+PPKEYWORD(elifndef)
 PPKEYWORD(else)
 PPKEYWORD(endif)
 PPKEYWORD(defined)
Index: clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
===================================================================
--- clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
+++ clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
@@ -44,6 +44,8 @@
   pp_ifdef,
   pp_ifndef,
   pp_elif,
+  pp_elifdef,
+  pp_elifndef,
   pp_else,
   pp_endif,
   decl_at_import,
Index: clang/include/clang/Lex/PPCallbacks.h
===================================================================
--- clang/include/clang/Lex/PPCallbacks.h
+++ clang/include/clang/Lex/PPCallbacks.h
@@ -351,6 +351,14 @@
                      const MacroDefinition &MD) {
   }
 
+  /// Hook called whenever an \#elifdef is seen.
+  /// \param Loc the source location of the directive.
+  /// \param MacroNameTok Information on the token being tested.
+  /// \param MD The MacroDefinition if the name was a macro, null otherwise.
+  virtual void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+                       const MacroDefinition &MD) {
+  }
+
   /// Hook called whenever an \#ifndef is seen.
   /// \param Loc the source location of the directive.
   /// \param MacroNameTok Information on the token being tested.
@@ -359,6 +367,14 @@
                       const MacroDefinition &MD) {
   }
 
+  /// Hook called whenever an \#elifndef is seen.
+  /// \param Loc the source location of the directive.
+  /// \param MacroNameTok Information on the token being tested.
+  /// \param MD The MacroDefinition if the name was a macro, null otherwise.
+  virtual void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+                        const MacroDefinition &MD) {
+  }
+
   /// Hook called whenever an \#else is seen.
   /// \param Loc the source location of the directive.
   /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
@@ -586,6 +602,13 @@
     Second->Ifdef(Loc, MacroNameTok, MD);
   }
 
+  /// Hook called whenever an \#elifdef is seen.
+  void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+               const MacroDefinition &MD) override {
+    First->Elifdef(Loc, MacroNameTok, MD);
+    Second->Elifdef(Loc, MacroNameTok, MD);
+  }
+
   /// Hook called whenever an \#ifndef is seen.
   void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
               const MacroDefinition &MD) override {
@@ -593,6 +616,13 @@
     Second->Ifndef(Loc, MacroNameTok, MD);
   }
 
+  /// Hook called whenever an \#elifndef is seen.
+  void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+                const MacroDefinition &MD) override {
+    First->Elifndef(Loc, MacroNameTok, MD);
+    Second->Elifndef(Loc, MacroNameTok, MD);
+  }
+
   /// Hook called whenever an \#else is seen.
   void Else(SourceLocation Loc, SourceLocation IfLoc) override {
     First->Else(Loc, IfLoc);
Index: clang/include/clang/Lex/PPConditionalDirectiveRecord.h
===================================================================
--- clang/include/clang/Lex/PPConditionalDirectiveRecord.h
+++ clang/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -93,6 +93,10 @@
              const MacroDefinition &MD) override;
   void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
               const MacroDefinition &MD) override;
+  void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+               const MacroDefinition &MD) override;
+  void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+                const MacroDefinition &MD) override;
   void Else(SourceLocation Loc, SourceLocation IfLoc) override;
   void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
 };
Index: clang/include/clang/Lex/PreprocessingRecord.h
===================================================================
--- clang/include/clang/Lex/PreprocessingRecord.h
+++ clang/include/clang/Lex/PreprocessingRecord.h
@@ -538,6 +538,10 @@
                const MacroDefinition &MD) override;
     void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
                 const MacroDefinition &MD) override;
+    void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+                 const MacroDefinition &MD) override;
+    void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+                  const MacroDefinition &MD) override;
 
     /// Hook called whenever the 'defined' operator is seen.
     void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -2358,6 +2358,9 @@
   void HandleEndifDirective(Token &EndifToken);
   void HandleElseDirective(Token &Result, const Token &HashToken);
   void HandleElifDirective(Token &ElifToken, const Token &HashToken);
+  void HandleElifdefDirective(Token &Result, const Token &HashToken,
+                              bool isElifndef,
+                              bool ReadAnyTokensBeforeDirective);
 
   // Pragmas.
   void HandlePragmaDirective(PragmaIntroducer Introducer);
Index: clang/lib/Basic/IdentifierTable.cpp
===================================================================
--- clang/lib/Basic/IdentifierTable.cpp
+++ clang/lib/Basic/IdentifierTable.cpp
@@ -308,9 +308,11 @@
   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);
 
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -751,6 +751,8 @@
   case tok::pp_else:
     parsePPElse();
     break;
+  case tok::pp_elifdef:
+  case tok::pp_elifndef:
   case tok::pp_elif:
     parsePPElIf();
     break;
Index: clang/lib/Index/IndexingAction.cpp
===================================================================
--- clang/lib/Index/IndexingAction.cpp
+++ clang/lib/Index/IndexingAction.cpp
@@ -77,6 +77,23 @@
                                    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 {
Index: clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
===================================================================
--- clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
+++ clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
@@ -846,6 +846,8 @@
                   .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)
@@ -919,6 +921,8 @@
       break;
 
     case pp_elif:
+    case pp_elifdef:
+    case pp_elifndef:
     case pp_else: {
       if (Offsets.empty())
         return true;
Index: clang/lib/Lex/Lexer.cpp
===================================================================
--- clang/lib/Lex/Lexer.cpp
+++ clang/lib/Lex/Lexer.cpp
@@ -682,6 +682,8 @@
               .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);
Index: clang/lib/Lex/PPConditionalDirectiveRecord.cpp
===================================================================
--- clang/lib/Lex/PPConditionalDirectiveRecord.cpp
+++ clang/lib/Lex/PPConditionalDirectiveRecord.cpp
@@ -101,6 +101,20 @@
   CondDirectiveStack.back() = Loc;
 }
 
+void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc,
+                                           const Token &MacroNameTok,
+                                           const MacroDefinition &MD) {
+  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
+  CondDirectiveStack.back() = Loc;
+}
+
+void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc,
+                                            const Token &MacroNameTok,
+                                            const MacroDefinition &MD) {
+  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
+  CondDirectiveStack.back() = Loc;
+}
+
 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
                                         SourceLocation IfLoc) {
   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -100,6 +100,14 @@
   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
+};
+
 /// Checks if the specified identifier is reserved in the specified
 /// language.
 /// This function does not check if the identifier is a keyword.
@@ -582,7 +590,8 @@
         PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
 
         // 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 (CondInfo.FoundElse)
+          Diag(Tok, diag::pp_err_elif_after_else) << PED_Elif;
 
         // If this is in a skipping block or if we're already handled this #if
         // block, don't bother parsing the condition.
@@ -609,6 +618,59 @@
             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;
+          }
+        }
       }
     }
 
@@ -993,6 +1055,12 @@
                                   ReadAnyTokensBeforeDirective);
     case tok::pp_elif:
       return HandleElifDirective(Result, SavedHash);
+    case tok::pp_elifdef:
+      return HandleElifdefDirective(Result, SavedHash, false,
+                                    true /*not valid for miopt*/);
+    case tok::pp_elifndef:
+      return HandleElifdefDirective(Result, SavedHash, true,
+                                    ReadAnyTokensBeforeDirective);
     case tok::pp_else:
       return HandleElseDirective(Result, SavedHash);
     case tok::pp_endif:
@@ -3140,7 +3208,7 @@
 
   PPConditionalInfo CI;
   if (CurPPLexer->popConditionalLevel(CI)) {
-    Diag(ElifToken, diag::pp_err_elif_without_if);
+    Diag(ElifToken, diag::pp_err_elif_without_if) << PED_Elif;
     return;
   }
 
@@ -3149,7 +3217,8 @@
     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) << PED_Elif;
 
   if (Callbacks)
     Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
@@ -3171,3 +3240,84 @@
       HashToken.getLocation(), CI.IfLoc, /*Foundnonskip*/ true,
       /*FoundElse*/ CI.FoundElse, ElifToken.getLocation());
 }
+
+/// HandleElifdefDirective - Implements the \#elifdef/\#elifndef directive.
+/// isElifndef is true when this is a \#elifndef directive.
+/// ReadAnyTokensBeforeDirective is true if any tokens have been returned or
+/// pp-directives activated before this \#elifndef has been lexed.
+void Preprocessor::HandleElifdefDirective(Token &Result, const Token &HashToken,
+                                          bool isElifndef,
+                                          bool ReadAnyTokensBeforeDirective) {
+  ++NumElse;
+  Token DirectiveTok = Result;
+
+  Token MacroNameTok;
+  ReadMacroName(MacroNameTok);
+
+  // Error reading macro name?  If so, diagnostic already issued.
+  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.
+    SkipExcludedConditionalBlock(HashToken.getLocation(),
+                                 DirectiveTok.getLocation(),
+                                 /*Foundnonskip*/ false, /*FoundElse*/ false);
+    return;
+  }
+
+  // Check to see if this is the last token on the #elif[n]def line.
+  CheckEndOfDirective(isElifndef ? "elifndef" : "elifdef");
+
+  PPConditionalInfo CI;
+  if (CurPPLexer->popConditionalLevel(CI)) {
+    Diag(DirectiveTok, diag::pp_err_elif_without_if)
+        << (isElifndef ? PED_Elifndef : PED_Elifdef);
+    return;
+  }
+
+  if (CurPPLexer->getConditionalStackDepth() == 0)
+    CurPPLexer->MIOpt.EnterTopLevelConditional();
+
+  // If this is a #elif[n]def with a #else before it, report the error.
+  if (CI.FoundElse)
+    Diag(DirectiveTok, diag::pp_err_elif_after_else)
+        << (isElifndef ? PED_Elifndef : PED_Elifdef);
+
+  IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
+  auto MD = getMacroDefinition(MII);
+  MacroInfo *MI = MD.getMacroInfo();
+
+  // If there is a macro, process it.
+  if (MI) // Mark it used.
+    markMacroAsUsed(MI);
+
+  if (Callbacks) {
+    if (isElifndef)
+      Callbacks->Elifndef(DirectiveTok.getLocation(), MacroNameTok, MD);
+    else
+      Callbacks->Elifdef(DirectiveTok.getLocation(), MacroNameTok, MD);
+  }
+
+  bool RetainExcludedCB =
+      PPOpts->RetainExcludedConditionalBlocks &&
+      getSourceManager().isInMainFile(DirectiveTok.getLocation());
+
+  // Should we include the stuff contained by this directive?
+  if (PPOpts->SingleFileParseMode && !MI) {
+    // In 'single-file-parse mode' undefined identifiers trigger parsing of all
+    // the directive blocks.
+    CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
+                                     /*wasskip*/ false, /*foundnonskip*/ false,
+                                     /*foundelse*/ false);
+  } else if (!MI == isElifndef || RetainExcludedCB) {
+    // Yes, remember that we are inside a conditional, then lex the next token.
+    CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
+                                     /*wasskip*/ false, /*foundnonskip*/ true,
+                                     /*foundelse*/ false);
+  } else {
+    // No, skip the contents of this block.
+    SkipExcludedConditionalBlock(HashToken.getLocation(),
+                                 DirectiveTok.getLocation(),
+                                 /*Foundnonskip*/ false,
+                                 /*FoundElse*/ false);
+  }
+}
Index: clang/lib/Lex/PreprocessingRecord.cpp
===================================================================
--- clang/lib/Lex/PreprocessingRecord.cpp
+++ clang/lib/Lex/PreprocessingRecord.cpp
@@ -411,6 +411,14 @@
                       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 @@
                       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) {
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -274,7 +274,7 @@
   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";
Index: clang/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -9199,6 +9199,18 @@
     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());
Index: clang/test/Index/complete-preprocessor.m
===================================================================
--- clang/test/Index/complete-preprocessor.m
+++ clang/test/Index/complete-preprocessor.m
@@ -35,6 +35,8 @@
 // CHECK-CC2: NotImplemented:{TypedText define}{HorizontalSpace  }{Placeholder macro} (40)
 // CHECK-CC2-NEXT: NotImplemented:{TypedText define}{HorizontalSpace  }{Placeholder macro}{LeftParen (}{Placeholder args}{RightParen )} (40)
 // CHECK-CC2-NEXT: NotImplemented:{TypedText elif}{HorizontalSpace  }{Placeholder condition} (40)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText elifdef}{HorizontalSpace  }{Placeholder macro} (40)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText elifndef}{HorizontalSpace  }{Placeholder macro} (40)
 // CHECK-CC2-NEXT: NotImplemented:{TypedText else} (40)
 // CHECK-CC2-NEXT: NotImplemented:{TypedText endif} (40)
 // CHECK-CC2-NEXT: NotImplemented:{TypedText error}{HorizontalSpace  }{Placeholder message} (40)
Index: clang/test/Preprocessor/elifdef.c
===================================================================
--- /dev/null
+++ clang/test/Preprocessor/elifdef.c
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 %s -Eonly -verify
+
+#ifdef FOO
+#elifdef BAR
+#error "did not expect to get here"
+#endif
+
+/* expected-error@+4 {{"got it"}} */
+#ifdef FOO
+#elifdef BAR
+#else
+#error "got it"
+#endif
+
+/* expected-error@+3 {{"got it"}} */
+#ifdef FOO
+#elifndef BAR
+#error "got it"
+#endif
+
+/* expected-error@+3 {{"got it"}} */
+#ifdef FOO
+#elifndef BAR
+#error "got it"
+#else
+#error "did not expect to get here"
+#endif
+
+#define BAR
+/* expected-error@+3 {{"got it"}} */
+#ifdef FOO
+#elifdef BAR
+#error "got it"
+#endif
+#undef BAR
+
+#ifdef FOO
+#elifdef BAR // test that comments aren't an issue
+#error "did not expect to get here"
+#endif
+
+/* expected-error@+4 {{"got it"}} */
+#ifdef FOO
+#elifdef BAR // test that comments aren't an issue
+#else
+#error "got it"
+#endif
+
+/* expected-error@+3 {{"got it"}} */
+#ifdef FOO
+#elifndef BAR // test that comments aren't an issue
+#error "got it"
+#endif
+
+/* expected-error@+3 {{"got it"}} */
+#ifdef FOO
+#elifndef BAR // test that comments aren't an issue
+#error "got it"
+#else
+#error "did not expect to get here"
+#endif
+
+#define BAR
+/* expected-error@+3 {{"got it"}} */
+#ifdef FOO
+#elifdef BAR // test that comments aren't an issue
+#error "got it"
+#endif
+#undef BAR
+
+#define BAR
+/* expected-error@+6 {{"got it"}} */
+#ifdef FOO
+#error "did not expect to get here"
+#elifndef BAR
+#error "did not expect to get here"
+#else
+#error "got it"
+#endif
+#undef BAR
+
+/* expected-error@+3 {{#elifdef after #else}} */
+#ifdef FOO
+#else
+#elifdef BAR
+#endif
+
+/* expected-error@+3 {{#elifndef after #else}} */
+#ifdef FOO
+#else
+#elifndef BAR
+#endif
+
+#elifdef FOO /* expected-error {{#elifdef without #if}} */
+#endif       /* expected-error {{#endif without #if}} */
+
+#elifndef FOO /* expected-error {{#elifndef without #if}} */
+#endif        /* expected-error {{#endif without #if}} */
Index: clang/test/Preprocessor/if_warning.c
===================================================================
--- clang/test/Preprocessor/if_warning.c
+++ clang/test/Preprocessor/if_warning.c
@@ -6,6 +6,7 @@
 #endif
 
 #ifdef foo
+#elifdef foo
 #endif
 
 #if defined(foo)
@@ -15,6 +16,7 @@
 // PR3938
 #if 0
 #ifdef D
+#elifdef D
 #else 1       // Should not warn due to C99 6.10p4
 #endif
 #endif
Index: clang/test/Preprocessor/ifdef-recover.c
===================================================================
--- clang/test/Preprocessor/ifdef-recover.c
+++ clang/test/Preprocessor/ifdef-recover.c
@@ -19,4 +19,14 @@
 #if f(2
 #endif
 
+/* expected-error@+2 {{macro name missing}} */
+#ifdef FOO
+#elifdef
+#endif
+
+/* expected-error@+2 {{macro name must be an identifier}} */
+#ifdef FOO
+#elifdef !
+#endif
+
 int x;
Index: clang/test/Preprocessor/macro_misc.c
===================================================================
--- clang/test/Preprocessor/macro_misc.c
+++ clang/test/Preprocessor/macro_misc.c
@@ -2,6 +2,7 @@
 
 // This should not be rejected.
 #ifdef defined
+#elifdef defined
 #endif
 
 
Index: clang/test/Preprocessor/macro_vaopt_check.cpp
===================================================================
--- clang/test/Preprocessor/macro_vaopt_check.cpp
+++ clang/test/Preprocessor/macro_vaopt_check.cpp
@@ -68,7 +68,9 @@
 #if __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}}
 #endif
 
+// expected-warning@+2 {{__VA_OPT__ can only appear in the expansion of a variadic macro}}
 #ifdef __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}}
+#elifdef __VA_OPT__
 #endif
 
 #define BAD __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}}