Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 1 | //===--- ParserDeclarations.cpp - Declaration Parsing ---------------------===// |
| 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 portions of the Parser interfaces. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "clang/Parse/Parser.h" |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 15 | #include "clang/Parse/Declarations.h" |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 16 | using namespace llvm; |
| 17 | using namespace clang; |
| 18 | |
| 19 | //===----------------------------------------------------------------------===// |
| 20 | // C99 6.7: Declarations. |
| 21 | //===----------------------------------------------------------------------===// |
| 22 | |
| 23 | /// ParseDeclarationSpecifiers |
| 24 | /// declaration-specifiers: [C99 6.7] |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 25 | /// storage-class-specifier declaration-specifiers [opt] |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 26 | /// type-specifier declaration-specifiers [opt] |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 27 | /// type-qualifier declaration-specifiers [opt] |
| 28 | /// [C99] function-specifier declaration-specifiers [opt] |
| 29 | /// [GNU] attributes declaration-specifiers [opt] [TODO] |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 30 | /// |
Chris Lattner | f63f89a | 2006-08-05 03:28:50 +0000 | [diff] [blame^] | 31 | /// storage-class-specifier: [C99 6.7.1] |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 32 | /// 'typedef' |
| 33 | /// 'extern' |
| 34 | /// 'static' |
| 35 | /// 'auto' |
| 36 | /// 'register' |
| 37 | /// [GNU] '__thread' |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 38 | /// type-specifier: [C99 6.7.2] |
| 39 | /// 'void' |
| 40 | /// 'char' |
| 41 | /// 'short' |
| 42 | /// 'int' |
| 43 | /// 'long' |
| 44 | /// 'float' |
| 45 | /// 'double' |
| 46 | /// 'signed' |
| 47 | /// 'unsigned' |
| 48 | /// [C99] '_Bool' |
| 49 | /// [C99] '_Complex' |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 50 | /// [C99] '_Imaginary' // Removed in TC2? |
| 51 | /// [GNU] '_Decimal32' |
| 52 | /// [GNU] '_Decimal64' |
| 53 | /// [GNU] '_Decimal128' |
Chris Lattner | f63f89a | 2006-08-05 03:28:50 +0000 | [diff] [blame^] | 54 | /// [GNU] typeof-specifier [TODO] |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 55 | /// [OBJC] class-name objc-protocol-refs [opt] [TODO] |
| 56 | /// [OBJC] typedef-name objc-protocol-refs [TODO] |
| 57 | /// [OBJC] objc-protocol-refs [TODO] |
| 58 | /// struct-or-union-specifier [TODO] |
| 59 | /// enum-specifier [TODO] |
| 60 | /// typedef-name [TODO] |
| 61 | /// type-qualifier: |
| 62 | /// const |
| 63 | /// volatile |
| 64 | /// [C99] restrict |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 65 | /// function-specifier: [C99 6.7.4] |
| 66 | /// [C99] inline |
| 67 | /// |
| 68 | void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { |
| 69 | SourceLocation StartLoc = Tok.getLocation(); |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 70 | while (1) { |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 71 | int isInvalid = false; |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 72 | const char *PrevSpec = 0; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 73 | switch (Tok.getKind()) { |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 74 | default: |
| 75 | // If this is not a declaration specifier token, we're done reading decl |
| 76 | // specifiers. First verify that DeclSpec's are consistent. |
Chris Lattner | 839713c | 2006-08-04 06:15:52 +0000 | [diff] [blame] | 77 | DS.Finish(StartLoc, Diags, getLang()); |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 78 | return; |
Chris Lattner | f63f89a | 2006-08-05 03:28:50 +0000 | [diff] [blame^] | 79 | |
| 80 | // storage-class-specifier |
| 81 | case tok::kw_typedef: |
| 82 | isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, PrevSpec); |
| 83 | break; |
| 84 | case tok::kw_extern: |
| 85 | if (DS.SCS_thread_specified) |
| 86 | Diag(Tok, diag::ext_thread_before, "extern"); |
| 87 | isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, PrevSpec); |
| 88 | break; |
| 89 | case tok::kw_static: |
| 90 | if (DS.SCS_thread_specified) |
| 91 | Diag(Tok, diag::ext_thread_before, "static"); |
| 92 | isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, PrevSpec); |
| 93 | break; |
| 94 | case tok::kw_auto: |
| 95 | isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, PrevSpec); |
| 96 | break; |
| 97 | case tok::kw_register: |
| 98 | isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, PrevSpec); |
| 99 | break; |
| 100 | case tok::kw___thread: |
| 101 | if (DS.SCS_thread_specified) |
| 102 | isInvalid = 2, PrevSpec = "__thread"; |
| 103 | else |
| 104 | DS.SCS_thread_specified = true; |
| 105 | break; |
| 106 | |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 107 | // type-specifiers |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 108 | case tok::kw_short: |
| 109 | isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec); |
| 110 | break; |
| 111 | case tok::kw_long: |
| 112 | if (DS.TypeSpecWidth != DeclSpec::TSW_long) { |
| 113 | isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec); |
| 114 | } else { |
| 115 | DS.TypeSpecWidth = DeclSpec::TSW_unspecified; |
| 116 | isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec); |
| 117 | } |
| 118 | break; |
| 119 | case tok::kw_signed: |
| 120 | isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec); |
| 121 | break; |
| 122 | case tok::kw_unsigned: |
| 123 | isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec); |
| 124 | break; |
| 125 | case tok::kw__Complex: |
| 126 | isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec); |
| 127 | break; |
| 128 | case tok::kw__Imaginary: |
| 129 | isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec); |
| 130 | break; |
| 131 | case tok::kw_void: |
| 132 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec); |
| 133 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 134 | case tok::kw_char: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 135 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec); |
| 136 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 137 | case tok::kw_int: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 138 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec); |
| 139 | break; |
| 140 | case tok::kw_float: |
| 141 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec); |
| 142 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 143 | case tok::kw_double: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 144 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec); |
| 145 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 146 | case tok::kw__Bool: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 147 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec); |
| 148 | break; |
| 149 | case tok::kw__Decimal32: |
| 150 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec); |
| 151 | break; |
| 152 | case tok::kw__Decimal64: |
| 153 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec); |
| 154 | break; |
| 155 | case tok::kw__Decimal128: |
| 156 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec); |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 157 | break; |
| 158 | |
| 159 | //case tok::kw_struct: |
| 160 | //case tok::kw_union: |
| 161 | //case tok::kw_enum: |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 162 | |
| 163 | // type-qualifier |
| 164 | case tok::kw_const: |
| 165 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2; |
| 166 | break; |
| 167 | case tok::kw_volatile: |
| 168 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2; |
| 169 | break; |
| 170 | case tok::kw_restrict: |
| 171 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2; |
| 172 | break; |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 173 | |
| 174 | // function-specifier |
| 175 | case tok::kw_inline: |
Chris Lattner | f63f89a | 2006-08-05 03:28:50 +0000 | [diff] [blame^] | 176 | // 'inline inline' is ok. |
| 177 | DS.FS_inline_specified = true; |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 178 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 179 | } |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 180 | // If the specifier combination wasn't legal, issue a diagnostic. |
| 181 | if (isInvalid) { |
| 182 | assert(PrevSpec && "Method did not return previous specifier!"); |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame] | 183 | if (isInvalid == 1) // Error. |
| 184 | Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec); |
| 185 | else // extwarn. |
| 186 | Diag(Tok, diag::ext_duplicate_declspec, PrevSpec); |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 187 | } |
| 188 | ConsumeToken(); |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 189 | } |
| 190 | } |
| 191 | |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 192 | |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 193 | /// ParseDeclarator |
| 194 | /// declarator: [C99 6.7.5] |
| 195 | /// pointer[opt] direct-declarator |
| 196 | /// |
| 197 | /// pointer: [C99 6.7.5] |
| 198 | /// '*' type-qualifier-list[opt] |
| 199 | /// '*' type-qualifier-list[opt] pointer |
| 200 | /// |
| 201 | void Parser::ParseDeclarator() { |
| 202 | while (Tok.getKind() == tok::star) { // '*' -> pointer. |
| 203 | ConsumeToken(); // Eat the *. |
| 204 | ParseTypeQualifierListOpt(); |
| 205 | } |
| 206 | |
| 207 | ParseDirectDeclarator(); |
| 208 | } |
| 209 | |
| 210 | /// ParseTypeQualifierListOpt |
| 211 | /// type-qualifier-list: [C99 6.7.5] |
| 212 | /// type-qualifier |
| 213 | /// [GNU] attributes [TODO] |
| 214 | /// type-qualifier-list type-qualifier |
| 215 | /// [GNU] type-qualifier-list attributes [TODO] |
| 216 | /// |
| 217 | void Parser::ParseTypeQualifierListOpt() { |
| 218 | while (1) { |
| 219 | switch (Tok.getKind()) { |
| 220 | default: break; |
| 221 | // TODO: attributes. |
| 222 | case tok::kw_const: |
| 223 | case tok::kw_volatile: |
| 224 | case tok::kw_restrict: |
| 225 | ConsumeToken(); |
| 226 | break; |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | |
| 232 | /// ParseDirectDeclarator |
| 233 | /// direct-declarator: [C99 6.7.5] |
| 234 | /// identifier |
| 235 | /// '(' declarator ')' |
| 236 | /// [GNU] '(' attributes declarator ')' |
| 237 | /// direct-declarator array-declarator |
| 238 | /// direct-declarator '(' parameter-type-list ')' |
| 239 | /// direct-declarator '(' identifier-list[opt] ')' |
| 240 | /// [GNU] direct-declarator '(' parameter-forward-declarations |
| 241 | /// parameter-type-list[opt] ')' |
| 242 | /// |
| 243 | /// parameter-type-list: [C99 6.7.5] |
| 244 | /// parameter-list |
| 245 | /// parameter-list ',' '...' |
| 246 | /// |
| 247 | /// parameter-list: [C99 6.7.5] |
| 248 | /// parameter-declaration |
| 249 | /// parameter-list ',' parameter-declaration |
| 250 | /// |
| 251 | /// parameter-declaration: [C99 6.7.5] |
| 252 | /// declaration-specifiers declarator |
| 253 | /// [GNU] declaration-specifiers declarator attributes |
| 254 | /// declaration-specifiers abstract-declarator[opt] |
| 255 | /// [GNU] declaration-specifiers abstract-declarator[opt] attributes |
| 256 | /// |
| 257 | /// identifier-list: [C99 6.7.5] |
| 258 | /// identifier |
| 259 | /// identifier-list ',' identifier |
| 260 | /// |
| 261 | void Parser::ParseDirectDeclarator() { |
| 262 | if (Tok.getKind() == tok::identifier) { |
| 263 | ConsumeToken(); |
| 264 | return; |
| 265 | } |
| 266 | // FIXME: missing most stuff. |
| 267 | assert(0 && "Unknown token!"); |
| 268 | } |