From: Chris Lattner Date: Sat, 14 Jul 2007 22:46:43 +0000 (+0000) Subject: switch function-like macros from using a vector for their arguments to an X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=25c9648909193d380a4e135d2e3d25394ba12922;p=clang switch function-like macros from using a vector for their arguments to an explicitly new'd array. The array never mutates once created, so a vector is overkill. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39862 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Lex/MacroInfo.cpp b/Lex/MacroInfo.cpp index e6dae42769..a9a8ad7fd6 100644 --- a/Lex/MacroInfo.cpp +++ b/Lex/MacroInfo.cpp @@ -23,6 +23,9 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { IsTargetSpecific = false; IsDisabled = false; IsUsed = true; + + ArgumentList = 0; + NumArguments = 0; } /// isIdenticalTo - Return true if the specified macro definition is equal to @@ -34,7 +37,7 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const { // Check # tokens in replacement, number of args, and various flags all match. if (ReplacementTokens.size() != Other.ReplacementTokens.size() || - Arguments.size() != Other.Arguments.size() || + getNumArgs() != Other.getNumArgs() || isFunctionLike() != Other.isFunctionLike() || isC99Varargs() != Other.isC99Varargs() || isGNUVarargs() != Other.isGNUVarargs()) diff --git a/Lex/Preprocessor.cpp b/Lex/Preprocessor.cpp index 073fda2011..4e3f68e1a1 100644 --- a/Lex/Preprocessor.cpp +++ b/Lex/Preprocessor.cpp @@ -1639,13 +1639,18 @@ void Preprocessor::HandleImportDirective(LexerToken &ImportTok) { /// closing ), updating MI with what we learn. Return true if an error occurs /// parsing the arg list. bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { + llvm::SmallVector Arguments; + LexerToken Tok; while (1) { LexUnexpandedToken(Tok); switch (Tok.getKind()) { case tok::r_paren: // Found the end of the argument list. - if (MI->arg_begin() == MI->arg_end()) return false; // #define FOO() + if (Arguments.empty()) { // #define FOO() + MI->setArgumentList(Arguments.begin(), Arguments.end()); + return false; + } // Otherwise we have #define FOO(A,) Diag(Tok, diag::err_pp_expected_ident_in_arg_list); return true; @@ -1660,8 +1665,9 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { return true; } // Add the __VA_ARGS__ identifier as an argument. - MI->addArgument(Ident__VA_ARGS__); + Arguments.push_back(Ident__VA_ARGS__); MI->setIsC99Varargs(); + MI->setArgumentList(Arguments.begin(), Arguments.end()); return false; case tok::eom: // #define X( Diag(Tok, diag::err_pp_missing_rparen_in_macro_def); @@ -1678,13 +1684,14 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { // If this is already used as an argument, it is used multiple times (e.g. // #define X(A,A. - if (MI->getArgumentNum(II) != -1) { // C99 6.10.3p6 + if (std::find(Arguments.begin(), Arguments.end(), II) != + Arguments.end()) { // C99 6.10.3p6 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list, II->getName()); return true; } // Add the argument to the macro info. - MI->addArgument(II); + Arguments.push_back(II); // Lex the token after the identifier. LexUnexpandedToken(Tok); @@ -1694,6 +1701,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { Diag(Tok, diag::err_pp_expected_comma_in_arg_list); return true; case tok::r_paren: // #define X(A) + MI->setArgumentList(Arguments.begin(), Arguments.end()); return false; case tok::comma: // #define X(A, break; @@ -1709,6 +1717,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { } MI->setIsGNUVarargs(); + MI->setArgumentList(Arguments.begin(), Arguments.end()); return false; } } diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 2a5a88b1eb..1c7a28ce2a 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -34,7 +34,8 @@ class MacroInfo { /// Arguments - The list of arguments for a function-like macro. This can be /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this /// includes the __VA_ARGS__ identifier on the list. - std::vector Arguments; + IdentifierInfo **ArgumentList; + unsigned NumArguments; /// ReplacementTokens - This is the list of tokens that the macro is defined /// to. @@ -77,6 +78,10 @@ private: public: MacroInfo(SourceLocation DefLoc); + ~MacroInfo() { + delete[] ArgumentList; + } + /// getDefinitionLoc - Return the location that the macro was defined at. /// SourceLocation getDefinitionLoc() const { return Location; } @@ -105,26 +110,33 @@ public: IsUsed = Val; } - /// addArgument - Add an argument to the list of formal arguments for this - /// function-like macro. - void addArgument(IdentifierInfo *Arg) { - Arguments.push_back(Arg); + /// setArgumentList - Set the specified list of identifiers as the argument + /// list for this macro. + template + void setArgumentList(ItTy ArgBegin, ItTy ArgEnd) { + assert(ArgumentList == 0 && "Argument list already set!"); + unsigned NumArgs = ArgEnd-ArgBegin; + if (NumArgs == 0) return; + NumArguments = NumArgs; + ArgumentList = new IdentifierInfo*[NumArgs]; + for (unsigned i = 0; ArgBegin != ArgEnd; ++i, ++ArgBegin) + ArgumentList[i] = *ArgBegin; } + /// Arguments - The list of arguments for a function-like macro. This can be + /// empty, for, e.g. "#define X()". + typedef IdentifierInfo* const *arg_iterator; + arg_iterator arg_begin() const { return ArgumentList; } + arg_iterator arg_end() const { return ArgumentList+NumArguments; } + unsigned getNumArgs() const { return NumArguments; } + /// getArgumentNum - Return the argument number of the specified identifier, /// or -1 if the identifier is not a formal argument identifier. - int getArgumentNum(IdentifierInfo *Arg) { - for (unsigned i = 0, e = Arguments.size(); i != e; ++i) - if (Arguments[i] == Arg) return i; + int getArgumentNum(IdentifierInfo *Arg) const { + for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I) + if (*I == Arg) return I-arg_begin(); return -1; } - - /// Arguments - The list of arguments for a function-like macro. This can be - /// empty, for, e.g. "#define X()". - typedef std::vector::const_iterator arg_iterator; - arg_iterator arg_begin() const { return Arguments.begin(); } - arg_iterator arg_end() const { return Arguments.end(); } - unsigned getNumArgs() const { return Arguments.size(); } /// Function/Object-likeness. Keep track of whether this macro has formal /// parameters.