//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines interfaces used for Declaration Specifiers and Declarators. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_PARSE_DECLSPEC_H #define LLVM_CLANG_PARSE_DECLSPEC_H #include "clang/Parse/Action.h" #include "clang/Parse/AttributeList.h" #include "llvm/ADT/SmallVector.h" namespace clang { struct LangOptions; class Diagnostic; class IdentifierInfo; /// DeclSpec - This class captures information about "declaration specifiers", /// which encompasses storage-class-specifiers, type-specifiers, /// type-qualifiers, and function-specifiers. class DeclSpec { public: // storage-class-specifier enum SCS { SCS_unspecified, SCS_typedef, SCS_extern, SCS_static, SCS_auto, SCS_register, SCS_private_extern, SCS_mutable }; // type-specifier enum TSW { TSW_unspecified, TSW_short, TSW_long, TSW_longlong }; enum TSC { TSC_unspecified, TSC_imaginary, TSC_complex }; enum TSS { TSS_unspecified, TSS_signed, TSS_unsigned }; enum TST { TST_unspecified, TST_void, TST_char, TST_wchar, // C++ wchar_t TST_int, TST_float, TST_double, TST_bool, // _Bool TST_decimal32, // _Decimal32 TST_decimal64, // _Decimal64 TST_decimal128, // _Decimal128 TST_enum, TST_union, TST_struct, TST_class, // C++ class type TST_typedef, TST_typeofType, TST_typeofExpr }; // type-qualifiers enum TQ { // NOTE: These flags must be kept in sync with QualType::TQ. TQ_unspecified = 0, TQ_const = 1, TQ_restrict = 2, TQ_volatile = 4 }; /// ParsedSpecifiers - Flags to query which specifiers were applied. This is /// returned by getParsedSpecifiers. enum ParsedSpecifiers { PQ_None = 0, PQ_StorageClassSpecifier = 1, PQ_TypeSpecifier = 2, PQ_TypeQualifier = 4, PQ_FunctionSpecifier = 8 }; private: // storage-class-specifier /*SCS*/unsigned StorageClassSpec : 3; bool SCS_thread_specified : 1; // type-specifier /*TSW*/unsigned TypeSpecWidth : 2; /*TSC*/unsigned TypeSpecComplex : 2; /*TSS*/unsigned TypeSpecSign : 2; /*TST*/unsigned TypeSpecType : 5; // type-qualifiers unsigned TypeQualifiers : 3; // Bitwise OR of TQ. // function-specifier bool FS_inline_specified : 1; bool FS_virtual_specified : 1; bool FS_explicit_specified : 1; /// TypeRep - This contains action-specific information about a specific TST. /// For example, for a typedef or struct, it might contain the declaration for /// these. Action::TypeTy *TypeRep; // attributes. AttributeList *AttrList; // List of protocol qualifiers for objective-c classes. Used for // protocol-qualified interfaces "NString" and protocol-qualified id // "id". Action::DeclTy * const *ProtocolQualifiers; unsigned NumProtocolQualifiers; // SourceLocation info. These are null if the item wasn't specified or if // the setting was synthesized. SourceRange Range; SourceLocation StorageClassSpecLoc, SCS_threadLoc; SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; bool BadSpecifier(TST T, const char *&PrevSpec); bool BadSpecifier(TQ T, const char *&PrevSpec); bool BadSpecifier(TSS T, const char *&PrevSpec); bool BadSpecifier(TSC T, const char *&PrevSpec); bool BadSpecifier(TSW T, const char *&PrevSpec); bool BadSpecifier(SCS T, const char *&PrevSpec); DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT void operator=(const DeclSpec&); // DO NOT IMPLEMENT public: DeclSpec() : StorageClassSpec(SCS_unspecified), SCS_thread_specified(false), TypeSpecWidth(TSW_unspecified), TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified), TypeSpecType(TST_unspecified), TypeQualifiers(TSS_unspecified), FS_inline_specified(false), FS_virtual_specified(false), FS_explicit_specified(false), TypeRep(0), AttrList(0), ProtocolQualifiers(0), NumProtocolQualifiers(0) { } ~DeclSpec() { delete AttrList; delete [] ProtocolQualifiers; } // storage-class-specifier SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; } bool isThreadSpecified() const { return SCS_thread_specified; } SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; } SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; } void ClearStorageClassSpecs() { StorageClassSpec = DeclSpec::SCS_unspecified; SCS_thread_specified = false; StorageClassSpecLoc = SourceLocation(); SCS_threadLoc = SourceLocation(); } // type-specifier TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; } TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; } TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; } TST getTypeSpecType() const { return (TST)TypeSpecType; } void *getTypeRep() const { return TypeRep; } const SourceRange &getSourceRange() const { return Range; } SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; } SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool" /// or "union". static const char *getSpecifierName(DeclSpec::TST T); static const char *getSpecifierName(DeclSpec::SCS S); // type-qualifiers /// getTypeQualifiers - Return a set of TQs. unsigned getTypeQualifiers() const { return TypeQualifiers; } SourceLocation getConstSpecLoc() const { return TQ_constLoc; } SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } // function-specifier bool isInlineSpecified() const { return FS_inline_specified; } SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; } bool isVirtualSpecified() const { return FS_virtual_specified; } SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; } bool isExplicitSpecified() const { return FS_explicit_specified; } SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; } void ClearFunctionSpecs() { FS_inline_specified = false; FS_inlineLoc = SourceLocation(); FS_virtual_specified = false; FS_virtualLoc = SourceLocation(); FS_explicit_specified = false; FS_explicitLoc = SourceLocation(); } /// hasTypeSpecifier - Return true if any type-specifier has been found. bool hasTypeSpecifier() const { return getTypeSpecType() != DeclSpec::TST_unspecified || getTypeSpecWidth() != DeclSpec::TSW_unspecified || getTypeSpecComplex() != DeclSpec::TSC_unspecified || getTypeSpecSign() != DeclSpec::TSS_unspecified; } /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this /// DeclSpec includes. /// unsigned getParsedSpecifiers() const; void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); } void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); } /// These methods set the specified attribute of the DeclSpec, but return true /// and ignore the request if invalid (e.g. "extern" then "auto" is /// specified). The name of the previous specifier is returned in prevspec. bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec); bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec); bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec); bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec); bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, Action::TypeTy *TypeRep = 0); bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, const LangOptions &Lang); bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec); bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec); bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec); /// AddAttributes - contatenates two attribute lists. /// The GCC attribute syntax allows for the following: /// /// short __attribute__(( unused, deprecated )) /// int __attribute__(( may_alias, aligned(16) )) var; /// /// This declares 4 attributes using 2 lists. The following syntax is /// also allowed and equivalent to the previous declaration. /// /// short __attribute__((unused)) __attribute__((deprecated)) /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// void AddAttributes(AttributeList *alist) { if (!alist) return; // we parsed __attribute__(()) or had a syntax error if (AttrList) alist->addAttributeList(AttrList); AttrList = alist; } void SetAttributes(AttributeList *AL) { AttrList = AL; } const AttributeList *getAttributes() const { return AttrList; } AttributeList *getAttributes() { return AttrList; } /// TakeAttributes - Return the current attribute list and remove them from /// the DeclSpec so that it doesn't own them. AttributeList *TakeAttributes() { AttributeList *AL = AttrList; AttrList = 0; return AL; } typedef const Action::DeclTy * const * ProtocolQualifierListTy; ProtocolQualifierListTy getProtocolQualifiers() const { return ProtocolQualifiers; } unsigned getNumProtocolQualifiers() const { return NumProtocolQualifiers; } void setProtocolQualifiers(Action::DeclTy* const *Protos, unsigned NumProtos){ if (NumProtos == 0) return; ProtocolQualifiers = new Action::DeclTy*[NumProtos]; memcpy((void*)ProtocolQualifiers, Protos,sizeof(Action::DeclTy*)*NumProtos); NumProtocolQualifiers = NumProtos; } /// Finish - This does final analysis of the declspec, issuing diagnostics for /// things like "_Imaginary" (lacking an FP type). After calling this method, /// DeclSpec is guaranteed self-consistent, even if an error occurred. void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang); }; /// ObjCDeclSpec - This class captures information about /// "declaration specifiers" specific to objective-c class ObjCDeclSpec { public: /// ObjCDeclQualifier - Qualifier used on types in method declarations enum ObjCDeclQualifier { DQ_None = 0x0, DQ_In = 0x1, DQ_Inout = 0x2, DQ_Out = 0x4, DQ_Bycopy = 0x8, DQ_Byref = 0x10, DQ_Oneway = 0x20 }; /// PropertyAttributeKind - list of property attributes. enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0, DQ_PR_readonly = 0x01, DQ_PR_getter = 0x02, DQ_PR_assign = 0x04, DQ_PR_readwrite = 0x08, DQ_PR_retain = 0x10, DQ_PR_copy = 0x20, DQ_PR_nonatomic = 0x40, DQ_PR_setter = 0x80 }; ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), GetterName(0), SetterName(0) {} ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); } ObjCPropertyAttributeKind getPropertyAttributes() const { return ObjCPropertyAttributeKind(PropertyAttributes); } void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { PropertyAttributes = (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal); } const IdentifierInfo *getGetterName() const { return GetterName; } IdentifierInfo *getGetterName() { return GetterName; } void setGetterName(IdentifierInfo *name) { GetterName = name; } const IdentifierInfo *getSetterName() const { return SetterName; } IdentifierInfo *getSetterName() { return SetterName; } void setSetterName(IdentifierInfo *name) { SetterName = name; } private: // FIXME: These two are unrelated and mutially exclusive. So perhaps // we can put them in a union to reflect their mutual exclusiveness // (space saving is negligible). ObjCDeclQualifier objcDeclQualifier : 6; // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind unsigned PropertyAttributes : 8; IdentifierInfo *GetterName; // getter name of NULL if no getter IdentifierInfo *SetterName; // setter name of NULL if no setter }; /// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope /// specifier. class CXXScopeSpec { SourceRange Range; Action::CXXScopeTy *ScopeRep; public: CXXScopeSpec() : ScopeRep(0) {} const SourceRange &getRange() const { return Range; } void setRange(const SourceRange &R) { Range = R; } void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); } SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } Action::CXXScopeTy *getScopeRep() const { return ScopeRep; } void setScopeRep(Action::CXXScopeTy *S) { ScopeRep = S; } bool isEmpty() const { return !Range.isValid(); } bool isNotEmpty() const { return !isEmpty(); } /// isInvalid - An error occured during parsing of the scope specifier. bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } /// isSet - A scope specifier was resolved to a valid C++ scope. bool isSet() const { return getScopeRep() != 0; } void clear() { Range = SourceRange(); ScopeRep = 0; } }; /// DeclaratorChunk - One instance of this struct is used for each type in a /// declarator that is parsed. /// /// This is intended to be a small value object. struct DeclaratorChunk { enum { Pointer, Reference, Array, Function, BlockPointer } Kind; /// Loc - The place where this type was defined. SourceLocation Loc; struct PointerTypeInfo { /// The type qualifiers: const/volatile/restrict. unsigned TypeQuals : 3; AttributeList *AttrList; void destroy() { delete AttrList; } }; struct ReferenceTypeInfo { /// The type qualifier: restrict. [GNU] C++ extension bool HasRestrict; AttributeList *AttrList; void destroy() { delete AttrList; } }; struct ArrayTypeInfo { /// The type qualifiers for the array: const/volatile/restrict. unsigned TypeQuals : 3; /// True if this dimension included the 'static' keyword. bool hasStatic : 1; /// True if this dimension was [*]. In this case, NumElts is null. bool isStar : 1; /// This is the size of the array, or null if [] or [*] was specified. /// Since the parser is multi-purpose, and we don't want to impose a root /// expression class on all clients, NumElts is untyped. Action::ExprTy *NumElts; void destroy() {} }; /// ParamInfo - An array of paraminfo objects is allocated whenever a function /// declarator is parsed. There are two interesting styles of arguments here: /// K&R-style identifier lists and parameter type lists. K&R-style identifier /// lists will have information about the identifier, but no type information. /// Parameter type lists will have type info (if the actions module provides /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'. struct ParamInfo { IdentifierInfo *Ident; SourceLocation IdentLoc; Action::DeclTy *Param; ParamInfo() {} ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::DeclTy *param) : Ident(ident), IdentLoc(iloc), Param(param) {} }; struct FunctionTypeInfo { /// hasPrototype - This is true if the function had at least one typed /// argument. If the function is () or (a,b,c), then it has no prototype, /// and is treated as a K&R-style function. bool hasPrototype : 1; /// isVariadic - If this function has a prototype, and if that proto ends /// with ',...)', this is true. bool isVariadic : 1; /// The type qualifiers: const/volatile/restrict. /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; /// NumArgs - This is the number of formal arguments provided for the /// declarator. unsigned NumArgs; /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that /// describe the arguments for this function declarator. This is null if /// there are no arguments specified. ParamInfo *ArgInfo; void destroy() { delete[] ArgInfo; } }; struct BlockPointerTypeInfo { /// For now, sema will catch these as invalid. /// The type qualifiers: const/volatile/restrict. unsigned TypeQuals : 3; void destroy() {} }; union { PointerTypeInfo Ptr; ReferenceTypeInfo Ref; ArrayTypeInfo Arr; FunctionTypeInfo Fun; BlockPointerTypeInfo Cls; }; /// getAttrs - If there are attributes applied to this declaratorchunk, return /// them. const AttributeList *getAttrs() const { switch (Kind) { default: assert(0 && "Unknown declarator kind!"); case Pointer: return Ptr.AttrList; case Reference: return Ref.AttrList; case Array: return 0; case Function: return 0; case BlockPointer: return 0; // FIXME: Do blocks have attr list? } } /// getPointer - Return a DeclaratorChunk for a pointer. /// static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, AttributeList *AL) { DeclaratorChunk I; I.Kind = Pointer; I.Loc = Loc; I.Ptr.TypeQuals = TypeQuals; I.Ptr.AttrList = AL; return I; } /// getReference - Return a DeclaratorChunk for a reference. /// static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, AttributeList *AL) { DeclaratorChunk I; I.Kind = Reference; I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.AttrList = AL; return I; } /// getArray - Return a DeclaratorChunk for an array. /// static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, bool isStar, void *NumElts, SourceLocation Loc) { DeclaratorChunk I; I.Kind = Array; I.Loc = Loc; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; I.Arr.NumElts = NumElts; return I; } /// getFunction - Return a DeclaratorChunk for a function. 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; } /// getBlockPointer - Return a DeclaratorChunk for a block. /// static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc) { DeclaratorChunk I; I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; return I; } }; /// Declarator - Information about one declarator, including the parsed type /// information and the identifier. When the declarator is fully formed, this /// is turned into the appropriate Decl object. /// /// Declarators come in two types: normal declarators and abstract declarators. /// Abstract declarators are used when parsing types, and don't have an /// identifier. Normal declarators do have ID's. /// /// 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 { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. KNRTypeListContext, // K&R type definition list for formals. TypeNameContext, // Abstract declarator for types. MemberContext, // Struct/Union field. BlockContext, // Declaration within a block in a function. ForContext, // Declaration within first part of a for loop. ConditionContext, // Condition declaration in a C++ if/switch/while/for. TemplateParamContext // Within a template parameter list. }; /// DeclaratorKind - The kind of declarator this represents. enum DeclaratorKind { DK_Abstract, // An abstract declarator (has no identifier) DK_Normal, // A normal declarator (has an identifier). DK_Constructor, // A C++ constructor (identifier is the class name) DK_Destructor, // A C++ destructor (identifier is ~class name) DK_Operator, // A C++ overloaded operator name DK_Conversion // A C++ conversion function (identifier is // "operator " then the type name) }; private: /// Context - Where we are parsing this declarator. /// TheContext Context; /// Kind - What kind of declarator this is. DeclaratorKind Kind; /// DeclTypeInfo - This holds each type that the declarator includes as it is /// parsed. This is pushed from the identifier out, which means that element /// #0 will be the most closely bound to the identifier, and /// DeclTypeInfo.back() will be the least closely bound. llvm::SmallVector DeclTypeInfo; // InvalidType - Set by Sema::GetTypeForDeclarator(). bool InvalidType : 1; /// GroupingParens - Set by Parser::ParseParenDeclarator(). bool GroupingParens : 1; /// AttrList - Attributes. AttributeList *AttrList; /// AsmLabel - The asm label, if specified. Action::ExprTy *AsmLabel; union { // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the // type associated with the constructor, destructor, or conversion // operator. Action::TypeTy *Type; /// When Kind is DK_Operator, this is the actual overloaded /// operator that this declarator names. OverloadedOperatorKind OperatorKind; }; 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) { } ~Declarator() { clear(); } /// getDeclSpec - Return the declaration-specifier that this declarator was /// declared with. const DeclSpec &getDeclSpec() const { return DS; } /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This /// should be used with extreme care: declspecs can often be shared between /// multiple declarators, so mutating the DeclSpec affects all of the /// Declarators. This should only be done when the declspec is known to not /// be shared or when in error recovery etc. DeclSpec &getMutableDeclSpec() { return const_cast(DS); } /// getCXXScopeSpec - Return the C++ scope specifier (global scope or /// nested-name-specifier) that is part of the declarator-id. const CXXScopeSpec &getCXXScopeSpec() const { return SS; } CXXScopeSpec &getCXXScopeSpec() { return SS; } TheContext getContext() const { return Context; } DeclaratorKind getKind() const { return Kind; } // getSourceRange - FIXME: This should be implemented. const SourceRange getSourceRange() const { return SourceRange(); } /// clear - Reset the contents of this Declarator. void clear() { SS.clear(); Identifier = 0; 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!"); } DeclTypeInfo.clear(); delete AttrList; AttrList = 0; AsmLabel = 0; Type = 0; } /// mayOmitIdentifier - Return true if the identifier is either optional or /// not allowed. This is true for typenames, prototypes, and template /// parameter lists. bool mayOmitIdentifier() const { return Context == TypeNameContext || Context == PrototypeContext || Context == TemplateParamContext; } /// mayHaveIdentifier - Return true if the identifier is either optional or /// required. This is true for normal declarators and prototypes, but not /// typenames. bool mayHaveIdentifier() const { return Context != TypeNameContext; } /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be /// followed by a C++ direct initializer, e.g. "int x(1);". bool mayBeFollowedByCXXDirectInit() const { return !hasGroupingParens() && (Context == FileContext || Context == BlockContext || Context == ForContext ); } /// isPastIdentifier - Return true if we have parsed beyond the point where /// the bool isPastIdentifier() const { return IdentifierLoc.isValid(); } /// hasName - Whether this declarator has a name, which might be an /// identifier (accessible via getIdentifier()) or some kind of /// special C++ name (constructor, destructor, etc.). bool hasName() const { return getKind() != DK_Abstract; } IdentifierInfo *getIdentifier() const { return Identifier; } SourceLocation getIdentifierLoc() const { return IdentifierLoc; } void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) { Identifier = ID; IdentifierLoc = Loc; if (ID) Kind = DK_Normal; else Kind = DK_Abstract; } /// setConstructor - Set this declarator to be a C++ constructor /// declarator. void setConstructor(Action::TypeTy *Ty, SourceLocation Loc) { IdentifierLoc = Loc; Kind = DK_Constructor; Type = Ty; } /// setDestructor - Set this declarator to be a C++ destructor /// declarator. void setDestructor(Action::TypeTy *Ty, SourceLocation Loc) { IdentifierLoc = Loc; Kind = DK_Destructor; Type = Ty; } // setConversionFunction - Set this declarator to be a C++ // conversion function declarator (e.g., @c operator int const *). void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc) { Identifier = 0; IdentifierLoc = Loc; Kind = DK_Conversion; Type = Ty; } // setOverloadedOperator - Set this declaration to be a C++ // overloaded operator declarator (e.g., @c operator+). void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc) { IdentifierLoc = Loc; Kind = DK_Operator; OperatorKind = Op; } void AddTypeInfo(const DeclaratorChunk &TI) { DeclTypeInfo.push_back(TI); } /// getNumTypeObjects() - Return the number of types applied to this /// declarator. unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } /// Return the specified TypeInfo from this declarator. TypeInfo #0 is /// closest to the identifier. const DeclaratorChunk &getTypeObject(unsigned i) const { assert(i < DeclTypeInfo.size() && "Invalid type chunk"); return DeclTypeInfo[i]; } DeclaratorChunk &getTypeObject(unsigned i) { assert(i < DeclTypeInfo.size() && "Invalid type chunk"); return DeclTypeInfo[i]; } /// isFunctionDeclarator - Once this declarator is fully parsed and formed, /// this method returns true if the identifier is a function declarator. bool isFunctionDeclarator() const { return !DeclTypeInfo.empty() && DeclTypeInfo[0].Kind == DeclaratorChunk::Function; } /// AddAttributes - simply adds the attribute list to the Declarator. /// These examples both add 3 attributes to "var": /// short int var __attribute__((aligned(16),common,deprecated)); /// short int x, __attribute__((aligned(16)) var /// __attribute__((common,deprecated)); /// void AddAttributes(AttributeList *alist) { if (!alist) return; // we parsed __attribute__(()) or had a syntax error if (AttrList) alist->addAttributeList(AttrList); AttrList = alist; } const AttributeList *getAttributes() const { return AttrList; } AttributeList *getAttributes() { return AttrList; } void setAsmLabel(Action::ExprTy *E) { AsmLabel = E; } Action::ExprTy *getAsmLabel() const { return AsmLabel; } Action::TypeTy *getDeclaratorIdType() const { return Type; } OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; } void setInvalidType(bool flag) { InvalidType = flag; } bool getInvalidType() const { return InvalidType; } void setGroupingParens(bool flag) { GroupingParens = flag; } bool hasGroupingParens() const { return GroupingParens; } }; /// FieldDeclarator - This little struct is used to capture information about /// structure field declarators, which is basically just a bitfield size. struct FieldDeclarator { Declarator D; Action::ExprTy *BitfieldSize; explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) { BitfieldSize = 0; } }; } // end namespace clang #endif