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 | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame^] | 31 | /// storage-class-specifier: [C99 6.7.1] |
| 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' |
| 54 | /// [OBJC] class-name objc-protocol-refs [opt] [TODO] |
| 55 | /// [OBJC] typedef-name objc-protocol-refs [TODO] |
| 56 | /// [OBJC] objc-protocol-refs [TODO] |
| 57 | /// struct-or-union-specifier [TODO] |
| 58 | /// enum-specifier [TODO] |
| 59 | /// typedef-name [TODO] |
| 60 | /// type-qualifier: |
| 61 | /// const |
| 62 | /// volatile |
| 63 | /// [C99] restrict |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 64 | /// function-specifier: [C99 6.7.4] |
| 65 | /// [C99] inline |
| 66 | /// |
| 67 | void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { |
| 68 | SourceLocation StartLoc = Tok.getLocation(); |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 69 | while (1) { |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame^] | 70 | int isInvalid = false; |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 71 | const char *PrevSpec = 0; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 72 | switch (Tok.getKind()) { |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 73 | default: |
| 74 | // If this is not a declaration specifier token, we're done reading decl |
| 75 | // specifiers. First verify that DeclSpec's are consistent. |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame^] | 76 | diag::kind Res = DS.Finish(getLang()); |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 77 | if (Res != diag::NUM_DIAGNOSTICS) |
| 78 | Diag(StartLoc, Res); |
| 79 | return; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 80 | // type-specifiers |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 81 | case tok::kw_short: |
| 82 | isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec); |
| 83 | break; |
| 84 | case tok::kw_long: |
| 85 | if (DS.TypeSpecWidth != DeclSpec::TSW_long) { |
| 86 | isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec); |
| 87 | } else { |
| 88 | DS.TypeSpecWidth = DeclSpec::TSW_unspecified; |
| 89 | isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec); |
| 90 | } |
| 91 | break; |
| 92 | case tok::kw_signed: |
| 93 | isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec); |
| 94 | break; |
| 95 | case tok::kw_unsigned: |
| 96 | isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec); |
| 97 | break; |
| 98 | case tok::kw__Complex: |
| 99 | isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec); |
| 100 | break; |
| 101 | case tok::kw__Imaginary: |
| 102 | isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec); |
| 103 | break; |
| 104 | case tok::kw_void: |
| 105 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec); |
| 106 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 107 | case tok::kw_char: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 108 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec); |
| 109 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 110 | case tok::kw_int: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 111 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec); |
| 112 | break; |
| 113 | case tok::kw_float: |
| 114 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec); |
| 115 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 116 | case tok::kw_double: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 117 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec); |
| 118 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 119 | case tok::kw__Bool: |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 120 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec); |
| 121 | break; |
| 122 | case tok::kw__Decimal32: |
| 123 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec); |
| 124 | break; |
| 125 | case tok::kw__Decimal64: |
| 126 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec); |
| 127 | break; |
| 128 | case tok::kw__Decimal128: |
| 129 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec); |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 130 | break; |
| 131 | |
| 132 | //case tok::kw_struct: |
| 133 | //case tok::kw_union: |
| 134 | //case tok::kw_enum: |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame^] | 135 | |
| 136 | // type-qualifier |
| 137 | case tok::kw_const: |
| 138 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2; |
| 139 | break; |
| 140 | case tok::kw_volatile: |
| 141 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2; |
| 142 | break; |
| 143 | case tok::kw_restrict: |
| 144 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2; |
| 145 | break; |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 146 | |
| 147 | // function-specifier |
| 148 | case tok::kw_inline: |
| 149 | isInvalid = DS.SetFuncSpec(DeclSpec::FS_inline, PrevSpec); |
| 150 | break; |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 151 | } |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 152 | // If the specifier combination wasn't legal, issue a diagnostic. |
| 153 | if (isInvalid) { |
| 154 | assert(PrevSpec && "Method did not return previous specifier!"); |
Chris Lattner | da48a8e | 2006-08-04 05:25:55 +0000 | [diff] [blame^] | 155 | if (isInvalid == 1) // Error. |
| 156 | Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec); |
| 157 | else // extwarn. |
| 158 | Diag(Tok, diag::ext_duplicate_declspec, PrevSpec); |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 159 | } |
| 160 | ConsumeToken(); |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 161 | } |
| 162 | } |
| 163 | |
Chris Lattner | b9093cd | 2006-08-04 04:39:53 +0000 | [diff] [blame] | 164 | |
Chris Lattner | c0acd3d | 2006-07-31 05:13:43 +0000 | [diff] [blame] | 165 | /// ParseDeclarator |
| 166 | /// declarator: [C99 6.7.5] |
| 167 | /// pointer[opt] direct-declarator |
| 168 | /// |
| 169 | /// pointer: [C99 6.7.5] |
| 170 | /// '*' type-qualifier-list[opt] |
| 171 | /// '*' type-qualifier-list[opt] pointer |
| 172 | /// |
| 173 | void Parser::ParseDeclarator() { |
| 174 | while (Tok.getKind() == tok::star) { // '*' -> pointer. |
| 175 | ConsumeToken(); // Eat the *. |
| 176 | ParseTypeQualifierListOpt(); |
| 177 | } |
| 178 | |
| 179 | ParseDirectDeclarator(); |
| 180 | } |
| 181 | |
| 182 | /// ParseTypeQualifierListOpt |
| 183 | /// type-qualifier-list: [C99 6.7.5] |
| 184 | /// type-qualifier |
| 185 | /// [GNU] attributes [TODO] |
| 186 | /// type-qualifier-list type-qualifier |
| 187 | /// [GNU] type-qualifier-list attributes [TODO] |
| 188 | /// |
| 189 | void Parser::ParseTypeQualifierListOpt() { |
| 190 | while (1) { |
| 191 | switch (Tok.getKind()) { |
| 192 | default: break; |
| 193 | // TODO: attributes. |
| 194 | case tok::kw_const: |
| 195 | case tok::kw_volatile: |
| 196 | case tok::kw_restrict: |
| 197 | ConsumeToken(); |
| 198 | break; |
| 199 | } |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | |
| 204 | /// ParseDirectDeclarator |
| 205 | /// direct-declarator: [C99 6.7.5] |
| 206 | /// identifier |
| 207 | /// '(' declarator ')' |
| 208 | /// [GNU] '(' attributes declarator ')' |
| 209 | /// direct-declarator array-declarator |
| 210 | /// direct-declarator '(' parameter-type-list ')' |
| 211 | /// direct-declarator '(' identifier-list[opt] ')' |
| 212 | /// [GNU] direct-declarator '(' parameter-forward-declarations |
| 213 | /// parameter-type-list[opt] ')' |
| 214 | /// |
| 215 | /// parameter-type-list: [C99 6.7.5] |
| 216 | /// parameter-list |
| 217 | /// parameter-list ',' '...' |
| 218 | /// |
| 219 | /// parameter-list: [C99 6.7.5] |
| 220 | /// parameter-declaration |
| 221 | /// parameter-list ',' parameter-declaration |
| 222 | /// |
| 223 | /// parameter-declaration: [C99 6.7.5] |
| 224 | /// declaration-specifiers declarator |
| 225 | /// [GNU] declaration-specifiers declarator attributes |
| 226 | /// declaration-specifiers abstract-declarator[opt] |
| 227 | /// [GNU] declaration-specifiers abstract-declarator[opt] attributes |
| 228 | /// |
| 229 | /// identifier-list: [C99 6.7.5] |
| 230 | /// identifier |
| 231 | /// identifier-list ',' identifier |
| 232 | /// |
| 233 | void Parser::ParseDirectDeclarator() { |
| 234 | if (Tok.getKind() == tok::identifier) { |
| 235 | ConsumeToken(); |
| 236 | return; |
| 237 | } |
| 238 | // FIXME: missing most stuff. |
| 239 | assert(0 && "Unknown token!"); |
| 240 | } |