blob: e4fd47e2ac958b90b02d5e5dfcf0ef836278fab9 [file] [log] [blame]
Chris Lattnerb9093cd2006-08-04 04:39:53 +00001//===--- Declarations.cpp - Declaration Representation Implementation -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Declaration representation classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Declarations.h"
Chris Lattnerda48a8e2006-08-04 05:25:55 +000015#include "clang/Basic/LangOptions.h"
Chris Lattner839713c2006-08-04 06:15:52 +000016#include "clang/Basic/SourceLocation.h"
Chris Lattnerb9093cd2006-08-04 04:39:53 +000017using namespace llvm;
18using namespace clang;
19
20/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
21///
22unsigned DeclSpec::getParsedSpecifiers() const {
23 unsigned Res = 0;
24 if (StorageClassSpec != SCS_unspecified)
25 Res |= PQ_StorageClassSpecifier;
26
27 if (TypeQualifiers != TQ_unspecified)
28 Res |= PQ_TypeQualifier;
29
30 if (TypeSpecWidth != TSW_unspecified ||
31 TypeSpecComplex != TSC_unspecified ||
32 TypeSpecSign != TSS_unspecified ||
33 TypeSpecType != TST_unspecified)
34 Res |= PQ_TypeSpecifier;
35
36 if (FuncSpec != FS_unspecified)
37 Res |= PQ_FunctionSpecifier;
38 return Res;
39}
40
41
42static bool BadSpecifier(DeclSpec::TSW W, const char *&PrevSpec) {
43 switch (W) {
44 case DeclSpec::TSW_unspecified: PrevSpec = "unspecified"; break;
45 case DeclSpec::TSW_short: PrevSpec = "short"; break;
46 case DeclSpec::TSW_long: PrevSpec = "long"; break;
47 case DeclSpec::TSW_longlong: PrevSpec = "long long"; break;
48 }
49 return true;
50}
51
52static bool BadSpecifier(DeclSpec::TSC C, const char *&PrevSpec) {
53 switch (C) {
54 case DeclSpec::TSC_unspecified: PrevSpec = "unspecified"; break;
55 case DeclSpec::TSC_imaginary: PrevSpec = "imaginary"; break;
56 case DeclSpec::TSC_complex: PrevSpec = "complex"; break;
57 }
58 return true;
59}
60
61
62static bool BadSpecifier(DeclSpec::TSS S, const char *&PrevSpec) {
63 switch (S) {
64 case DeclSpec::TSS_unspecified: PrevSpec = "unspecified"; break;
65 case DeclSpec::TSS_signed: PrevSpec = "signed"; break;
66 case DeclSpec::TSS_unsigned: PrevSpec = "unsigned"; break;
67 }
68 return true;
69}
70
Chris Lattner839713c2006-08-04 06:15:52 +000071static const char *getSpecifierName(DeclSpec::TST T) {
Chris Lattnerb9093cd2006-08-04 04:39:53 +000072 switch (T) {
Chris Lattner839713c2006-08-04 06:15:52 +000073 default: assert(0 && "Unknown typespec!");
74 case DeclSpec::TST_unspecified: return "unspecified";
75 case DeclSpec::TST_void: return "void";
76 case DeclSpec::TST_char: return "char";
77 case DeclSpec::TST_int: return "int";
78 case DeclSpec::TST_float: return "float";
79 case DeclSpec::TST_double: return "double";
80 case DeclSpec::TST_bool: return "_Bool";
81 case DeclSpec::TST_decimal32: return "_Decimal32";
82 case DeclSpec::TST_decimal64: return "_Decimal64";
83 case DeclSpec::TST_decimal128: return "_Decimal128";
Chris Lattnerb9093cd2006-08-04 04:39:53 +000084 }
Chris Lattner839713c2006-08-04 06:15:52 +000085}
86
87static bool BadSpecifier(DeclSpec::TST T, const char *&PrevSpec) {
88 PrevSpec = getSpecifierName(T);
Chris Lattnerb9093cd2006-08-04 04:39:53 +000089 return true;
90}
91
Chris Lattnerda48a8e2006-08-04 05:25:55 +000092static bool BadSpecifier(DeclSpec::TQ T, const char *&PrevSpec) {
93 switch (T) {
94 case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break;
95 case DeclSpec::TQ_const: PrevSpec = "const"; break;
96 case DeclSpec::TQ_restrict: PrevSpec = "restrict"; break;
97 case DeclSpec::TQ_volatile: PrevSpec = "volatile"; break;
98 }
99 return true;
100}
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000101
102/// These methods set the specified attribute of the DeclSpec, but return true
103/// and ignore the request if invalid (e.g. "extern" then "auto" is
104/// specified).
105bool DeclSpec::SetTypeSpecWidth(TSW W, const char *&PrevSpec) {
106 if (TypeSpecWidth != TSW_unspecified)
107 return BadSpecifier(TypeSpecWidth, PrevSpec);
108 TypeSpecWidth = W;
109 return false;
110}
111
112bool DeclSpec::SetTypeSpecComplex(TSC C, const char *&PrevSpec) {
113 if (TypeSpecComplex != TSC_unspecified)
114 return BadSpecifier(TypeSpecComplex, PrevSpec);
115 TypeSpecComplex = C;
116 return false;
117}
118
119bool DeclSpec::SetTypeSpecSign(TSS S, const char *&PrevSpec) {
120 if (TypeSpecSign != TSS_unspecified)
121 return BadSpecifier(TypeSpecSign, PrevSpec);
Chris Lattnerdeb42f52006-08-04 05:26:52 +0000122 TypeSpecSign = S;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000123 return false;
124}
125
126bool DeclSpec::SetTypeSpecType(TST T, const char *&PrevSpec) {
127 if (TypeSpecType != TST_unspecified)
128 return BadSpecifier(TypeSpecType, PrevSpec);
Chris Lattnerdeb42f52006-08-04 05:26:52 +0000129 TypeSpecType = T;
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000130 return false;
131}
132
Chris Lattnerda48a8e2006-08-04 05:25:55 +0000133bool DeclSpec::SetTypeQual(TQ T, const char *&PrevSpec,
134 const LangOptions &Lang) {
135 // Duplicates turn into warnings pre-C99.
136 if ((TypeQualifiers & T) && !Lang.C99)
137 return BadSpecifier(T, PrevSpec);
138 TypeQualifiers |= T;
139 return false;
140}
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000141
142bool DeclSpec::SetFuncSpec(FS F, const char *&PrevSpec) {
143 // 'inline inline' is ok.
144 FuncSpec = F;
145 return false;
146}
147
148/// Finish - This does final analysis of the declspec, rejecting things like
149/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
150/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
151/// DeclSpec is guaranteed self-consistent, even if an error occurred.
Chris Lattner839713c2006-08-04 06:15:52 +0000152void DeclSpec::Finish(SourceLocation Loc, Diagnostic &D,
153 const LangOptions &Lang) {
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000154 // Check the type specifier components first.
155
156 // signed/unsigned are only valid with int/char.
Chris Lattner839713c2006-08-04 06:15:52 +0000157 if (TypeSpecSign != TSS_unspecified) {
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000158 if (TypeSpecType == TST_unspecified)
159 TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
160 else if (TypeSpecType != TST_int && TypeSpecType != TST_char) {
Chris Lattner839713c2006-08-04 06:15:52 +0000161 D.Report(Loc, diag::err_invalid_sign_spec,getSpecifierName(TypeSpecType));
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000162 // signed double -> double.
Chris Lattner839713c2006-08-04 06:15:52 +0000163 TypeSpecSign = TSS_unspecified;
164 }
165 }
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000166
Chris Lattner839713c2006-08-04 06:15:52 +0000167 // Validate the width of the type.
168 switch (TypeSpecWidth) {
169 case TSW_unspecified: break;
170 case TSW_short: // short int
171 case TSW_longlong: // long long int
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000172 if (TypeSpecType == TST_unspecified)
173 TypeSpecType = TST_int; // short -> short int, long long -> long long int.
174 else if (TypeSpecType != TST_int) {
Chris Lattner839713c2006-08-04 06:15:52 +0000175 D.Report(Loc, TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec :
176 diag::err_invalid_longlong_spec,
177 getSpecifierName(TypeSpecType));
178 TypeSpecType = TST_int;
179 }
180 break;
181 case TSW_long: // long double, long int
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000182 if (TypeSpecType == TST_unspecified)
183 TypeSpecType = TST_int; // long -> long int.
184 else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
Chris Lattner839713c2006-08-04 06:15:52 +0000185 D.Report(Loc, diag::err_invalid_long_spec,
186 getSpecifierName(TypeSpecType));
187 TypeSpecType = TST_int;
188 }
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000189 break;
Chris Lattner839713c2006-08-04 06:15:52 +0000190 }
191
Chris Lattnerfef9d2b2006-08-04 06:36:52 +0000192 // FIXME: if the implementation does not implement _Complex or _Imaginary,
193 // disallow their use. Need information about the backend.
194 if (TypeSpecComplex != TSC_unspecified) {
195 if (TypeSpecType == TST_unspecified) {
196 D.Report(Loc, diag::ext_plain_complex);
197 TypeSpecType = TST_double; // _Complex -> _Complex double.
198 } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
199 // Note that GCC doesn't support _Complex _Bool.
200 D.Report(Loc, diag::ext_integer_complex);
201 } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
202 D.Report(Loc, diag::err_invalid_complex_spec,
203 getSpecifierName(TypeSpecType));
204 TypeSpecComplex = TSC_unspecified;
205 }
206 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000207}