1 //===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines interfaces used for Declaration Specifiers and Declarators.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_PARSE_SEMADECLSPEC_H
15 #define LLVM_CLANG_PARSE_SEMADECLSPEC_H
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Parse/Action.h"
19 #include "clang/Parse/AttributeList.h"
20 #include "llvm/ADT/SmallVector.h"
26 /// DeclSpec - This class captures information about "declaration specifiers",
27 /// which encompasses storage-class-specifiers, type-specifiers,
28 /// type-qualifiers, and function-specifiers.
32 const SourceRange &getSourceRange() const { return Range; }
34 // storage-class-specifier
73 TST_decimal32, // _Decimal32
74 TST_decimal64, // _Decimal64
75 TST_decimal128, // _Decimal128
85 enum TQ { // NOTE: These flags must be kept in sync with QualType::TQ.
92 /// ParsedSpecifiers - Flags to query which specifiers were applied. This is
93 /// returned by getParsedSpecifiers.
94 enum ParsedSpecifiers {
96 PQ_StorageClassSpecifier = 1,
99 PQ_FunctionSpecifier = 8
104 // storage-class-specifier
105 /*SCS*/unsigned StorageClassSpec : 3;
106 bool SCS_thread_specified : 1;
109 /*TSW*/unsigned TypeSpecWidth : 2;
110 /*TSC*/unsigned TypeSpecComplex : 2;
111 /*TSS*/unsigned TypeSpecSign : 2;
112 /*TST*/unsigned TypeSpecType : 4;
115 unsigned TypeQualifiers : 3; // Bitwise OR of TQ.
117 // function-specifier
118 bool FS_inline_specified : 1;
120 /// TypeRep - This contains action-specific information about a specific TST.
121 /// For example, for a typedef or struct, it might contain the declaration for
126 AttributeList *AttrList;
128 // List of protocol qualifiers for objective-c classes.
129 llvm::SmallVector<Action::DeclTy *, 8> *ProtocolQualifiers;
131 // SourceLocation info. These are null if the item wasn't specified or if
132 // the setting was synthesized.
133 SourceLocation StorageClassSpecLoc, SCS_threadLoc;
134 SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc;
135 SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
136 SourceLocation FS_inlineLoc;
138 bool BadSpecifier(TST T, const char *&PrevSpec);
139 bool BadSpecifier(TQ T, const char *&PrevSpec);
140 bool BadSpecifier(TSS T, const char *&PrevSpec);
141 bool BadSpecifier(TSC T, const char *&PrevSpec);
142 bool BadSpecifier(TSW T, const char *&PrevSpec);
143 bool BadSpecifier(SCS T, const char *&PrevSpec);
147 : StorageClassSpec(SCS_unspecified),
148 SCS_thread_specified(false),
149 TypeSpecWidth(TSW_unspecified),
150 TypeSpecComplex(TSC_unspecified),
151 TypeSpecSign(TSS_unspecified),
152 TypeSpecType(TST_unspecified),
153 TypeQualifiers(TSS_unspecified),
154 FS_inline_specified(false),
157 ProtocolQualifiers(0) {
161 delete ProtocolQualifiers;
163 // storage-class-specifier
164 SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
165 bool isThreadSpecified() const { return SCS_thread_specified; }
167 SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
168 SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
170 void ClearStorageClassSpecs() {
171 StorageClassSpec = DeclSpec::SCS_unspecified;
172 SCS_thread_specified = false;
173 StorageClassSpecLoc = SourceLocation();
174 SCS_threadLoc = SourceLocation();
178 TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; }
179 TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
180 TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; }
181 TST getTypeSpecType() const { return (TST)TypeSpecType; }
182 void *getTypeRep() const { return TypeRep; }
184 SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
185 SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
186 SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
187 SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
189 /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
191 static const char *getSpecifierName(DeclSpec::TST T);
192 static const char *getSpecifierName(DeclSpec::SCS S);
196 /// getTypeQualifiers - Return a set of TQs.
197 unsigned getTypeQualifiers() const { return TypeQualifiers; }
198 SourceLocation getConstSpecLoc() const { return TQ_constLoc; }
199 SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
200 SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
203 // function-specifier
204 bool isInlineSpecified() const { return FS_inline_specified; }
205 SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
206 void ClearFunctionSpecs() {
207 FS_inline_specified = false;
208 FS_inlineLoc = SourceLocation();
211 /// hasTypeSpecifier - Return true if any type-specifier has been found.
212 bool hasTypeSpecifier() const {
213 return getTypeSpecType() != DeclSpec::TST_unspecified ||
214 getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
215 getTypeSpecComplex() != DeclSpec::TSC_unspecified ||
216 getTypeSpecSign() != DeclSpec::TSS_unspecified;
220 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
221 /// DeclSpec includes.
223 unsigned getParsedSpecifiers() const;
225 /// These methods set the specified attribute of the DeclSpec, but return true
226 /// and ignore the request if invalid (e.g. "extern" then "auto" is
227 /// specified). The name of the previous specifier is returned in prevspec.
228 bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec);
229 bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec);
230 bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec);
231 bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec);
232 bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec);
233 bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
236 bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
237 const LangOptions &Lang);
239 bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec);
241 /// AddAttributes - contatenates two attribute lists.
242 /// The GCC attribute syntax allows for the following:
244 /// short __attribute__(( unused, deprecated ))
245 /// int __attribute__(( may_alias, aligned(16) )) var;
247 /// This declares 4 attributes using 2 lists. The following syntax is
248 /// also allowed and equivalent to the previous declaration.
250 /// short __attribute__((unused)) __attribute__((deprecated))
251 /// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
253 void AddAttributes(AttributeList *alist) {
255 return; // we parsed __attribute__(()) or had a syntax error
258 alist->addAttributeList(AttrList);
261 void SetAttributes(AttributeList *AL) { AttrList = AL; }
262 AttributeList *getAttributes() const { return AttrList; }
263 void clearAttributes() { AttrList = 0; }
265 llvm::SmallVector<Action::DeclTy *, 8> *getProtocolQualifiers() const {
266 return ProtocolQualifiers;
268 void setProtocolQualifiers(llvm::SmallVector<Action::DeclTy *, 8> *protos) {
269 ProtocolQualifiers = protos;
271 unsigned NumProtocolQualifiers() const {
272 return ProtocolQualifiers ? ProtocolQualifiers->size() : 0;
274 /// Finish - This does final analysis of the declspec, issuing diagnostics for
275 /// things like "_Imaginary" (lacking an FP type). After calling this method,
276 /// DeclSpec is guaranteed self-consistent, even if an error occurred.
277 void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang);
280 void Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
282 D.Report(FullSourceLoc(Loc,SrcMgr), DiagID);
285 void Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
286 unsigned DiagID, const std::string &info) {
287 D.Report(FullSourceLoc(Loc,SrcMgr), DiagID, &info, 1);
291 /// ObjCDeclSpec - This class captures information about
292 /// "declaration specifiers" specific to objective-c
295 /// ObjCDeclQualifier - Qualifier used on types in method declarations
296 enum ObjCDeclQualifier {
306 /// PropertyAttributeKind - list of property attributes.
307 enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0,
308 DQ_PR_readonly = 0x01,
311 DQ_PR_readwrite = 0x08,
314 DQ_PR_nonatomic = 0x40,
319 ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr)
321 ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
322 void setObjCDeclQualifier(ObjCDeclQualifier DQVal)
323 { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); }
325 const ObjCPropertyAttributeKind getPropertyAttributes() const
326 { return PropertyAttributes; }
327 void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
329 (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal);
332 const IdentifierInfo *getGetterName() const { return GetterName; }
333 IdentifierInfo *getGetterName() { return GetterName; }
334 void setGetterName(IdentifierInfo *name) { GetterName = name; }
336 const IdentifierInfo *getSetterName() const { return SetterName; }
337 IdentifierInfo *getSetterName() { return SetterName; }
338 void setSetterName(IdentifierInfo *name) { SetterName = name; }
340 // FIXME: These two are unrelated and mutially exclusive. So perhaps
341 // we can put them in a union to reflect their mutual exclusiveness
342 // (space saving is negligible).
343 ObjCDeclQualifier objcDeclQualifier : 6;
345 ObjCPropertyAttributeKind PropertyAttributes : 8;
346 IdentifierInfo *GetterName; // getter name of NULL if no getter
347 IdentifierInfo *SetterName; // setter name of NULL if no setter
350 /// DeclaratorChunk - One instance of this struct is used for each type in a
351 /// declarator that is parsed.
353 /// This is intended to be a small value object.
354 struct DeclaratorChunk {
356 Pointer, Reference, Array, Function
359 /// Loc - The place where this type was defined.
362 struct PointerTypeInfo {
363 /// The type qualifiers: const/volatile/restrict.
364 unsigned TypeQuals : 3;
368 struct ReferenceTypeInfo {
369 /// The type qualifier: restrict. [GNU] C++ extension
374 struct ArrayTypeInfo {
375 /// The type qualifiers for the array: const/volatile/restrict.
376 unsigned TypeQuals : 3;
378 /// True if this dimension included the 'static' keyword.
381 /// True if this dimension was [*]. In this case, NumElts is null.
384 /// This is the size of the array, or null if [] or [*] was specified.
385 /// Since the parser is multi-purpose, and we don't want to impose a root
386 /// expression class on all clients, NumElts is untyped.
387 Action::ExprTy *NumElts;
391 /// ParamInfo - An array of paraminfo objects is allocated whenever a function
392 /// declarator is parsed. There are two interesting styles of arguments here:
393 /// K&R-style identifier lists and parameter type lists. K&R-style identifier
394 /// lists will have information about the identifier, but no type information.
395 /// Parameter type lists will have type info (if the actions module provides
396 /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
398 IdentifierInfo *Ident;
399 SourceLocation IdentLoc;
400 Action::TypeTy *TypeInfo;
402 AttributeList *AttrList;
404 ParamInfo(IdentifierInfo *ident, SourceLocation iloc, Action::TypeTy *typ,
405 bool flag = false, AttributeList *AL = 0)
406 : Ident(ident), IdentLoc(iloc), TypeInfo(typ), InvalidType(flag),
410 struct FunctionTypeInfo {
411 /// hasPrototype - This is true if the function had at least one typed
412 /// argument. If the function is () or (a,b,c), then it has no prototype,
413 /// and is treated as a K&R-style function.
414 bool hasPrototype : 1;
416 /// isVariadic - If this function has a prototype, and if that proto ends
417 /// with ',...)', this is true.
420 /// NumArgs - This is the number of formal arguments provided for the
424 /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
425 /// describe the arguments for this function declarator. This is null if
426 /// there are no arguments specified.
436 ReferenceTypeInfo Ref;
438 FunctionTypeInfo Fun;
442 /// getPointer - Return a DeclaratorChunk for a pointer.
444 static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc) {
448 I.Ptr.TypeQuals = TypeQuals;
452 /// getReference - Return a DeclaratorChunk for a reference.
454 static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc) {
458 I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
462 /// getArray - Return a DeclaratorChunk for an array.
464 static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
465 bool isStar, void *NumElts,
466 SourceLocation Loc) {
470 I.Arr.TypeQuals = TypeQuals;
471 I.Arr.hasStatic = isStatic;
472 I.Arr.isStar = isStar;
473 I.Arr.NumElts = NumElts;
477 /// getFunction - Return a DeclaratorChunk for a function.
478 static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
479 ParamInfo *ArgInfo, unsigned NumArgs,
480 SourceLocation Loc) {
484 I.Fun.hasPrototype = hasProto;
485 I.Fun.isVariadic = isVariadic;
486 I.Fun.NumArgs = NumArgs;
489 // new[] an argument array if needed.
491 I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
492 memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
499 /// Declarator - Information about one declarator, including the parsed type
500 /// information and the identifier. When the declarator is fully formed, this
501 /// is turned into the appropriate Decl object.
503 /// Declarators come in two types: normal declarators and abstract declarators.
504 /// Abstract declarators are used when parsing types, and don't have an
505 /// identifier. Normal declarators do have ID's.
507 /// Instances of this class should be a transient object that lives on the
508 /// stack, not objects that are allocated in large quantities on the heap.
511 IdentifierInfo *Identifier;
512 SourceLocation IdentifierLoc;
516 FileContext, // File scope declaration.
517 PrototypeContext, // Within a function prototype.
518 KNRTypeListContext, // K&R type definition list for formals.
519 TypeNameContext, // Abstract declarator for types.
520 MemberContext, // Struct/Union field.
521 BlockContext, // Declaration within a block in a function.
522 ForContext // Declaration within first part of a for loop.
525 /// Context - Where we are parsing this declarator.
529 /// DeclTypeInfo - This holds each type that the declarator includes as it is
530 /// parsed. This is pushed from the identifier out, which means that element
531 /// #0 will be the most closely bound to the identifier, and
532 /// DeclTypeInfo.back() will be the least closely bound.
533 llvm::SmallVector<DeclaratorChunk, 8> DeclTypeInfo;
535 // InvalidType - Set by Sema::GetTypeForDeclarator().
539 AttributeList *AttrList;
541 Declarator(DeclSpec &ds, TheContext C)
542 : DS(ds), Identifier(0), Context(C), InvalidType(false), AttrList(0) {
549 /// getDeclSpec - Return the declaration-specifier that this declarator was
551 DeclSpec &getDeclSpec() const { return DS; }
553 TheContext getContext() const { return Context; }
555 // getSourceRange - FIXME: This should be implemented.
556 const SourceRange getSourceRange() const { return SourceRange(); }
558 /// clear - Reset the contents of this Declarator.
561 IdentifierLoc = SourceLocation();
563 for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) {
564 if (DeclTypeInfo[i].Kind == DeclaratorChunk::Function)
565 DeclTypeInfo[i].Fun.destroy();
566 else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Pointer)
567 DeclTypeInfo[i].Ptr.destroy();
568 else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Reference)
569 DeclTypeInfo[i].Ref.destroy();
570 else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Array)
571 DeclTypeInfo[i].Arr.destroy();
573 assert(0 && "Unknown decl type!");
575 DeclTypeInfo.clear();
580 /// mayOmitIdentifier - Return true if the identifier is either optional or
581 /// not allowed. This is true for typenames and prototypes.
582 bool mayOmitIdentifier() const {
583 return Context == TypeNameContext || Context == PrototypeContext;
586 /// mayHaveIdentifier - Return true if the identifier is either optional or
587 /// required. This is true for normal declarators and prototypes, but not
589 bool mayHaveIdentifier() const {
590 return Context != TypeNameContext;
593 /// isPastIdentifier - Return true if we have parsed beyond the point where
595 bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
597 IdentifierInfo *getIdentifier() const { return Identifier; }
598 SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
600 void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
605 void AddTypeInfo(const DeclaratorChunk &TI) {
606 DeclTypeInfo.push_back(TI);
609 /// getNumTypeObjects() - Return the number of types applied to this
611 unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
613 /// Return the specified TypeInfo from this declarator. TypeInfo #0 is
614 /// closest to the identifier.
615 const DeclaratorChunk &getTypeObject(unsigned i) const {
616 assert(i < DeclTypeInfo.size() && "Invalid type chunk");
617 return DeclTypeInfo[i];
619 DeclaratorChunk &getTypeObject(unsigned i) {
620 assert(i < DeclTypeInfo.size() && "Invalid type chunk");
621 return DeclTypeInfo[i];
624 /// isFunctionDeclarator - Once this declarator is fully parsed and formed,
625 /// this method returns true if the identifier is a function declarator.
626 bool isFunctionDeclarator() const {
627 return !DeclTypeInfo.empty() &&
628 DeclTypeInfo[0].Kind == DeclaratorChunk::Function;
631 /// AddAttributes - simply adds the attribute list to the Declarator.
632 /// Unlike AddAttributes on DeclSpec, this routine should never have to
633 /// concatenate two lists. The following syntax adds 3 attributes to "var":
635 /// short int var __attribute__((aligned(16),common,deprecated));
637 void AddAttributes(AttributeList *alist) {
639 return; // we parsed __attribute__(()) or had a syntax error
640 assert((AttrList == 0) && "Declarator already has an attribute list");
643 AttributeList *getAttributes() const { return AttrList; }
645 void setInvalidType(bool flag) { InvalidType = flag; }
646 bool getInvalidType() { return InvalidType; }
649 } // end namespace clang