#include "clang/Parse/AttributeList.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerIntPair.h"
namespace clang {
struct LangOptions;
getTypeSpecSign() != DeclSpec::TSS_unspecified;
}
-
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
/// DeclSpec includes.
///
/// 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,
/// 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;
ParamInfo *ArgInfo;
void destroy() {
- delete[] ArgInfo;
+ if (DeleteArgInfo)
+ delete[] ArgInfo;
}
};
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.
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,
/// 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.
};
private:
+ const DeclSpec &DS;
+ CXXScopeSpec SS;
+ IdentifierInfo *Identifier;
+ SourceLocation IdentifierLoc;
+
/// Context - Where we are parsing this declarator.
///
TheContext Context;
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() {
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
return !hasGroupingParens() &&
(Context == FileContext ||
Context == BlockContext ||
- Context == ForContext );
+ Context == ForContext);
}
/// isPastIdentifier - Return true if we have parsed beyond the point where
}
};
-
} // end namespace clang
#endif
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
using namespace clang;
}
+/// 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
///