blob: d37983bb9fbcb6ecb5dcb52091856ad42ad72e35 [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) {
154 // signed/unsigned are not valid with void,float,double,bool,decimal*.
155 if (TypeSpecSign != TSS_unspecified) {
156 if (TypeSpecType == TST_void || TypeSpecType == TST_float ||
157 TypeSpecType == TST_double || TypeSpecType == TST_bool ||
158 TypeSpecType == TST_decimal32 || TypeSpecType == TST_decimal64 ||
159 TypeSpecType == TST_decimal128) {
160 D.Report(Loc, diag::err_invalid_sign_spec,getSpecifierName(TypeSpecType));
161 TypeSpecSign = TSS_unspecified;
162 }
163 }
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000164
Chris Lattner839713c2006-08-04 06:15:52 +0000165 // Validate the width of the type.
166 switch (TypeSpecWidth) {
167 case TSW_unspecified: break;
168 case TSW_short: // short int
169 case TSW_longlong: // long long int
170 if (TypeSpecType != TST_unspecified && TypeSpecType != TST_int) {
171 D.Report(Loc, TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec :
172 diag::err_invalid_longlong_spec,
173 getSpecifierName(TypeSpecType));
174 TypeSpecType = TST_int;
175 }
176 break;
177 case TSW_long: // long double, long int
178 if (TypeSpecType != TST_unspecified && TypeSpecType != TST_int &&
179 TypeSpecType != TST_double) {
180 D.Report(Loc, diag::err_invalid_long_spec,
181 getSpecifierName(TypeSpecType));
182 TypeSpecType = TST_int;
183 }
184 }
185
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000186}