[cfe-commits] r38681 - in /cfe/cfe/trunk: Lex/Lexer.cpp Lex/MacroInfo.cpp Lex/Pragma.cpp Lex/Preprocessor.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Lex/MacroInfo.h include/clang/Lex/Preprocessor.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:23:46 PDT 2007
Author: sabre
Date: Wed Jul 11 11:23:46 2007
New Revision: 38681
URL: http://llvm.org/viewvc/llvm-project?rev=38681&view=rev
Log:
Start reading/validating the argument list for a function-like macro.
Modified:
cfe/cfe/trunk/Lex/Lexer.cpp
cfe/cfe/trunk/Lex/MacroInfo.cpp
cfe/cfe/trunk/Lex/Pragma.cpp
cfe/cfe/trunk/Lex/Preprocessor.cpp
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/cfe/trunk/include/clang/Lex/MacroInfo.h
cfe/cfe/trunk/include/clang/Lex/Preprocessor.h
Modified: cfe/cfe/trunk/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Lexer.cpp?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/Lexer.cpp (original)
+++ cfe/cfe/trunk/Lex/Lexer.cpp Wed Jul 11 11:23:46 2007
@@ -349,22 +349,13 @@
// FIXME: UCNs.
if (C != '\\' && C != '?' && (C != '$' || !Features.DollarIdents)) {
FinishIdentifier:
- const char *IdStart = BufferPtr, *IdEnd = CurPtr;
+ const char *IdStart = BufferPtr;
FormTokenWithChars(Result, CurPtr);
Result.SetKind(tok::identifier);
- // Look up this token, see if it is a macro, or if it is a language keyword.
- IdentifierInfo *II;
- if (!Result.needsCleaning()) {
- // No cleaning needed, just use the characters from the lexed buffer.
- II = PP.getIdentifierInfo(IdStart, IdEnd);
- } else {
- // Cleaning needed, alloca a buffer, clean into it, then use the buffer.
- const char *TmpBuf = (char*)alloca(Result.getLength());
- unsigned Size = PP.getSpelling(Result, TmpBuf);
- II = PP.getIdentifierInfo(TmpBuf, TmpBuf+Size);
- }
- Result.SetIdentifierInfo(II);
+ // Fill in Result.IdentifierInfo, looking up the identifier in the
+ // identifier table.
+ PP.LookUpIdentifierInfo(Result, IdStart);
// Finally, now that we know we have an identifier, pass this off to the
// preprocessor, which may macro expand it or something.
Modified: cfe/cfe/trunk/Lex/MacroInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/MacroInfo.cpp?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/MacroInfo.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroInfo.cpp Wed Jul 11 11:23:46 2007
@@ -17,14 +17,27 @@
using namespace llvm;
using namespace clang;
+MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
+ IsFunctionLike = false;
+ IsC99Varargs = false;
+ IsGNUVarargs = false;
+ IsBuiltinMacro = false;
+ IsDisabled = false;
+ IsUsed = true;
+}
+
+
/// isIdenticalTo - Return true if the specified macro definition is equal to
/// this macro in spelling, arguments, and whitespace. This is used to emit
/// duplicate definition warnings. This implements the rules in C99 6.10.3.
bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
- // TODO: Check param count, variadic, function likeness.
+ // TODO: Check param count.
// Check # tokens in replacement match.
- if (ReplacementTokens.size() != Other.ReplacementTokens.size())
+ if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
+ isFunctionLike() != Other.isFunctionLike() ||
+ isC99Varargs() != Other.isC99Varargs() ||
+ isGNUVarargs() != Other.isGNUVarargs())
return false;
// Check all the tokens.
Modified: cfe/cfe/trunk/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Pragma.cpp?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/Pragma.cpp (original)
+++ cfe/cfe/trunk/Lex/Pragma.cpp Wed Jul 11 11:23:46 2007
@@ -204,10 +204,9 @@
return;
}
- // Look up the identifier info for the token. Note that this can't use
- // Tok.getIdentifierInfo() directly because we disabled identifier lookup.
- std::string TokStr = getSpelling(Tok);
- IdentifierInfo *II =getIdentifierInfo(&TokStr[0], &TokStr[0]+TokStr.size());
+ // Look up the identifier info for the token. We disabled identifier lookup
+ // by saying we're skipping contents, so we need to do this manually.
+ IdentifierInfo *II = LookUpIdentifierInfo(Tok);
// Already poisoned.
if (II->isPoisoned()) continue;
Modified: cfe/cfe/trunk/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Preprocessor.cpp?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:23:46 2007
@@ -706,6 +706,29 @@
// 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 @@
// 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 @@
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
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:23:46 2007
@@ -119,6 +119,10 @@
"\"%s\" macro redefined")
DIAG(ext_pp_macro_redef2, EXTENSION,
"this is previous definition")
+DIAG(ext_variadic_macro, EXTENSION,
+ "variadic macros were introduced in C99")
+DIAG(ext_named_variadic_macro, EXTENSION,
+ "named variadic macros are a GNU extension")
DIAG(ext_pp_base_file, EXTENSION,
"__BASE_FILE__ is a language extension")
@@ -143,6 +147,14 @@
"macro names must be identifiers")
DIAG(err_pp_missing_macro_name, ERROR,
"macro name missing")
+DIAG(err_pp_missing_rparen_in_macro_def, ERROR,
+ "missing ')' in macro parameter list")
+DIAG(err_pp_invalid_tok_in_arg_list, ERROR,
+ "invalid token in macro parameter list")
+DIAG(err_pp_expected_ident_in_arg_list, ERROR,
+ "expected identifier in macro parameter list")
+DIAG(err_pp_expected_comma_in_arg_list, ERROR,
+ "expected comma in macro parameter list")
DIAG(err_pp_malformed_ident, ERROR,
"invalid #ident directive")
DIAG(err_pp_unterminated_conditional, ERROR,
Modified: cfe/cfe/trunk/include/clang/Lex/MacroInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/MacroInfo.h?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroInfo.h Wed Jul 11 11:23:46 2007
@@ -24,6 +24,9 @@
/// MacroInfo - Each identifier that is #define'd has an instance of this class
/// associated with it, used to implement macro expansion.
class MacroInfo {
+ //===--------------------------------------------------------------------===//
+ // State set when the macro is defined.
+
/// Location - This is the place the macro is defined.
SourceLocation Location;
@@ -33,26 +36,40 @@
/// ReplacementTokens - This is the list of tokens that the macro is defined
/// to.
std::vector<LexerToken> ReplacementTokens;
+
+ /// IsFunctionLike - True if this macro is a function-like macro, false if it
+ /// is an object-like macro.
+ bool IsFunctionLike : 1;
+
+ /// IsC99Varargs - True if this macro is of the form "#define X(...)" or
+ /// "#define X(Y,Z,...)". The __VA_ARGS__ token should be replaced with the
+ /// contents of "..." in an invocation.
+ bool IsC99Varargs : 1;
+
+ /// IsGNUVarargs - True if this macro is of the form "#define X(a...)". The
+ /// "a" identifier in th replacement list will be replaced with all arguments
+ /// of the macro starting with the specified one.
+ bool IsGNUVarargs : 1;
+ /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if
+ /// it has not yet been redefined or undefined.
+ bool IsBuiltinMacro : 1;
+
+private:
+ //===--------------------------------------------------------------------===//
+ // State that changes as the macro is used.
+
/// IsDisabled - True if we have started an expansion of this macro already.
/// This disbles recursive expansion, which would be quite bad for things like
/// #define A A.
bool IsDisabled : 1;
- /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if
- /// it has not yet been redefined or undefined.
- bool IsBuiltinMacro : 1;
-
/// IsUsed - True if this macro is either defined in the main file and has
/// been used, or if it is not defined in the main file. This is used to
/// emit -Wunused-macros diagnostics.
bool IsUsed : 1;
public:
- MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
- IsDisabled = false;
- IsBuiltinMacro = false;
- IsUsed = true;
- }
+ MacroInfo(SourceLocation DefLoc);
/// getDefinitionLoc - Return the location that the macro was defined at.
///
@@ -75,6 +92,18 @@
IsUsed = Val;
}
+ /// Function/Object-likeness. Keep track of whether this macro has formal
+ /// parameters.
+ void setIsFunctionLike() { IsFunctionLike = true; }
+ bool isFunctionLike() const { return IsFunctionLike; }
+ bool isObjectLike() const { return !IsFunctionLike; }
+
+ /// Varargs querying methods. This can only be set for function-like macros.
+ void setIsC99Varargs() { IsC99Varargs = true; }
+ void setIsGNUVarargs() { IsGNUVarargs = true; }
+ bool isC99Varargs() const { return IsC99Varargs; }
+ bool isGNUVarargs() const { return IsGNUVarargs; }
+
/// isBuiltinMacro - Return true if this macro is a builtin macro, such as
/// __LINE__, which requires processing before expansion.
bool isBuiltinMacro() const { return IsBuiltinMacro; }
Modified: cfe/cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=38681&r1=38680&r2=38681&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:23:46 2007
@@ -384,6 +384,11 @@
// Preprocessor callback methods. These are invoked by a lexer as various
// directives and events are found.
+ /// LookUpIdentifierInfo - Given a tok::identifier token, look up the
+ /// identifier information for the token and install it into the token.
+ IdentifierInfo *LookUpIdentifierInfo(LexerToken &Identifier,
+ const char *BufPtr = 0);
+
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier and has filled in the tokens IdentifierInfo member. This
/// callback potentially macro expands it or turns it into a named token (like
@@ -423,6 +428,12 @@
/// and discards the rest of the macro line if the macro name is invalid.
void ReadMacroName(LexerToken &MacroNameTok, char isDefineUndef = 0);
+ /// 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 ReadMacroDefinitionArgList(MacroInfo *MI);
+
/// SkipExcludedConditionalBlock - We just read a #if or related directive and
/// decided that the subsequent tokens are in the #if'd out portion of the
/// file. Lex the rest of the file, until we see an #endif. If
More information about the cfe-commits
mailing list