1 //===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
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 implements semantic analysis for declaration specifiers.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Parse/DeclSpec.h"
15 #include "clang/Parse/ParseDiagnostic.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Basic/LangOptions.h"
18 #include "llvm/ADT/STLExtras.h"
20 using namespace clang
;
23 static DiagnosticBuilder
Diag(Diagnostic
&D
, SourceLocation Loc
,
24 SourceManager
&SrcMgr
, unsigned DiagID
) {
25 return D
.Report(FullSourceLoc(Loc
, SrcMgr
), DiagID
);
28 /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
29 /// "TheDeclarator" is the declarator that this will be added to.
30 DeclaratorChunk
DeclaratorChunk::getFunction(bool hasProto
, bool isVariadic
,
31 SourceLocation EllipsisLoc
,
35 bool hasExceptionSpec
,
36 SourceLocation ThrowLoc
,
37 bool hasAnyExceptionSpec
,
38 ActionBase::TypeTy
**Exceptions
,
39 SourceRange
*ExceptionRanges
,
40 unsigned NumExceptions
,
42 Declarator
&TheDeclarator
) {
46 I
.Fun
.hasPrototype
= hasProto
;
47 I
.Fun
.isVariadic
= isVariadic
;
48 I
.Fun
.EllipsisLoc
= EllipsisLoc
.getRawEncoding();
49 I
.Fun
.DeleteArgInfo
= false;
50 I
.Fun
.TypeQuals
= TypeQuals
;
51 I
.Fun
.NumArgs
= NumArgs
;
53 I
.Fun
.hasExceptionSpec
= hasExceptionSpec
;
54 I
.Fun
.ThrowLoc
= ThrowLoc
.getRawEncoding();
55 I
.Fun
.hasAnyExceptionSpec
= hasAnyExceptionSpec
;
56 I
.Fun
.NumExceptions
= NumExceptions
;
59 // new[] an argument array if needed.
61 // If the 'InlineParams' in Declarator is unused and big enough, put our
62 // parameter list there (in an effort to avoid new/delete traffic). If it
63 // is already used (consider a function returning a function pointer) or too
64 // small (function taking too many arguments), go to the heap.
65 if (!TheDeclarator
.InlineParamsUsed
&&
66 NumArgs
<= llvm::array_lengthof(TheDeclarator
.InlineParams
)) {
67 I
.Fun
.ArgInfo
= TheDeclarator
.InlineParams
;
68 I
.Fun
.DeleteArgInfo
= false;
69 TheDeclarator
.InlineParamsUsed
= true;
71 I
.Fun
.ArgInfo
= new DeclaratorChunk::ParamInfo
[NumArgs
];
72 I
.Fun
.DeleteArgInfo
= true;
74 memcpy(I
.Fun
.ArgInfo
, ArgInfo
, sizeof(ArgInfo
[0])*NumArgs
);
76 // new[] an exception array if needed
78 I
.Fun
.Exceptions
= new DeclaratorChunk::TypeAndRange
[NumExceptions
];
79 for (unsigned i
= 0; i
!= NumExceptions
; ++i
) {
80 I
.Fun
.Exceptions
[i
].Ty
= Exceptions
[i
];
81 I
.Fun
.Exceptions
[i
].Range
= ExceptionRanges
[i
];
87 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
88 /// declaration specifier includes.
90 unsigned DeclSpec::getParsedSpecifiers() const {
92 if (StorageClassSpec
!= SCS_unspecified
||
94 Res
|= PQ_StorageClassSpecifier
;
96 if (TypeQualifiers
!= TQ_unspecified
)
97 Res
|= PQ_TypeQualifier
;
99 if (hasTypeSpecifier())
100 Res
|= PQ_TypeSpecifier
;
102 if (FS_inline_specified
|| FS_virtual_specified
|| FS_explicit_specified
)
103 Res
|= PQ_FunctionSpecifier
;
107 const char *DeclSpec::getSpecifierName(DeclSpec::SCS S
) {
109 default: assert(0 && "Unknown typespec!");
110 case DeclSpec::SCS_unspecified
: return "unspecified";
111 case DeclSpec::SCS_typedef
: return "typedef";
112 case DeclSpec::SCS_extern
: return "extern";
113 case DeclSpec::SCS_static
: return "static";
114 case DeclSpec::SCS_auto
: return "auto";
115 case DeclSpec::SCS_register
: return "register";
116 case DeclSpec::SCS_private_extern
: return "__private_extern__";
117 case DeclSpec::SCS_mutable
: return "mutable";
121 bool DeclSpec::BadSpecifier(SCS S
, const char *&PrevSpec
) {
122 PrevSpec
= getSpecifierName(S
);
126 bool DeclSpec::BadSpecifier(TSW W
, const char *&PrevSpec
) {
128 case TSW_unspecified
: PrevSpec
= "unspecified"; break;
129 case TSW_short
: PrevSpec
= "short"; break;
130 case TSW_long
: PrevSpec
= "long"; break;
131 case TSW_longlong
: PrevSpec
= "long long"; break;
136 bool DeclSpec::BadSpecifier(TSC C
, const char *&PrevSpec
) {
138 case TSC_unspecified
: PrevSpec
= "unspecified"; break;
139 case TSC_imaginary
: PrevSpec
= "imaginary"; break;
140 case TSC_complex
: PrevSpec
= "complex"; break;
146 bool DeclSpec::BadSpecifier(TSS S
, const char *&PrevSpec
) {
148 case TSS_unspecified
: PrevSpec
= "unspecified"; break;
149 case TSS_signed
: PrevSpec
= "signed"; break;
150 case TSS_unsigned
: PrevSpec
= "unsigned"; break;
155 const char *DeclSpec::getSpecifierName(DeclSpec::TST T
) {
157 default: assert(0 && "Unknown typespec!");
158 case DeclSpec::TST_unspecified
: return "unspecified";
159 case DeclSpec::TST_void
: return "void";
160 case DeclSpec::TST_char
: return "char";
161 case DeclSpec::TST_wchar
: return "wchar_t";
162 case DeclSpec::TST_char16
: return "char16_t";
163 case DeclSpec::TST_char32
: return "char32_t";
164 case DeclSpec::TST_int
: return "int";
165 case DeclSpec::TST_float
: return "float";
166 case DeclSpec::TST_double
: return "double";
167 case DeclSpec::TST_bool
: return "_Bool";
168 case DeclSpec::TST_decimal32
: return "_Decimal32";
169 case DeclSpec::TST_decimal64
: return "_Decimal64";
170 case DeclSpec::TST_decimal128
: return "_Decimal128";
171 case DeclSpec::TST_enum
: return "enum";
172 case DeclSpec::TST_class
: return "class";
173 case DeclSpec::TST_union
: return "union";
174 case DeclSpec::TST_struct
: return "struct";
175 case DeclSpec::TST_typename
: return "type-name";
176 case DeclSpec::TST_typeofType
:
177 case DeclSpec::TST_typeofExpr
: return "typeof";
178 case DeclSpec::TST_auto
: return "auto";
182 bool DeclSpec::BadSpecifier(TST T
, const char *&PrevSpec
) {
183 PrevSpec
= getSpecifierName(T
);
187 bool DeclSpec::BadSpecifier(TQ T
, const char *&PrevSpec
) {
189 case DeclSpec::TQ_unspecified
: PrevSpec
= "unspecified"; break;
190 case DeclSpec::TQ_const
: PrevSpec
= "const"; break;
191 case DeclSpec::TQ_restrict
: PrevSpec
= "restrict"; break;
192 case DeclSpec::TQ_volatile
: PrevSpec
= "volatile"; break;
197 bool DeclSpec::SetStorageClassSpec(SCS S
, SourceLocation Loc
,
198 const char *&PrevSpec
) {
199 if (StorageClassSpec
!= SCS_unspecified
)
200 return BadSpecifier((SCS
)StorageClassSpec
, PrevSpec
);
201 StorageClassSpec
= S
;
202 StorageClassSpecLoc
= Loc
;
203 assert((unsigned)S
== StorageClassSpec
&& "SCS constants overflow bitfield");
207 bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc
,
208 const char *&PrevSpec
) {
209 if (SCS_thread_specified
) {
210 PrevSpec
= "__thread";
213 SCS_thread_specified
= true;
219 /// These methods set the specified attribute of the DeclSpec, but return true
220 /// and ignore the request if invalid (e.g. "extern" then "auto" is
222 bool DeclSpec::SetTypeSpecWidth(TSW W
, SourceLocation Loc
,
223 const char *&PrevSpec
) {
224 if (TypeSpecWidth
!= TSW_unspecified
&&
225 // Allow turning long -> long long.
226 (W
!= TSW_longlong
|| TypeSpecWidth
!= TSW_long
))
227 return BadSpecifier((TSW
)TypeSpecWidth
, PrevSpec
);
233 bool DeclSpec::SetTypeSpecComplex(TSC C
, SourceLocation Loc
,
234 const char *&PrevSpec
) {
235 if (TypeSpecComplex
!= TSC_unspecified
)
236 return BadSpecifier((TSC
)TypeSpecComplex
, PrevSpec
);
242 bool DeclSpec::SetTypeSpecSign(TSS S
, SourceLocation Loc
,
243 const char *&PrevSpec
) {
244 if (TypeSpecSign
!= TSS_unspecified
)
245 return BadSpecifier((TSS
)TypeSpecSign
, PrevSpec
);
251 bool DeclSpec::SetTypeSpecType(TST T
, SourceLocation Loc
,
252 const char *&PrevSpec
, void *Rep
,
254 if (TypeSpecType
!= TST_unspecified
)
255 return BadSpecifier((TST
)TypeSpecType
, PrevSpec
);
259 TypeSpecOwned
= Owned
;
263 bool DeclSpec::SetTypeSpecError() {
264 TypeSpecType
= TST_error
;
266 TSTLoc
= SourceLocation();
270 bool DeclSpec::SetTypeQual(TQ T
, SourceLocation Loc
, const char *&PrevSpec
,
271 const LangOptions
&Lang
) {
272 // Duplicates turn into warnings pre-C99.
273 if ((TypeQualifiers
& T
) && !Lang
.C99
)
274 return BadSpecifier(T
, PrevSpec
);
278 default: assert(0 && "Unknown type qualifier!");
279 case TQ_const
: TQ_constLoc
= Loc
; break;
280 case TQ_restrict
: TQ_restrictLoc
= Loc
; break;
281 case TQ_volatile
: TQ_volatileLoc
= Loc
; break;
286 bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc
, const char *&PrevSpec
){
287 // 'inline inline' is ok.
288 FS_inline_specified
= true;
293 bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc
, const char *&PrevSpec
){
294 // 'virtual virtual' is ok.
295 FS_virtual_specified
= true;
300 bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc
, const char *&PrevSpec
){
301 // 'explicit explicit' is ok.
302 FS_explicit_specified
= true;
303 FS_explicitLoc
= Loc
;
307 bool DeclSpec::SetFriendSpec(SourceLocation Loc
, const char *&PrevSpec
) {
308 if (Friend_specified
) {
313 Friend_specified
= true;
318 /// Finish - This does final analysis of the declspec, rejecting things like
319 /// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
320 /// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
321 /// DeclSpec is guaranteed self-consistent, even if an error occurred.
322 void DeclSpec::Finish(Diagnostic
&D
, Preprocessor
&PP
) {
323 // Check the type specifier components first.
324 SourceManager
&SrcMgr
= PP
.getSourceManager();
326 // signed/unsigned are only valid with int/char/wchar_t.
327 if (TypeSpecSign
!= TSS_unspecified
) {
328 if (TypeSpecType
== TST_unspecified
)
329 TypeSpecType
= TST_int
; // unsigned -> unsigned int, signed -> signed int.
330 else if (TypeSpecType
!= TST_int
&&
331 TypeSpecType
!= TST_char
&& TypeSpecType
!= TST_wchar
) {
332 Diag(D
, TSSLoc
, SrcMgr
, diag::err_invalid_sign_spec
)
333 << getSpecifierName((TST
)TypeSpecType
);
334 // signed double -> double.
335 TypeSpecSign
= TSS_unspecified
;
339 // Validate the width of the type.
340 switch (TypeSpecWidth
) {
341 case TSW_unspecified
: break;
342 case TSW_short
: // short int
343 case TSW_longlong
: // long long int
344 if (TypeSpecType
== TST_unspecified
)
345 TypeSpecType
= TST_int
; // short -> short int, long long -> long long int.
346 else if (TypeSpecType
!= TST_int
) {
347 Diag(D
, TSWLoc
, SrcMgr
,
348 TypeSpecWidth
== TSW_short
? diag::err_invalid_short_spec
349 : diag::err_invalid_longlong_spec
)
350 << getSpecifierName((TST
)TypeSpecType
);
351 TypeSpecType
= TST_int
;
354 case TSW_long
: // long double, long int
355 if (TypeSpecType
== TST_unspecified
)
356 TypeSpecType
= TST_int
; // long -> long int.
357 else if (TypeSpecType
!= TST_int
&& TypeSpecType
!= TST_double
) {
358 Diag(D
, TSWLoc
, SrcMgr
, diag::err_invalid_long_spec
)
359 << getSpecifierName((TST
)TypeSpecType
);
360 TypeSpecType
= TST_int
;
365 // TODO: if the implementation does not implement _Complex or _Imaginary,
366 // disallow their use. Need information about the backend.
367 if (TypeSpecComplex
!= TSC_unspecified
) {
368 if (TypeSpecType
== TST_unspecified
) {
369 Diag(D
, TSCLoc
, SrcMgr
, diag::ext_plain_complex
)
370 << CodeModificationHint::CreateInsertion(
371 PP
.getLocForEndOfToken(getTypeSpecComplexLoc()),
373 TypeSpecType
= TST_double
; // _Complex -> _Complex double.
374 } else if (TypeSpecType
== TST_int
|| TypeSpecType
== TST_char
) {
375 // Note that this intentionally doesn't include _Complex _Bool.
376 Diag(D
, TSTLoc
, SrcMgr
, diag::ext_integer_complex
);
377 } else if (TypeSpecType
!= TST_float
&& TypeSpecType
!= TST_double
) {
378 Diag(D
, TSCLoc
, SrcMgr
, diag::err_invalid_complex_spec
)
379 << getSpecifierName((TST
)TypeSpecType
);
380 TypeSpecComplex
= TSC_unspecified
;
384 // Okay, now we can infer the real type.
386 // TODO: return "auto function" and other bad things based on the real type.
388 // 'data definition has no type or storage class'?
391 bool DeclSpec::isMissingDeclaratorOk() {
392 TST tst
= getTypeSpecType();
393 return (tst
== TST_union
397 ) && getTypeRep() != 0 && StorageClassSpec
!= DeclSpec::SCS_typedef
;