diff options
-rw-r--r-- | clang/include/clang/Parse/DeclSpec.h | 85 | ||||
-rw-r--r-- | clang/lib/Parse/DeclSpec.cpp | 38 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 |
5 files changed, 85 insertions, 49 deletions
diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h index 2fd00dd6401..c351e30bf2f 100644 --- a/clang/include/clang/Parse/DeclSpec.h +++ b/clang/include/clang/Parse/DeclSpec.h @@ -18,6 +18,7 @@ #include "clang/Parse/AttributeList.h" #include "clang/Lex/Token.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" namespace clang { struct LangOptions; @@ -241,7 +242,6 @@ public: getTypeSpecSign() != DeclSpec::TSS_unspecified; } - /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this /// DeclSpec includes. /// @@ -486,7 +486,7 @@ struct DeclaratorChunk { /// declaration of a member function), it will be stored here as a /// sequence of tokens to be parsed once the class definition is /// complete. Non-NULL indicates that there is a default argument. - CachedTokens *DefaultArgTokens; + CachedTokens *DefaultArgTokens; ParamInfo() {} ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::DeclTy *param, @@ -509,6 +509,9 @@ struct DeclaratorChunk { /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; + /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. + bool DeleteArgInfo : 1; + /// NumArgs - This is the number of formal arguments provided for the /// declarator. unsigned NumArgs; @@ -519,7 +522,8 @@ struct DeclaratorChunk { ParamInfo *ArgInfo; void destroy() { - delete[] ArgInfo; + if (DeleteArgInfo) + delete[] ArgInfo; } }; @@ -538,6 +542,16 @@ struct DeclaratorChunk { BlockPointerTypeInfo Cls; }; + void destroy() { + switch (Kind) { + default: assert(0 && "Unknown decl type!"); + case DeclaratorChunk::Function: return Fun.destroy(); + case DeclaratorChunk::Pointer: return Ptr.destroy(); + case DeclaratorChunk::BlockPointer: return Cls.destroy(); + case DeclaratorChunk::Reference: return Ref.destroy(); + case DeclaratorChunk::Array: return Arr.destroy(); + } + } /// getAttrs - If there are attributes applied to this declaratorchunk, return /// them. @@ -592,26 +606,13 @@ struct DeclaratorChunk { return I; } - /// getFunction - Return a DeclaratorChunk for a function. + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. + /// "TheDeclarator" is the declarator that this will be added to. static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, ParamInfo *ArgInfo, unsigned NumArgs, - unsigned TypeQuals, SourceLocation Loc) { - DeclaratorChunk I; - I.Kind = Function; - I.Loc = Loc; - I.Fun.hasPrototype = hasProto; - I.Fun.isVariadic = isVariadic; - I.Fun.TypeQuals = TypeQuals; - I.Fun.NumArgs = NumArgs; - I.Fun.ArgInfo = 0; - - // new[] an argument array if needed. - if (NumArgs) { - I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs]; - memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); - } - return I; - } + unsigned TypeQuals, SourceLocation Loc, + Declarator &TheDeclarator); + /// getBlockPointer - Return a DeclaratorChunk for a block. /// static DeclaratorChunk getBlockPointer(unsigned TypeQuals, @@ -635,13 +636,8 @@ struct DeclaratorChunk { /// Instances of this class should be a transient object that lives on the /// stack, not objects that are allocated in large quantities on the heap. class Declarator { - const DeclSpec &DS; - CXXScopeSpec SS; - IdentifierInfo *Identifier; - SourceLocation IdentifierLoc; - public: - enum TheContext { + enum TheContext { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. KNRTypeListContext, // K&R type definition list for formals. @@ -666,6 +662,11 @@ public: }; private: + const DeclSpec &DS; + CXXScopeSpec SS; + IdentifierInfo *Identifier; + SourceLocation IdentifierLoc; + /// Context - Where we are parsing this declarator. /// TheContext Context; @@ -702,10 +703,18 @@ private: OverloadedOperatorKind OperatorKind; }; + /// InlineParams - This is a local array used for the first function decl + /// chunk to avoid going to the heap for the common case when we have one + /// function chunk in the declarator. + friend class DeclaratorChunk; + DeclaratorChunk::ParamInfo InlineParams[16]; + bool InlineParamsUsed; + public: Declarator(const DeclSpec &ds, TheContext C) : DS(ds), Identifier(0), Context(C), Kind(DK_Abstract), InvalidType(false), - GroupingParens(false), AttrList(0), AsmLabel(0), Type(0) { + GroupingParens(false), AttrList(0), AsmLabel(0), Type(0), + InlineParamsUsed(false) { } ~Declarator() { @@ -741,25 +750,14 @@ public: IdentifierLoc = SourceLocation(); Kind = DK_Abstract; - for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) { - if (DeclTypeInfo[i].Kind == DeclaratorChunk::Function) - DeclTypeInfo[i].Fun.destroy(); - else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Pointer) - DeclTypeInfo[i].Ptr.destroy(); - else if (DeclTypeInfo[i].Kind == DeclaratorChunk::BlockPointer) - DeclTypeInfo[i].Cls.destroy(); - else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Reference) - DeclTypeInfo[i].Ref.destroy(); - else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Array) - DeclTypeInfo[i].Arr.destroy(); - else - assert(0 && "Unknown decl type!"); - } + for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) + DeclTypeInfo[i].destroy(); DeclTypeInfo.clear(); delete AttrList; AttrList = 0; AsmLabel = 0; Type = 0; + InlineParamsUsed = false; } /// mayOmitIdentifier - Return true if the identifier is either optional or @@ -783,7 +781,7 @@ public: return !hasGroupingParens() && (Context == FileContext || Context == BlockContext || - Context == ForContext ); + Context == ForContext); } /// isPastIdentifier - Return true if we have parsed beyond the point where @@ -908,7 +906,6 @@ struct FieldDeclarator { } }; - } // end namespace clang #endif diff --git a/clang/lib/Parse/DeclSpec.cpp b/clang/lib/Parse/DeclSpec.cpp index 4459c804f37..83bf36c7163 100644 --- a/clang/lib/Parse/DeclSpec.cpp +++ b/clang/lib/Parse/DeclSpec.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/DeclSpec.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" +#include "llvm/ADT/STLExtras.h" using namespace clang; @@ -23,6 +24,43 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc, } +/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. +/// "TheDeclarator" is the declarator that this will be added to. +DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, + ParamInfo *ArgInfo, + unsigned NumArgs, + unsigned TypeQuals, + SourceLocation Loc, + Declarator &TheDeclarator) { + DeclaratorChunk I; + I.Kind = Function; + I.Loc = Loc; + I.Fun.hasPrototype = hasProto; + I.Fun.isVariadic = isVariadic; + I.Fun.DeleteArgInfo = false; + I.Fun.TypeQuals = TypeQuals; + I.Fun.NumArgs = NumArgs; + I.Fun.ArgInfo = 0; + + // new[] an argument array if needed. + if (NumArgs) { + // If the 'InlineParams' in Declarator is unused and big enough, put our + // parameter list there (in an effort to avoid new/delete traffic). If it + // is already used (consider a function returning a function pointer) or too + // small (function taking too many arguments), go to the heap. + if (!TheDeclarator.InlineParamsUsed && + NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) { + I.Fun.ArgInfo = TheDeclarator.InlineParams; + I.Fun.DeleteArgInfo = false; + TheDeclarator.InlineParamsUsed = true; + } else { + I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs]; + I.Fun.DeleteArgInfo = true; + } + memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); + } + return I; +} /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this /// diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 456acbeebdf..bf922780c7c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1854,7 +1854,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, /*variadic*/ false, /*arglist*/ 0, 0, DS.getTypeQualifiers(), - LParenLoc)); + LParenLoc, D)); return; } @@ -2013,7 +2013,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic, &ParamInfo[0], ParamInfo.size(), DS.getTypeQualifiers(), - LParenLoc)); + LParenLoc, D)); } /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator @@ -2080,7 +2080,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // has no prototype. D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false, &ParamInfo[0], ParamInfo.size(), - /*TypeQuals*/0, LParenLoc)); + /*TypeQuals*/0, LParenLoc, D)); // If we have the closing ')', eat it and we're done. MatchRHSPunctuation(tok::r_paren, LParenLoc); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index dc95c381d5c..38518557a3f 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1222,7 +1222,8 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() { } else { // Otherwise, pretend we saw (void). ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, - 0, 0, 0, CaretLoc)); + 0, 0, 0, CaretLoc, + ParamInfo)); } // Inform sema that we are starting a block. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6f731ca5480..c91d174d654 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2772,7 +2772,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, Error = Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext); - D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc)); + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc, D)); D.SetIdentifier(&II, Loc); // Insert this function into translation-unit scope. |