From: Chris Lattner Date: Sat, 18 Apr 2009 02:23:25 +0000 (+0000) Subject: enforce requirements imposed by C90 6.8 TC1, fixing PR3919. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6272bcfe5dc148d293ccce9db19df9e71c991cde;p=clang enforce requirements imposed by C90 6.8 TC1, fixing PR3919. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69415 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 8d85637ea0..d87c891036 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -95,6 +95,11 @@ def pp_include_macros_out_of_predefines : Error< def pp_include_next_absolute_path : Warning<"#include_next with absolute path">; def ext_c99_whitespace_required_after_macro_name : ExtWarn< "ISO C99 requires whitespace after the macro name">; +def ext_missing_whitespace_after_macro_name : ExtWarn< + "whitespace required after macro name">; +def warn_missing_whitespace_after_macro_name : Warning< + "whitespace required after macro name">; + def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">; def pp_pragma_sysheader_in_main_file : Warning< "#pragma system_header ignored in main file">; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index be4da35f93..e4b36fd157 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1289,7 +1289,11 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // check other constraints on the first token of the macro body. if (Tok.is(tok::eom)) { // If there is no body to this macro, we have no special handling here. - } else if (Tok.is(tok::l_paren) && !Tok.hasLeadingSpace()) { + } else if (Tok.hasLeadingSpace()) { + // This is a normal token with leading space. Clear the leading space + // marker on the first token to get proper expansion. + Tok.clearFlag(Token::LeadingSpace); + } else if (Tok.is(tok::l_paren)) { // This is a function-like macro definition. Read the argument list. MI->setIsFunctionLike(); if (ReadMacroDefinitionArgList(MI)) { @@ -1303,19 +1307,30 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // Read the first token after the arg list for down below. LexUnexpandedToken(Tok); - } else if (!Tok.hasLeadingSpace()) { + } else if (Features.C99) { // C99 requires whitespace between the macro definition and the body. Emit // a diagnostic for something like "#define X+". - if (Features.C99) { - Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name); - } else { - // FIXME: C90/C++ do not get this diagnostic, but it does get a similar - // one in some cases! - } + Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name); } else { - // This is a normal token with leading space. Clear the leading space - // marker on the first token to get proper expansion. - Tok.clearFlag(Token::LeadingSpace); + // C90 6.8 TC1 says: "In the definition of an object-like macro, if the + // first character of a replacement list is not a character required by + // subclause 5.2.1, then there shall be white-space separation between the + // identifier and the replacement list.". 5.2.1 lists this set: + // "A-Za-z0-9!"#%&'()*+,_./:;<=>?[\]^_{|}~" as well as whitespace, which + // is irrelevant here. + bool isInvalid = false; + if (Tok.is(tok::at)) // @ is not in the list above. + isInvalid = true; + else if (Tok.is(tok::unknown)) { + // If we have an unknown token, it is something strange like "`". Since + // all of valid characters would have lexed into a single character + // token of some sort, we know this is not a valid case. + isInvalid = true; + } + if (isInvalid) + Diag(Tok, diag::ext_missing_whitespace_after_macro_name); + else + Diag(Tok, diag::warn_missing_whitespace_after_macro_name); } // If this is a definition of a variadic C99 function-like macro, not using diff --git a/test/Preprocessor/c90.c b/test/Preprocessor/c90.c new file mode 100644 index 0000000000..4287d0d6b8 --- /dev/null +++ b/test/Preprocessor/c90.c @@ -0,0 +1,10 @@ +/* RUN: clang-cc %s -std=c89 -Eonly -verify -pedantic-errors + */ + +/* PR3919 */ + +#define foo`bar /* expected-error {{whitespace required after macro name}} */ +#define foo2!bar /* expected-warning {{whitespace required after macro name}} */ + +#define foo3$bar /* expected-error {{'$' in identifier}} */ +