summaryrefslogtreecommitdiffstats
path: root/clang/Lex/Preprocessor.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-07-08 08:28:12 +0000
committerChris Lattner <sabre@nondot.org>2006-07-08 08:28:12 +0000
commitcefc768f5b4a6789c45584a7264b950e65fe253d (patch)
treee4eaf546e999a0c9e1152ad3d45be22773e3a81d /clang/Lex/Preprocessor.cpp
parent21284dfdd128f2f2e7faec9b1694aaa88fb0ab2d (diff)
downloadbcm5719-llvm-cefc768f5b4a6789c45584a7264b950e65fe253d.tar.gz
bcm5719-llvm-cefc768f5b4a6789c45584a7264b950e65fe253d.zip
Start reading/validating the argument list for a function-like macro.
llvm-svn: 38681
Diffstat (limited to 'clang/Lex/Preprocessor.cpp')
-rw-r--r--clang/Lex/Preprocessor.cpp107
1 files changed, 103 insertions, 4 deletions
diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp
index 6aa6fe273f3..218702f99c8 100644
--- a/clang/Lex/Preprocessor.cpp
+++ b/clang/Lex/Preprocessor.cpp
@@ -706,6 +706,29 @@ struct UnusedIdentifierReporter : public IdentifierVisitor {
// Lexer Event Handling.
//===----------------------------------------------------------------------===//
+/// LookUpIdentifierInfo - Given a tok::identifier token, look up the
+/// identifier information for the token and install it into the token.
+IdentifierInfo *Preprocessor::LookUpIdentifierInfo(LexerToken &Identifier,
+ const char *BufPtr) {
+ assert(Identifier.getKind() == tok::identifier && "Not an identifier!");
+ assert(Identifier.getIdentifierInfo() == 0 && "Identinfo already exists!");
+
+ // Look up this token, see if it is a macro, or if it is a language keyword.
+ IdentifierInfo *II;
+ if (BufPtr && !Identifier.needsCleaning()) {
+ // No cleaning needed, just use the characters from the lexed buffer.
+ II = getIdentifierInfo(BufPtr, BufPtr+Identifier.getLength());
+ } else {
+ // Cleaning needed, alloca a buffer, clean into it, then use the buffer.
+ const char *TmpBuf = (char*)alloca(Identifier.getLength());
+ unsigned Size = getSpelling(Identifier, TmpBuf);
+ II = getIdentifierInfo(TmpBuf, TmpBuf+Size);
+ }
+ Identifier.SetIdentifierInfo(II);
+ return II;
+}
+
+
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier. This callback looks up the identifier in the map and/or
/// potentially macro expands it or turns it into a named token (like 'for').
@@ -1318,6 +1341,78 @@ void Preprocessor::HandleImportDirective(LexerToken &ImportTok) {
// Preprocessor Macro Directive Handling.
//===----------------------------------------------------------------------===//
+/// ReadMacroDefinitionArgList - The ( starting an argument list of a macro
+/// definition has just been read. Lex the rest of the arguments and the
+/// closing ), updating MI with what we learn. Return true if an error occurs
+/// parsing the arg list.
+bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) {
+ LexerToken Tok;
+ bool isFirst = true;
+ while (1) {
+ LexUnexpandedToken(Tok);
+ switch (Tok.getKind()) {
+ case tok::r_paren:
+ // Found the end of the argument list.
+ if (isFirst) return false; // #define FOO()
+ // Otherwise we have #define FOO(A,)
+ Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
+ return true;
+ case tok::ellipsis: // #define X(... -> C99 varargs
+ // Warn if use of C99 feature in non-C99 mode.
+ if (!Features.C99) Diag(Tok, diag::ext_variadic_macro);
+
+ // Lex the token after the identifier.
+ LexUnexpandedToken(Tok);
+ if (Tok.getKind() != tok::r_paren) {
+ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
+ return true;
+ }
+ MI->setIsC99Varargs();
+ return false;
+ case tok::eom: // #define X(
+ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
+ return true;
+ default: // #define X(1
+ Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
+ return true;
+ case tok::identifier:
+ isFirst = false;
+
+ // Fill in Result.IdentifierInfo, looking up the identifier in the
+ // identifier table.
+ IdentifierInfo *II = LookUpIdentifierInfo(Tok);
+
+ assert(0 && "FIXME: lookup/add identifier, check for conflicts");
+
+ // Lex the token after the identifier.
+ LexUnexpandedToken(Tok);
+
+ switch (Tok.getKind()) {
+ default: // #define X(A B
+ Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
+ return true;
+ case tok::r_paren: // #define X(A)
+ return false;
+ case tok::comma: // #define X(A,
+ break;
+ case tok::ellipsis: // #define X(A... -> GCC extension
+ // Diagnose extension.
+ Diag(Tok, diag::ext_named_variadic_macro);
+
+ // Lex the token after the identifier.
+ LexUnexpandedToken(Tok);
+ if (Tok.getKind() != tok::r_paren) {
+ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
+ return true;
+ }
+
+ MI->setIsGNUVarargs();
+ return false;
+ }
+ }
+ }
+}
+
/// HandleDefineDirective - Implements #define. This consumes the entire macro
/// line then lets the caller lex the next real token.
///
@@ -1339,10 +1434,14 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok) {
if (Tok.getKind() == tok::eom) {
// If there is no body to this macro, we have no special handling here.
} else if (Tok.getKind() == tok::l_paren && !Tok.hasLeadingSpace()) {
- // This is a function-like macro definition.
- //assert(0 && "Function-like macros not implemented!");
- delete MI;
- return DiscardUntilEndOfDirective();
+ // This is a function-like macro definition. Read the argument list.
+ MI->setIsFunctionLike();
+ if (ReadMacroDefinitionArgList(MI)) {
+ delete MI;
+ if (CurLexer->ParsingPreprocessorDirective)
+ DiscardUntilEndOfDirective();
+ return;
+ }
} else if (!Tok.hasLeadingSpace()) {
// C99 requires whitespace between the macro definition and the body. Emit
OpenPOWER on IntegriCloud