Index: llvm/lib/TableGen/TGLexer.h =================================================================== --- llvm/lib/TableGen/TGLexer.h +++ llvm/lib/TableGen/TGLexer.h @@ -65,7 +65,7 @@ // Preprocessing tokens for internal usage by the lexer. // They are never returned as a result of Lex(). - Ifdef, Else, Endif, Define + Ifdef, Ifndef, Else, Endif, Define }; } Index: llvm/lib/TableGen/TGLexer.cpp =================================================================== --- llvm/lib/TableGen/TGLexer.cpp +++ llvm/lib/TableGen/TGLexer.cpp @@ -36,6 +36,7 @@ const char *Word; } PreprocessorDirs[] = { { tgtok::Ifdef, "ifdef" }, + { tgtok::Ifndef, "ifndef" }, { tgtok::Else, "else" }, { tgtok::Endif, "endif" }, { tgtok::Define, "define" } @@ -676,21 +677,28 @@ PrintFatalError("lexPreprocessor() called for unknown " "preprocessor directive"); - if (Kind == tgtok::Ifdef) { + if (Kind == tgtok::Ifdef || Kind == tgtok::Ifndef) { StringRef MacroName = prepLexMacroName(); + StringRef IfTokName = Kind == tgtok::Ifdef ? "#ifdef" : "#ifndef"; if (MacroName.empty()) - return ReturnError(TokStart, "Expected macro name after #ifdef"); + return ReturnError(TokStart, "Expected macro name after " + IfTokName); bool MacroIsDefined = DefinedMacros.count(MacroName) != 0; + // Canonicalize ifndef to ifdef equivalent + if (Kind == tgtok::Ifndef) { + MacroIsDefined = !MacroIsDefined; + Kind = tgtok::Ifdef; + } + // Regardless of whether we are processing tokens or not, // we put the #ifdef control on stack. PrepIncludeStack.back()->push_back( {Kind, MacroIsDefined, SMLoc::getFromPointer(TokStart)}); if (!prepSkipDirectiveEnd()) - return ReturnError(CurPtr, - "Only comments are supported after #ifdef NAME"); + return ReturnError(CurPtr, "Only comments are supported after " + + IfTokName + " NAME"); // If we were not processing tokens before this #ifdef, // then just return back to the lines skipping code. @@ -714,7 +722,7 @@ // Check if this #else is correct before calling prepSkipDirectiveEnd(), // which will move CurPtr away from the beginning of #else. if (PrepIncludeStack.back()->empty()) - return ReturnError(TokStart, "#else without #ifdef"); + return ReturnError(TokStart, "#else without #ifdef or #ifndef"); PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back()->back(); Index: llvm/test/TableGen/prep-diag5.td =================================================================== --- llvm/test/TableGen/prep-diag5.td +++ llvm/test/TableGen/prep-diag5.td @@ -1,6 +1,6 @@ // RUN: not llvm-tblgen -I %p %s 2>&1 | FileCheck %s -// CHECK: error: #else without #ifdef +// CHECK: error: #else without #ifdef or #ifndef #else #else #endif Index: llvm/test/TableGen/prep-ifndef-diag-1.td =================================================================== --- /dev/null +++ llvm/test/TableGen/prep-ifndef-diag-1.td @@ -0,0 +1,4 @@ +// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s + +// CHECK: error: Expected macro name after #ifndef +#ifndef 1 Index: llvm/test/TableGen/prep-ifndef-diag-2.td =================================================================== --- /dev/null +++ llvm/test/TableGen/prep-ifndef-diag-2.td @@ -0,0 +1,4 @@ +// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s + +// CHECK: error: Only comments are supported after #ifndef NAME +#ifndef MACRO 42 Index: llvm/test/TableGen/prep-ifndef.td =================================================================== --- /dev/null +++ llvm/test/TableGen/prep-ifndef.td @@ -0,0 +1,10 @@ +// RUN: llvm-tblgen %s -DMACRO | FileCheck %s +// RUN: llvm-tblgen %s | FileCheck %s --check-prefix=CHECK-NOMACRO + +#ifndef MACRO +// CHECK-NOMACRO: def nomacro +def nomacro; +#else +// CHECK: def macro +def macro; +#endif