diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -693,6 +693,9 @@ def warn_cxx98_compat_pp_line_too_big : Warning< "#line number greater than 32767 is incompatible with C++98">, InGroup, DefaultIgnore; +def ext_c2x_pp_directive : Extension< + "%select{#elifdef|#elifndef}0 is a C2x extension">, + InGroup; def err_pp_visibility_non_macro : Error<"no macro named %0">; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -3255,6 +3255,17 @@ : PED_Elifndef; ++NumElse; + // Warn if using `#elifdef` & `#elifndef` in not C2x mode. + switch (DirKind) { + case PED_Elifdef: + case PED_Elifndef: + if (!getLangOpts().C2x) + Diag(ElifToken, diag::ext_c2x_pp_directive) << DirKind - 1; + break; + default: + break; + } + // #elif directive in a non-skipping conditional... start skipping. // We don't care what the condition is, because we will always skip it (since // the block immediately before it was included). diff --git a/clang/test/Preprocessor/ext-c2x-pp-directive.c b/clang/test/Preprocessor/ext-c2x-pp-directive.c new file mode 100644 --- /dev/null +++ b/clang/test/Preprocessor/ext-c2x-pp-directive.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -pedantic %s +// RUN: not %clang_cc1 -std=c99 -fsyntax-only -verify %s +// RUN: not %clang_cc1 -std=c2x -fsyntax-only -verify -pedantic %s +// RUN: not %clang_cc1 -std=c2x -fsyntax-only -verify %s + +#if 1 +#elifndef FOO // expected-warning {{#elifndef is a C2x extension}} +#endif + +#if 1 +#elifdef BAR // expected-warning {{#elifdef is a C2x extension}} +#endif + +// expected-warning {{ISO C requires a translation unit to contain at least one declaration}}