]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Parse/DeclSpec.cpp
Import Clang, at r72805.
[FreeBSD/FreeBSD.git] / lib / Parse / DeclSpec.cpp
1 //===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements semantic analysis for declaration specifiers.
11 //
12 //===----------------------------------------------------------------------===//
13
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"
19 #include <cstring>
20 using namespace clang;
21
22
23 static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
24                               SourceManager &SrcMgr, unsigned DiagID) {
25   return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
26 }
27
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,
32                                              ParamInfo *ArgInfo,
33                                              unsigned NumArgs,
34                                              unsigned TypeQuals,
35                                              bool hasExceptionSpec,
36                                              SourceLocation ThrowLoc,
37                                              bool hasAnyExceptionSpec,
38                                              ActionBase::TypeTy **Exceptions,
39                                              SourceRange *ExceptionRanges,
40                                              unsigned NumExceptions,
41                                              SourceLocation Loc,
42                                              Declarator &TheDeclarator) {
43   DeclaratorChunk I;
44   I.Kind                 = Function;
45   I.Loc                  = Loc;
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;
52   I.Fun.ArgInfo          = 0;
53   I.Fun.hasExceptionSpec = hasExceptionSpec;
54   I.Fun.ThrowLoc         = ThrowLoc.getRawEncoding();
55   I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
56   I.Fun.NumExceptions    = NumExceptions;
57   I.Fun.Exceptions       = 0;
58
59   // new[] an argument array if needed.
60   if (NumArgs) {
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;
70     } else {
71       I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
72       I.Fun.DeleteArgInfo = true;
73     }
74     memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
75   }
76   // new[] an exception array if needed
77   if (NumExceptions) {
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];
82     }
83   }
84   return I;
85 }
86
87 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
88 /// declaration specifier includes.
89 ///
90 unsigned DeclSpec::getParsedSpecifiers() const {
91   unsigned Res = 0;
92   if (StorageClassSpec != SCS_unspecified ||
93       SCS_thread_specified)
94     Res |= PQ_StorageClassSpecifier;
95
96   if (TypeQualifiers != TQ_unspecified)
97     Res |= PQ_TypeQualifier;
98   
99   if (hasTypeSpecifier())
100     Res |= PQ_TypeSpecifier;
101   
102   if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
103     Res |= PQ_FunctionSpecifier;
104   return Res;
105 }
106
107 const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
108   switch (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";
118   }
119 }
120
121 bool DeclSpec::BadSpecifier(SCS S, const char *&PrevSpec) {
122   PrevSpec = getSpecifierName(S);
123   return true;
124 }
125
126 bool DeclSpec::BadSpecifier(TSW W, const char *&PrevSpec) {
127   switch (W) {
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;
132   }
133   return true;
134 }
135
136 bool DeclSpec::BadSpecifier(TSC C, const char *&PrevSpec) {
137   switch (C) {
138   case TSC_unspecified: PrevSpec = "unspecified"; break;
139   case TSC_imaginary:   PrevSpec = "imaginary"; break;
140   case TSC_complex:     PrevSpec = "complex"; break;
141   }
142   return true;
143 }
144
145
146 bool DeclSpec::BadSpecifier(TSS S, const char *&PrevSpec) {
147   switch (S) {
148   case TSS_unspecified: PrevSpec = "unspecified"; break;
149   case TSS_signed:      PrevSpec = "signed"; break;
150   case TSS_unsigned:    PrevSpec = "unsigned"; break;
151   }
152   return true;
153 }
154
155 const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
156   switch (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_int:         return "int";
163   case DeclSpec::TST_float:       return "float";
164   case DeclSpec::TST_double:      return "double";
165   case DeclSpec::TST_bool:        return "_Bool";
166   case DeclSpec::TST_decimal32:   return "_Decimal32";
167   case DeclSpec::TST_decimal64:   return "_Decimal64";
168   case DeclSpec::TST_decimal128:  return "_Decimal128";
169   case DeclSpec::TST_enum:        return "enum";
170   case DeclSpec::TST_class:       return "class";
171   case DeclSpec::TST_union:       return "union";
172   case DeclSpec::TST_struct:      return "struct";
173   case DeclSpec::TST_typename:    return "type-name";
174   case DeclSpec::TST_typeofType:
175   case DeclSpec::TST_typeofExpr:  return "typeof";
176   }
177 }
178
179 bool DeclSpec::BadSpecifier(TST T, const char *&PrevSpec) {
180   PrevSpec = getSpecifierName(T);
181   return true;
182 }
183
184 bool DeclSpec::BadSpecifier(TQ T, const char *&PrevSpec) {
185   switch (T) {
186   case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break;
187   case DeclSpec::TQ_const:       PrevSpec = "const"; break;
188   case DeclSpec::TQ_restrict:    PrevSpec = "restrict"; break;
189   case DeclSpec::TQ_volatile:    PrevSpec = "volatile"; break;
190   }
191   return true;
192 }
193
194 bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
195                                    const char *&PrevSpec) {
196   if (StorageClassSpec != SCS_unspecified)
197     return BadSpecifier((SCS)StorageClassSpec, PrevSpec);
198   StorageClassSpec = S;
199   StorageClassSpecLoc = Loc;
200   assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
201   return false;
202 }
203
204 bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, 
205                                          const char *&PrevSpec) {
206   if (SCS_thread_specified) {
207     PrevSpec = "__thread";
208     return true;
209   }
210   SCS_thread_specified = true;
211   SCS_threadLoc = Loc;
212   return false;
213 }
214
215
216 /// These methods set the specified attribute of the DeclSpec, but return true
217 /// and ignore the request if invalid (e.g. "extern" then "auto" is
218 /// specified).
219 bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
220                                 const char *&PrevSpec) {
221   if (TypeSpecWidth != TSW_unspecified &&
222       // Allow turning long -> long long.
223       (W != TSW_longlong || TypeSpecWidth != TSW_long))
224     return BadSpecifier((TSW)TypeSpecWidth, PrevSpec);
225   TypeSpecWidth = W;
226   TSWLoc = Loc;
227   return false;
228 }
229
230 bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, 
231                                   const char *&PrevSpec) {
232   if (TypeSpecComplex != TSC_unspecified)
233     return BadSpecifier((TSC)TypeSpecComplex, PrevSpec);
234   TypeSpecComplex = C;
235   TSCLoc = Loc;
236   return false;
237 }
238
239 bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, 
240                                const char *&PrevSpec) {
241   if (TypeSpecSign != TSS_unspecified)
242     return BadSpecifier((TSS)TypeSpecSign, PrevSpec);
243   TypeSpecSign = S;
244   TSSLoc = Loc;
245   return false;
246 }
247
248 bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
249                                const char *&PrevSpec, void *Rep,
250                                bool Owned) {
251   if (TypeSpecType != TST_unspecified)
252     return BadSpecifier((TST)TypeSpecType, PrevSpec);
253   TypeSpecType = T;
254   TypeRep = Rep;
255   TSTLoc = Loc;
256   TypeSpecOwned = Owned;
257   return false;
258 }
259
260 bool DeclSpec::SetTypeSpecError() {
261   TypeSpecType = TST_error;
262   TypeRep = 0;
263   TSTLoc = SourceLocation();
264   return false;
265 }
266
267 bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
268                            const LangOptions &Lang) {
269   // Duplicates turn into warnings pre-C99.
270   if ((TypeQualifiers & T) && !Lang.C99)
271     return BadSpecifier(T, PrevSpec);
272   TypeQualifiers |= T;
273   
274   switch (T) {
275   default: assert(0 && "Unknown type qualifier!");
276   case TQ_const:    TQ_constLoc = Loc; break;
277   case TQ_restrict: TQ_restrictLoc = Loc; break;
278   case TQ_volatile: TQ_volatileLoc = Loc; break;
279   }
280   return false;
281 }
282
283 bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec){
284   // 'inline inline' is ok.
285   FS_inline_specified = true;
286   FS_inlineLoc = Loc;
287   return false;
288 }
289
290 bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec){
291   // 'virtual virtual' is ok.
292   FS_virtual_specified = true;
293   FS_virtualLoc = Loc;
294   return false;
295 }
296
297 bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec){
298   // 'explicit explicit' is ok.
299   FS_explicit_specified = true;
300   FS_explicitLoc = Loc;
301   return false;
302 }
303
304 bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec) {
305   if (Friend_specified) {
306     PrevSpec = "friend";
307     return true;
308   }
309   
310   Friend_specified = true;
311   FriendLoc = Loc;
312   return false;
313 }
314
315 /// Finish - This does final analysis of the declspec, rejecting things like
316 /// "_Imaginary" (lacking an FP type).  This returns a diagnostic to issue or
317 /// diag::NUM_DIAGNOSTICS if there is no error.  After calling this method,
318 /// DeclSpec is guaranteed self-consistent, even if an error occurred.
319 void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
320   // Check the type specifier components first.
321   SourceManager &SrcMgr = PP.getSourceManager();
322
323   // signed/unsigned are only valid with int/char/wchar_t.
324   if (TypeSpecSign != TSS_unspecified) {
325     if (TypeSpecType == TST_unspecified)
326       TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
327     else if (TypeSpecType != TST_int  &&
328              TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
329       Diag(D, TSSLoc, SrcMgr, diag::err_invalid_sign_spec)
330         << getSpecifierName((TST)TypeSpecType);
331       // signed double -> double.
332       TypeSpecSign = TSS_unspecified;
333     }
334   }
335
336   // Validate the width of the type.
337   switch (TypeSpecWidth) {
338   case TSW_unspecified: break;
339   case TSW_short:    // short int
340   case TSW_longlong: // long long int
341     if (TypeSpecType == TST_unspecified)
342       TypeSpecType = TST_int; // short -> short int, long long -> long long int.
343     else if (TypeSpecType != TST_int) {
344       Diag(D, TSWLoc, SrcMgr,
345            TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
346                                       : diag::err_invalid_longlong_spec)
347         <<  getSpecifierName((TST)TypeSpecType);
348       TypeSpecType = TST_int;
349     }
350     break;
351   case TSW_long:  // long double, long int
352     if (TypeSpecType == TST_unspecified)
353       TypeSpecType = TST_int;  // long -> long int.
354     else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
355       Diag(D, TSWLoc, SrcMgr, diag::err_invalid_long_spec)
356         << getSpecifierName((TST)TypeSpecType);
357       TypeSpecType = TST_int;
358     }
359     break;
360   }
361   
362   // TODO: if the implementation does not implement _Complex or _Imaginary,
363   // disallow their use.  Need information about the backend.
364   if (TypeSpecComplex != TSC_unspecified) {
365     if (TypeSpecType == TST_unspecified) {
366       Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex)
367         << CodeModificationHint::CreateInsertion(
368                               PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
369                                                  " double");
370       TypeSpecType = TST_double;   // _Complex -> _Complex double.
371     } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
372       // Note that this intentionally doesn't include _Complex _Bool.
373       Diag(D, TSTLoc, SrcMgr, diag::ext_integer_complex);
374     } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
375       Diag(D, TSCLoc, SrcMgr, diag::err_invalid_complex_spec)
376         << getSpecifierName((TST)TypeSpecType);
377       TypeSpecComplex = TSC_unspecified;
378     }
379   }
380
381   // Okay, now we can infer the real type.
382   
383   // TODO: return "auto function" and other bad things based on the real type.
384   
385   // 'data definition has no type or storage class'?
386 }
387
388 bool DeclSpec::isMissingDeclaratorOk() {
389   TST tst = getTypeSpecType();
390   return (tst == TST_union
391        || tst == TST_struct
392        || tst == TST_class
393        || tst == TST_enum
394           ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
395 }