| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This file implements the Expression parsing implementation for C++. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| Chris Lattner | 500d329 | 2009-01-29 05:15:15 +0000 | [diff] [blame] | 14 | #include "clang/Parse/ParseDiagnostic.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 15 | #include "clang/Parse/Parser.h" | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 16 | #include "clang/Parse/DeclSpec.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 17 | using namespace clang; | 
 | 18 |  | 
| Chris Lattner | 7a0ab5f | 2009-01-06 06:59:53 +0000 | [diff] [blame] | 19 | /// ParseOptionalCXXScopeSpecifier - Parse global scope or | 
 | 20 | /// nested-name-specifier if present.  Returns true if a nested-name-specifier | 
 | 21 | /// was parsed from the token stream.  Note that this routine will not parse | 
 | 22 | /// ::new or ::delete, it will just leave them in the token stream. | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 23 | /// | 
 | 24 | ///       '::'[opt] nested-name-specifier | 
 | 25 | ///       '::' | 
 | 26 | /// | 
 | 27 | ///       nested-name-specifier: | 
 | 28 | ///         type-name '::' | 
 | 29 | ///         namespace-name '::' | 
 | 30 | ///         nested-name-specifier identifier '::' | 
 | 31 | ///         nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] | 
 | 32 | /// | 
| Chris Lattner | 7a0ab5f | 2009-01-06 06:59:53 +0000 | [diff] [blame] | 33 | bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { | 
| Argyrios Kyrtzidis | 4bdd91c | 2008-11-26 21:41:52 +0000 | [diff] [blame] | 34 |   assert(getLang().CPlusPlus && | 
| Chris Lattner | 7452c6f | 2009-01-05 01:24:05 +0000 | [diff] [blame] | 35 |          "Call sites of this function should be guarded by checking for C++"); | 
| Argyrios Kyrtzidis | 4bdd91c | 2008-11-26 21:41:52 +0000 | [diff] [blame] | 36 |  | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 37 |   if (Tok.is(tok::annot_cxxscope)) { | 
| Douglas Gregor | 3507369 | 2009-03-26 23:56:24 +0000 | [diff] [blame] | 38 |     SS.setScopeRep(Tok.getAnnotationValue()); | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 39 |     SS.setRange(Tok.getAnnotationRange()); | 
 | 40 |     ConsumeToken(); | 
| Argyrios Kyrtzidis | 4bdd91c | 2008-11-26 21:41:52 +0000 | [diff] [blame] | 41 |     return true; | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 42 |   } | 
| Chris Lattner | e607e80 | 2009-01-04 21:14:15 +0000 | [diff] [blame] | 43 |  | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 44 |   bool HasScopeSpecifier = false; | 
 | 45 |  | 
| Chris Lattner | 5b45473 | 2009-01-05 03:55:46 +0000 | [diff] [blame] | 46 |   if (Tok.is(tok::coloncolon)) { | 
 | 47 |     // ::new and ::delete aren't nested-name-specifiers. | 
 | 48 |     tok::TokenKind NextKind = NextToken().getKind(); | 
 | 49 |     if (NextKind == tok::kw_new || NextKind == tok::kw_delete) | 
 | 50 |       return false; | 
| Chris Lattner | 55a7cef | 2009-01-05 00:13:00 +0000 | [diff] [blame] | 51 |      | 
| Chris Lattner | 55a7cef | 2009-01-05 00:13:00 +0000 | [diff] [blame] | 52 |     // '::' - Global scope qualifier. | 
| Chris Lattner | 357089d | 2009-01-05 02:07:19 +0000 | [diff] [blame] | 53 |     SourceLocation CCLoc = ConsumeToken(); | 
| Chris Lattner | 357089d | 2009-01-05 02:07:19 +0000 | [diff] [blame] | 54 |     SS.setBeginLoc(CCLoc); | 
| Douglas Gregor | 3507369 | 2009-03-26 23:56:24 +0000 | [diff] [blame] | 55 |     SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc)); | 
| Chris Lattner | 357089d | 2009-01-05 02:07:19 +0000 | [diff] [blame] | 56 |     SS.setEndLoc(CCLoc); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 57 |     HasScopeSpecifier = true; | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 58 |   } | 
 | 59 |  | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 60 |   while (true) { | 
 | 61 |     // nested-name-specifier: | 
| Chris Lattner | 77cf72a | 2009-06-26 03:47:46 +0000 | [diff] [blame] | 62 |     //   nested-name-specifier 'template'[opt] simple-template-id '::' | 
 | 63 |  | 
 | 64 |     // Parse the optional 'template' keyword, then make sure we have | 
 | 65 |     // 'identifier <' after it. | 
 | 66 |     if (Tok.is(tok::kw_template)) { | 
 | 67 |       SourceLocation TemplateKWLoc = ConsumeToken(); | 
 | 68 |        | 
 | 69 |       if (Tok.isNot(tok::identifier)) { | 
 | 70 |         Diag(Tok.getLocation(),  | 
 | 71 |              diag::err_id_after_template_in_nested_name_spec) | 
 | 72 |           << SourceRange(TemplateKWLoc); | 
 | 73 |         break; | 
 | 74 |       } | 
 | 75 |        | 
 | 76 |       if (NextToken().isNot(tok::less)) { | 
 | 77 |         Diag(NextToken().getLocation(), | 
 | 78 |              diag::err_less_after_template_name_in_nested_name_spec) | 
 | 79 |           << Tok.getIdentifierInfo()->getName() | 
 | 80 |           << SourceRange(TemplateKWLoc, Tok.getLocation()); | 
 | 81 |         break; | 
 | 82 |       } | 
 | 83 |        | 
 | 84 |       TemplateTy Template  | 
 | 85 |         = Actions.ActOnDependentTemplateName(TemplateKWLoc, | 
 | 86 |                                              *Tok.getIdentifierInfo(), | 
 | 87 |                                              Tok.getLocation(), SS); | 
| Chris Lattner | c8e27cc | 2009-06-26 04:27:47 +0000 | [diff] [blame] | 88 |       if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, | 
 | 89 |                                   &SS, TemplateKWLoc, false)) | 
 | 90 |         break; | 
 | 91 |        | 
| Chris Lattner | 77cf72a | 2009-06-26 03:47:46 +0000 | [diff] [blame] | 92 |       continue; | 
 | 93 |     } | 
 | 94 |      | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 95 |     if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { | 
 | 96 |       // We have  | 
 | 97 |       // | 
 | 98 |       //   simple-template-id '::' | 
 | 99 |       // | 
 | 100 |       // So we need to check whether the simple-template-id is of the | 
| Douglas Gregor | c45c232 | 2009-03-31 00:43:58 +0000 | [diff] [blame] | 101 |       // right kind (it should name a type or be dependent), and then | 
 | 102 |       // convert it into a type within the nested-name-specifier. | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 103 |       TemplateIdAnnotation *TemplateId  | 
 | 104 |         = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); | 
 | 105 |  | 
| Douglas Gregor | c45c232 | 2009-03-31 00:43:58 +0000 | [diff] [blame] | 106 |       if (TemplateId->Kind == TNK_Type_template ||  | 
 | 107 |           TemplateId->Kind == TNK_Dependent_template_name) { | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 108 |         AnnotateTemplateIdTokenAsType(&SS); | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 109 |         SS.setScopeRep(0); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 110 |  | 
 | 111 |         assert(Tok.is(tok::annot_typename) &&  | 
 | 112 |                "AnnotateTemplateIdTokenAsType isn't working"); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 113 |         Token TypeToken = Tok; | 
 | 114 |         ConsumeToken(); | 
 | 115 |         assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); | 
 | 116 |         SourceLocation CCLoc = ConsumeToken(); | 
 | 117 |          | 
 | 118 |         if (!HasScopeSpecifier) { | 
 | 119 |           SS.setBeginLoc(TypeToken.getLocation()); | 
 | 120 |           HasScopeSpecifier = true; | 
 | 121 |         } | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 122 |          | 
 | 123 |         if (TypeToken.getAnnotationValue()) | 
 | 124 |           SS.setScopeRep( | 
 | 125 |             Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,  | 
 | 126 |                                                 TypeToken.getAnnotationValue(), | 
 | 127 |                                                 TypeToken.getAnnotationRange(), | 
 | 128 |                                                 CCLoc)); | 
 | 129 |         else | 
 | 130 |           SS.setScopeRep(0); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 131 |         SS.setEndLoc(CCLoc); | 
 | 132 |         continue; | 
| Chris Lattner | 67b9e83 | 2009-06-26 03:45:46 +0000 | [diff] [blame] | 133 |       } | 
 | 134 |        | 
 | 135 |       assert(false && "FIXME: Only type template names supported here"); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 136 |     } | 
 | 137 |  | 
| Chris Lattner | 5c7f786 | 2009-06-26 03:52:38 +0000 | [diff] [blame] | 138 |  | 
 | 139 |     // The rest of the nested-name-specifier possibilities start with | 
 | 140 |     // tok::identifier. | 
 | 141 |     if (Tok.isNot(tok::identifier)) | 
 | 142 |       break; | 
 | 143 |  | 
 | 144 |     IdentifierInfo &II = *Tok.getIdentifierInfo(); | 
 | 145 |  | 
 | 146 |     // nested-name-specifier: | 
 | 147 |     //   type-name '::' | 
 | 148 |     //   namespace-name '::' | 
 | 149 |     //   nested-name-specifier identifier '::' | 
 | 150 |     Token Next = NextToken(); | 
 | 151 |     if (Next.is(tok::coloncolon)) { | 
 | 152 |       // We have an identifier followed by a '::'. Lookup this name | 
 | 153 |       // as the name in a nested-name-specifier. | 
 | 154 |       SourceLocation IdLoc = ConsumeToken(); | 
 | 155 |       assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); | 
 | 156 |       SourceLocation CCLoc = ConsumeToken(); | 
 | 157 |        | 
 | 158 |       if (!HasScopeSpecifier) { | 
 | 159 |         SS.setBeginLoc(IdLoc); | 
 | 160 |         HasScopeSpecifier = true; | 
 | 161 |       } | 
 | 162 |        | 
 | 163 |       if (SS.isInvalid()) | 
 | 164 |         continue; | 
 | 165 |        | 
 | 166 |       SS.setScopeRep( | 
 | 167 |         Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II)); | 
 | 168 |       SS.setEndLoc(CCLoc); | 
 | 169 |       continue; | 
 | 170 |     } | 
 | 171 |      | 
 | 172 |     // nested-name-specifier: | 
 | 173 |     //   type-name '<' | 
 | 174 |     if (Next.is(tok::less)) { | 
 | 175 |       TemplateTy Template; | 
 | 176 |       if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope, | 
 | 177 |                                                         Template, &SS)) { | 
 | 178 |         // We have found a template name, so annotate this this token | 
 | 179 |         // with a template-id annotation. We do not permit the | 
 | 180 |         // template-id to be translated into a type annotation, | 
 | 181 |         // because some clients (e.g., the parsing of class template | 
 | 182 |         // specializations) still want to see the original template-id | 
 | 183 |         // token. | 
| Chris Lattner | c8e27cc | 2009-06-26 04:27:47 +0000 | [diff] [blame] | 184 |         if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), | 
 | 185 |                                     false)) | 
 | 186 |           break; | 
| Chris Lattner | 5c7f786 | 2009-06-26 03:52:38 +0000 | [diff] [blame] | 187 |         continue; | 
 | 188 |       } | 
 | 189 |     } | 
 | 190 |  | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 191 |     // We don't have any tokens that form the beginning of a | 
 | 192 |     // nested-name-specifier, so we're done. | 
 | 193 |     break; | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 194 |   } | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 195 |      | 
 | 196 |   return HasScopeSpecifier; | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 197 | } | 
 | 198 |  | 
 | 199 | /// ParseCXXIdExpression - Handle id-expression. | 
 | 200 | /// | 
 | 201 | ///       id-expression: | 
 | 202 | ///         unqualified-id | 
 | 203 | ///         qualified-id | 
 | 204 | /// | 
 | 205 | ///       unqualified-id: | 
 | 206 | ///         identifier | 
 | 207 | ///         operator-function-id | 
 | 208 | ///         conversion-function-id                [TODO] | 
 | 209 | ///         '~' class-name                        [TODO] | 
| Douglas Gregor | edce4dd | 2009-06-30 22:34:41 +0000 | [diff] [blame] | 210 | ///         template-id | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 211 | /// | 
 | 212 | ///       qualified-id: | 
 | 213 | ///         '::'[opt] nested-name-specifier 'template'[opt] unqualified-id | 
 | 214 | ///         '::' identifier | 
 | 215 | ///         '::' operator-function-id | 
| Douglas Gregor | edce4dd | 2009-06-30 22:34:41 +0000 | [diff] [blame] | 216 | ///         '::' template-id | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 217 | /// | 
 | 218 | ///       nested-name-specifier: | 
 | 219 | ///         type-name '::' | 
 | 220 | ///         namespace-name '::' | 
 | 221 | ///         nested-name-specifier identifier '::' | 
 | 222 | ///         nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] | 
 | 223 | /// | 
 | 224 | /// NOTE: The standard specifies that, for qualified-id, the parser does not | 
 | 225 | /// expect: | 
 | 226 | /// | 
 | 227 | ///   '::' conversion-function-id | 
 | 228 | ///   '::' '~' class-name | 
 | 229 | /// | 
 | 230 | /// This may cause a slight inconsistency on diagnostics: | 
 | 231 | /// | 
 | 232 | /// class C {}; | 
 | 233 | /// namespace A {} | 
 | 234 | /// void f() { | 
 | 235 | ///   :: A :: ~ C(); // Some Sema error about using destructor with a | 
 | 236 | ///                  // namespace. | 
 | 237 | ///   :: ~ C(); // Some Parser error like 'unexpected ~'. | 
 | 238 | /// } | 
 | 239 | /// | 
 | 240 | /// We simplify the parser a bit and make it work like: | 
 | 241 | /// | 
 | 242 | ///       qualified-id: | 
 | 243 | ///         '::'[opt] nested-name-specifier 'template'[opt] unqualified-id | 
 | 244 | ///         '::' unqualified-id | 
 | 245 | /// | 
 | 246 | /// That way Sema can handle and report similar errors for namespaces and the | 
 | 247 | /// global scope. | 
 | 248 | /// | 
| Sebastian Redl | ebc07d5 | 2009-02-03 20:19:35 +0000 | [diff] [blame] | 249 | /// The isAddressOfOperand parameter indicates that this id-expression is a | 
 | 250 | /// direct operand of the address-of operator. This is, besides member contexts, | 
 | 251 | /// the only place where a qualified-id naming a non-static class member may | 
 | 252 | /// appear. | 
 | 253 | /// | 
 | 254 | Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 255 |   // qualified-id: | 
 | 256 |   //   '::'[opt] nested-name-specifier 'template'[opt] unqualified-id | 
 | 257 |   //   '::' unqualified-id | 
 | 258 |   // | 
 | 259 |   CXXScopeSpec SS; | 
| Chris Lattner | 7a0ab5f | 2009-01-06 06:59:53 +0000 | [diff] [blame] | 260 |   ParseOptionalCXXScopeSpecifier(SS); | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 261 |  | 
 | 262 |   // unqualified-id: | 
 | 263 |   //   identifier | 
 | 264 |   //   operator-function-id | 
| Douglas Gregor | 2def483 | 2008-11-17 20:34:05 +0000 | [diff] [blame] | 265 |   //   conversion-function-id | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 266 |   //   '~' class-name                        [TODO] | 
| Douglas Gregor | edce4dd | 2009-06-30 22:34:41 +0000 | [diff] [blame] | 267 |   //   template-id | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 268 |   // | 
 | 269 |   switch (Tok.getKind()) { | 
 | 270 |   default: | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 271 |     return ExprError(Diag(Tok, diag::err_expected_unqualified_id)); | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 272 |  | 
 | 273 |   case tok::identifier: { | 
 | 274 |     // Consume the identifier so that we can see if it is followed by a '('. | 
 | 275 |     IdentifierInfo &II = *Tok.getIdentifierInfo(); | 
 | 276 |     SourceLocation L = ConsumeToken(); | 
| Sebastian Redl | ebc07d5 | 2009-02-03 20:19:35 +0000 | [diff] [blame] | 277 |     return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren), | 
 | 278 |                                        &SS, isAddressOfOperand); | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 279 |   } | 
 | 280 |  | 
 | 281 |   case tok::kw_operator: { | 
 | 282 |     SourceLocation OperatorLoc = Tok.getLocation(); | 
| Chris Lattner | 7452c6f | 2009-01-05 01:24:05 +0000 | [diff] [blame] | 283 |     if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) | 
| Sebastian Redl | cd965b9 | 2009-01-18 18:53:16 +0000 | [diff] [blame] | 284 |       return Actions.ActOnCXXOperatorFunctionIdExpr( | 
| Sebastian Redl | ebc07d5 | 2009-02-03 20:19:35 +0000 | [diff] [blame] | 285 |                        CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS, | 
 | 286 |                        isAddressOfOperand); | 
| Chris Lattner | 7452c6f | 2009-01-05 01:24:05 +0000 | [diff] [blame] | 287 |     if (TypeTy *Type = ParseConversionFunctionId()) | 
| Sebastian Redl | cd965b9 | 2009-01-18 18:53:16 +0000 | [diff] [blame] | 288 |       return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type, | 
| Sebastian Redl | ebc07d5 | 2009-02-03 20:19:35 +0000 | [diff] [blame] | 289 |                                                     Tok.is(tok::l_paren), SS, | 
 | 290 |                                                     isAddressOfOperand); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 291 |  | 
| Douglas Gregor | 2def483 | 2008-11-17 20:34:05 +0000 | [diff] [blame] | 292 |     // We already complained about a bad conversion-function-id, | 
 | 293 |     // above. | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 294 |     return ExprError(); | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 295 |   } | 
 | 296 |  | 
| Douglas Gregor | edce4dd | 2009-06-30 22:34:41 +0000 | [diff] [blame] | 297 |   case tok::annot_template_id: { | 
 | 298 |     TemplateIdAnnotation *TemplateId  | 
 | 299 |       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); | 
 | 300 |     assert((TemplateId->Kind == TNK_Function_template || | 
 | 301 |             TemplateId->Kind == TNK_Dependent_template_name) && | 
 | 302 |            "A template type name is not an ID expression"); | 
 | 303 |  | 
 | 304 |     ASTTemplateArgsPtr TemplateArgsPtr(Actions,  | 
 | 305 |                                        TemplateId->getTemplateArgs(), | 
 | 306 |                                        TemplateId->getTemplateArgIsType(), | 
 | 307 |                                        TemplateId->NumArgs); | 
 | 308 |      | 
 | 309 |     OwningExprResult Result | 
 | 310 |       = Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template), | 
 | 311 |                                     TemplateId->TemplateNameLoc, | 
 | 312 |                                     TemplateId->LAngleLoc, | 
 | 313 |                                     TemplateArgsPtr, | 
 | 314 |                                     TemplateId->getTemplateArgLocations(), | 
 | 315 |                                     TemplateId->RAngleLoc); | 
 | 316 |     ConsumeToken(); // Consume the template-id token | 
 | 317 |     return move(Result); | 
 | 318 |   } | 
 | 319 |  | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 320 |   } // switch. | 
 | 321 |  | 
 | 322 |   assert(0 && "The switch was supposed to take care everything."); | 
 | 323 | } | 
 | 324 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 325 | /// ParseCXXCasts - This handles the various ways to cast expressions to another | 
 | 326 | /// type. | 
 | 327 | /// | 
 | 328 | ///       postfix-expression: [C++ 5.2p1] | 
 | 329 | ///         'dynamic_cast' '<' type-name '>' '(' expression ')' | 
 | 330 | ///         'static_cast' '<' type-name '>' '(' expression ')' | 
 | 331 | ///         'reinterpret_cast' '<' type-name '>' '(' expression ')' | 
 | 332 | ///         'const_cast' '<' type-name '>' '(' expression ')' | 
 | 333 | /// | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 334 | Parser::OwningExprResult Parser::ParseCXXCasts() { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 335 |   tok::TokenKind Kind = Tok.getKind(); | 
 | 336 |   const char *CastName = 0;     // For error messages | 
 | 337 |  | 
 | 338 |   switch (Kind) { | 
 | 339 |   default: assert(0 && "Unknown C++ cast!"); abort(); | 
 | 340 |   case tok::kw_const_cast:       CastName = "const_cast";       break; | 
 | 341 |   case tok::kw_dynamic_cast:     CastName = "dynamic_cast";     break; | 
 | 342 |   case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; | 
 | 343 |   case tok::kw_static_cast:      CastName = "static_cast";      break; | 
 | 344 |   } | 
 | 345 |  | 
 | 346 |   SourceLocation OpLoc = ConsumeToken(); | 
 | 347 |   SourceLocation LAngleBracketLoc = Tok.getLocation(); | 
 | 348 |  | 
 | 349 |   if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 350 |     return ExprError(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 351 |  | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 352 |   TypeResult CastTy = ParseTypeName(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 353 |   SourceLocation RAngleBracketLoc = Tok.getLocation(); | 
 | 354 |  | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 355 |   if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 356 |     return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 357 |  | 
 | 358 |   SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; | 
 | 359 |  | 
| Argyrios Kyrtzidis | 21e7ad2 | 2009-05-22 10:23:16 +0000 | [diff] [blame] | 360 |   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName)) | 
 | 361 |     return ExprError(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 362 |  | 
| Argyrios Kyrtzidis | 21e7ad2 | 2009-05-22 10:23:16 +0000 | [diff] [blame] | 363 |   OwningExprResult Result = ParseExpression(); | 
 | 364 |    | 
 | 365 |   // Match the ')'. | 
 | 366 |   if (Result.isInvalid()) | 
 | 367 |     SkipUntil(tok::r_paren); | 
 | 368 |    | 
 | 369 |   if (Tok.is(tok::r_paren)) | 
 | 370 |     RParenLoc = ConsumeParen(); | 
 | 371 |   else | 
 | 372 |     MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 373 |  | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 374 |   if (!Result.isInvalid() && !CastTy.isInvalid()) | 
| Douglas Gregor | 49badde | 2008-10-27 19:41:14 +0000 | [diff] [blame] | 375 |     Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 376 |                                        LAngleBracketLoc, CastTy.get(), | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 377 |                                        RAngleBracketLoc, | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 378 |                                        LParenLoc, move(Result), RParenLoc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 379 |  | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 380 |   return move(Result); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 381 | } | 
 | 382 |  | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 383 | /// ParseCXXTypeid - This handles the C++ typeid expression. | 
 | 384 | /// | 
 | 385 | ///       postfix-expression: [C++ 5.2p1] | 
 | 386 | ///         'typeid' '(' expression ')' | 
 | 387 | ///         'typeid' '(' type-id ')' | 
 | 388 | /// | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 389 | Parser::OwningExprResult Parser::ParseCXXTypeid() { | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 390 |   assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); | 
 | 391 |  | 
 | 392 |   SourceLocation OpLoc = ConsumeToken(); | 
 | 393 |   SourceLocation LParenLoc = Tok.getLocation(); | 
 | 394 |   SourceLocation RParenLoc; | 
 | 395 |  | 
 | 396 |   // typeid expressions are always parenthesized. | 
 | 397 |   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, | 
 | 398 |       "typeid")) | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 399 |     return ExprError(); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 400 |  | 
| Sebastian Redl | 15faa7f | 2008-12-09 20:22:58 +0000 | [diff] [blame] | 401 |   OwningExprResult Result(Actions); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 402 |  | 
 | 403 |   if (isTypeIdInParens()) { | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 404 |     TypeResult Ty = ParseTypeName(); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 405 |  | 
 | 406 |     // Match the ')'. | 
 | 407 |     MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
 | 408 |  | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 409 |     if (Ty.isInvalid()) | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 410 |       return ExprError(); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 411 |  | 
 | 412 |     Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 413 |                                     Ty.get(), RParenLoc); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 414 |   } else { | 
| Douglas Gregor | e0762c9 | 2009-06-19 23:52:42 +0000 | [diff] [blame] | 415 |     // C++0x [expr.typeid]p3: | 
 | 416 |     //   When typeid is applied to an expression other than an lvalue of a  | 
 | 417 |     //   polymorphic class type [...] The expression is an unevaluated  | 
 | 418 |     //   operand (Clause 5). | 
 | 419 |     // | 
 | 420 |     // Note that we can't tell whether the expression is an lvalue of a  | 
 | 421 |     // polymorphic class type until after we've parsed the expression, so | 
| Douglas Gregor | ac7610d | 2009-06-22 20:57:11 +0000 | [diff] [blame] | 422 |     // we the expression is potentially potentially evaluated. | 
 | 423 |     EnterExpressionEvaluationContext Unevaluated(Actions, | 
 | 424 |                                        Action::PotentiallyPotentiallyEvaluated); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 425 |     Result = ParseExpression(); | 
 | 426 |  | 
 | 427 |     // Match the ')'. | 
| Sebastian Redl | 0e9eabc | 2008-12-09 13:15:23 +0000 | [diff] [blame] | 428 |     if (Result.isInvalid()) | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 429 |       SkipUntil(tok::r_paren); | 
 | 430 |     else { | 
 | 431 |       MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
 | 432 |  | 
 | 433 |       Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, | 
| Sebastian Redl | effa8d1 | 2008-12-10 00:02:53 +0000 | [diff] [blame] | 434 |                                       Result.release(), RParenLoc); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 435 |     } | 
 | 436 |   } | 
 | 437 |  | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 438 |   return move(Result); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 439 | } | 
 | 440 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 441 | /// ParseCXXBoolLiteral - This handles the C++ Boolean literals. | 
 | 442 | /// | 
 | 443 | ///       boolean-literal: [C++ 2.13.5] | 
 | 444 | ///         'true' | 
 | 445 | ///         'false' | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 446 | Parser::OwningExprResult Parser::ParseCXXBoolLiteral() { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 447 |   tok::TokenKind Kind = Tok.getKind(); | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 448 |   return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 449 | } | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 450 |  | 
 | 451 | /// ParseThrowExpression - This handles the C++ throw expression. | 
 | 452 | /// | 
 | 453 | ///       throw-expression: [C++ 15] | 
 | 454 | ///         'throw' assignment-expression[opt] | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 455 | Parser::OwningExprResult Parser::ParseThrowExpression() { | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 456 |   assert(Tok.is(tok::kw_throw) && "Not throw!"); | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 457 |   SourceLocation ThrowLoc = ConsumeToken();           // Eat the throw token. | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 458 |  | 
| Chris Lattner | 2a2819a | 2008-04-06 06:02:23 +0000 | [diff] [blame] | 459 |   // If the current token isn't the start of an assignment-expression, | 
 | 460 |   // then the expression is not present.  This handles things like: | 
 | 461 |   //   "C ? throw : (void)42", which is crazy but legal. | 
 | 462 |   switch (Tok.getKind()) {  // FIXME: move this predicate somewhere common. | 
 | 463 |   case tok::semi: | 
 | 464 |   case tok::r_paren: | 
 | 465 |   case tok::r_square: | 
 | 466 |   case tok::r_brace: | 
 | 467 |   case tok::colon: | 
 | 468 |   case tok::comma: | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 469 |     return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions)); | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 470 |  | 
| Chris Lattner | 2a2819a | 2008-04-06 06:02:23 +0000 | [diff] [blame] | 471 |   default: | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 472 |     OwningExprResult Expr(ParseAssignmentExpression()); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 473 |     if (Expr.isInvalid()) return move(Expr); | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 474 |     return Actions.ActOnCXXThrow(ThrowLoc, move(Expr)); | 
| Chris Lattner | 2a2819a | 2008-04-06 06:02:23 +0000 | [diff] [blame] | 475 |   } | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 476 | } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 477 |  | 
 | 478 | /// ParseCXXThis - This handles the C++ 'this' pointer. | 
 | 479 | /// | 
 | 480 | /// C++ 9.3.2: In the body of a non-static member function, the keyword this is | 
 | 481 | /// a non-lvalue expression whose value is the address of the object for which | 
 | 482 | /// the function is called. | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 483 | Parser::OwningExprResult Parser::ParseCXXThis() { | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 484 |   assert(Tok.is(tok::kw_this) && "Not 'this'!"); | 
 | 485 |   SourceLocation ThisLoc = ConsumeToken(); | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 486 |   return Actions.ActOnCXXThis(ThisLoc); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 487 | } | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 488 |  | 
 | 489 | /// ParseCXXTypeConstructExpression - Parse construction of a specified type. | 
 | 490 | /// Can be interpreted either as function-style casting ("int(x)") | 
 | 491 | /// or class type construction ("ClassType(x,y,z)") | 
 | 492 | /// or creation of a value-initialized type ("int()"). | 
 | 493 | /// | 
 | 494 | ///       postfix-expression: [C++ 5.2p1] | 
 | 495 | ///         simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3] | 
 | 496 | ///         typename-specifier '(' expression-list[opt] ')'         [TODO] | 
 | 497 | /// | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 498 | Parser::OwningExprResult | 
 | 499 | Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 500 |   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); | 
| Douglas Gregor | 5ac8aff | 2009-01-26 22:44:13 +0000 | [diff] [blame] | 501 |   TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get(); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 502 |  | 
 | 503 |   assert(Tok.is(tok::l_paren) && "Expected '('!"); | 
 | 504 |   SourceLocation LParenLoc = ConsumeParen(); | 
 | 505 |  | 
| Sebastian Redl | a55e52c | 2008-11-25 22:21:31 +0000 | [diff] [blame] | 506 |   ExprVector Exprs(Actions); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 507 |   CommaLocsTy CommaLocs; | 
 | 508 |  | 
 | 509 |   if (Tok.isNot(tok::r_paren)) { | 
 | 510 |     if (ParseExpressionList(Exprs, CommaLocs)) { | 
 | 511 |       SkipUntil(tok::r_paren); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 512 |       return ExprError(); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 513 |     } | 
 | 514 |   } | 
 | 515 |  | 
 | 516 |   // Match the ')'. | 
 | 517 |   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
 | 518 |  | 
| Sebastian Redl | ef0cb8e | 2009-07-29 13:50:23 +0000 | [diff] [blame] | 519 |   // TypeRep could be null, if it references an invalid typedef. | 
 | 520 |   if (!TypeRep) | 
 | 521 |     return ExprError(); | 
 | 522 |  | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 523 |   assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& | 
 | 524 |          "Unexpected number of commas!"); | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 525 |   return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, | 
 | 526 |                                            LParenLoc, move_arg(Exprs), | 
| Jay Foad | beaaccd | 2009-05-21 09:52:38 +0000 | [diff] [blame] | 527 |                                            CommaLocs.data(), RParenLoc); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 528 | } | 
 | 529 |  | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 530 | /// ParseCXXCondition - if/switch/while/for condition expression. | 
 | 531 | /// | 
 | 532 | ///       condition: | 
 | 533 | ///         expression | 
 | 534 | ///         type-specifier-seq declarator '=' assignment-expression | 
 | 535 | /// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] | 
 | 536 | ///             '=' assignment-expression | 
 | 537 | /// | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 538 | Parser::OwningExprResult Parser::ParseCXXCondition() { | 
| Argyrios Kyrtzidis | a8a4598 | 2008-10-05 15:03:47 +0000 | [diff] [blame] | 539 |   if (!isCXXConditionDeclaration()) | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 540 |     return ParseExpression(); // expression | 
 | 541 |  | 
 | 542 |   SourceLocation StartLoc = Tok.getLocation(); | 
 | 543 |  | 
 | 544 |   // type-specifier-seq | 
 | 545 |   DeclSpec DS; | 
 | 546 |   ParseSpecifierQualifierList(DS); | 
 | 547 |  | 
 | 548 |   // declarator | 
 | 549 |   Declarator DeclaratorInfo(DS, Declarator::ConditionContext); | 
 | 550 |   ParseDeclarator(DeclaratorInfo); | 
 | 551 |  | 
 | 552 |   // simple-asm-expr[opt] | 
 | 553 |   if (Tok.is(tok::kw_asm)) { | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 554 |     SourceLocation Loc; | 
 | 555 |     OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); | 
| Sebastian Redl | 0e9eabc | 2008-12-09 13:15:23 +0000 | [diff] [blame] | 556 |     if (AsmLabel.isInvalid()) { | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 557 |       SkipUntil(tok::semi); | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 558 |       return ExprError(); | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 559 |     } | 
| Sebastian Redl | effa8d1 | 2008-12-10 00:02:53 +0000 | [diff] [blame] | 560 |     DeclaratorInfo.setAsmLabel(AsmLabel.release()); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 561 |     DeclaratorInfo.SetRangeEnd(Loc); | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 562 |   } | 
 | 563 |  | 
 | 564 |   // If attributes are present, parse them. | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 565 |   if (Tok.is(tok::kw___attribute)) { | 
 | 566 |     SourceLocation Loc; | 
 | 567 |     AttributeList *AttrList = ParseAttributes(&Loc); | 
 | 568 |     DeclaratorInfo.AddAttributes(AttrList, Loc); | 
 | 569 |   } | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 570 |  | 
 | 571 |   // '=' assignment-expression | 
 | 572 |   if (Tok.isNot(tok::equal)) | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 573 |     return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator)); | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 574 |   SourceLocation EqualLoc = ConsumeToken(); | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 575 |   OwningExprResult AssignExpr(ParseAssignmentExpression()); | 
| Sebastian Redl | 0e9eabc | 2008-12-09 13:15:23 +0000 | [diff] [blame] | 576 |   if (AssignExpr.isInvalid()) | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 577 |     return ExprError(); | 
 | 578 |  | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 579 |   return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, | 
 | 580 |                                                   DeclaratorInfo,EqualLoc, | 
 | 581 |                                                   move(AssignExpr)); | 
| Argyrios Kyrtzidis | 71b914b | 2008-09-09 20:38:47 +0000 | [diff] [blame] | 582 | } | 
 | 583 |  | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 584 | /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. | 
 | 585 | /// This should only be called when the current token is known to be part of | 
 | 586 | /// simple-type-specifier. | 
 | 587 | /// | 
 | 588 | ///       simple-type-specifier: | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 589 | ///         '::'[opt] nested-name-specifier[opt] type-name | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 590 | ///         '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] | 
 | 591 | ///         char | 
 | 592 | ///         wchar_t | 
 | 593 | ///         bool | 
 | 594 | ///         short | 
 | 595 | ///         int | 
 | 596 | ///         long | 
 | 597 | ///         signed | 
 | 598 | ///         unsigned | 
 | 599 | ///         float | 
 | 600 | ///         double | 
 | 601 | ///         void | 
 | 602 | /// [GNU]   typeof-specifier | 
 | 603 | /// [C++0x] auto               [TODO] | 
 | 604 | /// | 
 | 605 | ///       type-name: | 
 | 606 | ///         class-name | 
 | 607 | ///         enum-name | 
 | 608 | ///         typedef-name | 
 | 609 | /// | 
 | 610 | void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { | 
 | 611 |   DS.SetRangeStart(Tok.getLocation()); | 
 | 612 |   const char *PrevSpec; | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 613 |   unsigned DiagID; | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 614 |   SourceLocation Loc = Tok.getLocation(); | 
 | 615 |    | 
 | 616 |   switch (Tok.getKind()) { | 
| Chris Lattner | 55a7cef | 2009-01-05 00:13:00 +0000 | [diff] [blame] | 617 |   case tok::identifier:   // foo::bar | 
 | 618 |   case tok::coloncolon:   // ::foo::bar | 
 | 619 |     assert(0 && "Annotation token should already be formed!"); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 620 |   default:  | 
 | 621 |     assert(0 && "Not a simple-type-specifier token!"); | 
 | 622 |     abort(); | 
| Chris Lattner | 55a7cef | 2009-01-05 00:13:00 +0000 | [diff] [blame] | 623 |  | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 624 |   // type-name | 
| Chris Lattner | b31757b | 2009-01-06 05:06:21 +0000 | [diff] [blame] | 625 |   case tok::annot_typename: { | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 626 |     DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 627 |                        Tok.getAnnotationValue()); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 628 |     break; | 
 | 629 |   } | 
 | 630 |      | 
 | 631 |   // builtin types | 
 | 632 |   case tok::kw_short: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 633 |     DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 634 |     break; | 
 | 635 |   case tok::kw_long: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 636 |     DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 637 |     break; | 
 | 638 |   case tok::kw_signed: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 639 |     DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 640 |     break; | 
 | 641 |   case tok::kw_unsigned: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 642 |     DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 643 |     break; | 
 | 644 |   case tok::kw_void: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 645 |     DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 646 |     break; | 
 | 647 |   case tok::kw_char: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 648 |     DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 649 |     break; | 
 | 650 |   case tok::kw_int: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 651 |     DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 652 |     break; | 
 | 653 |   case tok::kw_float: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 654 |     DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 655 |     break; | 
 | 656 |   case tok::kw_double: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 657 |     DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 658 |     break; | 
 | 659 |   case tok::kw_wchar_t: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 660 |     DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 661 |     break; | 
| Alisdair Meredith | f5c209d | 2009-07-14 06:30:34 +0000 | [diff] [blame] | 662 |   case tok::kw_char16_t: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 663 |     DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID); | 
| Alisdair Meredith | f5c209d | 2009-07-14 06:30:34 +0000 | [diff] [blame] | 664 |     break; | 
 | 665 |   case tok::kw_char32_t: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 666 |     DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID); | 
| Alisdair Meredith | f5c209d | 2009-07-14 06:30:34 +0000 | [diff] [blame] | 667 |     break; | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 668 |   case tok::kw_bool: | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 669 |     DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 670 |     break; | 
 | 671 |    | 
 | 672 |   // GNU typeof support. | 
 | 673 |   case tok::kw_typeof: | 
 | 674 |     ParseTypeofSpecifier(DS); | 
| Douglas Gregor | 9b3064b | 2009-04-01 22:41:11 +0000 | [diff] [blame] | 675 |     DS.Finish(Diags, PP); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 676 |     return; | 
 | 677 |   } | 
| Chris Lattner | b31757b | 2009-01-06 05:06:21 +0000 | [diff] [blame] | 678 |   if (Tok.is(tok::annot_typename)) | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 679 |     DS.SetRangeEnd(Tok.getAnnotationEndLoc()); | 
 | 680 |   else | 
 | 681 |     DS.SetRangeEnd(Tok.getLocation()); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 682 |   ConsumeToken(); | 
| Douglas Gregor | 9b3064b | 2009-04-01 22:41:11 +0000 | [diff] [blame] | 683 |   DS.Finish(Diags, PP); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 684 | } | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 685 |  | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 686 | /// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ | 
 | 687 | /// [dcl.name]), which is a non-empty sequence of type-specifiers, | 
 | 688 | /// e.g., "const short int". Note that the DeclSpec is *not* finished | 
 | 689 | /// by parsing the type-specifier-seq, because these sequences are | 
 | 690 | /// typically followed by some form of declarator. Returns true and | 
 | 691 | /// emits diagnostics if this is not a type-specifier-seq, false | 
 | 692 | /// otherwise. | 
 | 693 | /// | 
 | 694 | ///   type-specifier-seq: [C++ 8.1] | 
 | 695 | ///     type-specifier type-specifier-seq[opt] | 
 | 696 | /// | 
 | 697 | bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { | 
 | 698 |   DS.SetRangeStart(Tok.getLocation()); | 
 | 699 |   const char *PrevSpec = 0; | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 700 |   unsigned DiagID; | 
 | 701 |   bool isInvalid = 0; | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 702 |  | 
 | 703 |   // Parse one or more of the type specifiers. | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 704 |   if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) { | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 705 |     Diag(Tok, diag::err_operator_missing_type_specifier); | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 706 |     return true; | 
 | 707 |   } | 
| Chris Lattner | 7a0ab5f | 2009-01-06 06:59:53 +0000 | [diff] [blame] | 708 |    | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame^] | 709 |   while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ; | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 710 |  | 
 | 711 |   return false; | 
 | 712 | } | 
 | 713 |  | 
| Douglas Gregor | 43c7bad | 2008-11-17 16:14:12 +0000 | [diff] [blame] | 714 | /// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 715 | /// operator name (C++ [over.oper]). If successful, returns the | 
 | 716 | /// predefined identifier that corresponds to that overloaded | 
 | 717 | /// operator. Otherwise, returns NULL and does not consume any tokens. | 
 | 718 | /// | 
 | 719 | ///       operator-function-id: [C++ 13.5] | 
 | 720 | ///         'operator' operator | 
 | 721 | /// | 
 | 722 | /// operator: one of | 
 | 723 | ///            new   delete  new[]   delete[] | 
 | 724 | ///            +     -    *  /    %  ^    &   |   ~ | 
 | 725 | ///            !     =    <  >    += -=   *=  /=  %= | 
 | 726 | ///            ^=    &=   |= <<   >> >>= <<=  ==  != | 
 | 727 | ///            <=    >=   && ||   ++ --   ,   ->* -> | 
 | 728 | ///            ()    [] | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 729 | OverloadedOperatorKind | 
 | 730 | Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) { | 
| Argyrios Kyrtzidis | 9057a81 | 2008-11-07 15:54:02 +0000 | [diff] [blame] | 731 |   assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 732 |   SourceLocation Loc; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 733 |  | 
 | 734 |   OverloadedOperatorKind Op = OO_None; | 
 | 735 |   switch (NextToken().getKind()) { | 
 | 736 |   case tok::kw_new: | 
 | 737 |     ConsumeToken(); // 'operator' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 738 |     Loc = ConsumeToken(); // 'new' | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 739 |     if (Tok.is(tok::l_square)) { | 
 | 740 |       ConsumeBracket(); // '[' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 741 |       Loc = Tok.getLocation(); | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 742 |       ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' | 
 | 743 |       Op = OO_Array_New; | 
 | 744 |     } else { | 
 | 745 |       Op = OO_New; | 
 | 746 |     } | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 747 |     if (EndLoc) | 
 | 748 |       *EndLoc = Loc; | 
| Douglas Gregor | e94ca9e4 | 2008-11-18 14:39:36 +0000 | [diff] [blame] | 749 |     return Op; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 750 |  | 
 | 751 |   case tok::kw_delete: | 
 | 752 |     ConsumeToken(); // 'operator' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 753 |     Loc = ConsumeToken(); // 'delete' | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 754 |     if (Tok.is(tok::l_square)) { | 
 | 755 |       ConsumeBracket(); // '[' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 756 |       Loc = Tok.getLocation(); | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 757 |       ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' | 
 | 758 |       Op = OO_Array_Delete; | 
 | 759 |     } else { | 
 | 760 |       Op = OO_Delete; | 
 | 761 |     } | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 762 |     if (EndLoc) | 
 | 763 |       *EndLoc = Loc; | 
| Douglas Gregor | e94ca9e4 | 2008-11-18 14:39:36 +0000 | [diff] [blame] | 764 |     return Op; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 765 |  | 
| Douglas Gregor | 02bcd4c | 2008-11-10 13:38:07 +0000 | [diff] [blame] | 766 | #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)  \ | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 767 |     case tok::Token:  Op = OO_##Name; break; | 
| Douglas Gregor | 02bcd4c | 2008-11-10 13:38:07 +0000 | [diff] [blame] | 768 | #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 769 | #include "clang/Basic/OperatorKinds.def" | 
 | 770 |  | 
 | 771 |   case tok::l_paren: | 
 | 772 |     ConsumeToken(); // 'operator' | 
 | 773 |     ConsumeParen(); // '(' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 774 |     Loc = Tok.getLocation(); | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 775 |     ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 776 |     if (EndLoc) | 
 | 777 |       *EndLoc = Loc; | 
| Douglas Gregor | e94ca9e4 | 2008-11-18 14:39:36 +0000 | [diff] [blame] | 778 |     return OO_Call; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 779 |  | 
 | 780 |   case tok::l_square: | 
 | 781 |     ConsumeToken(); // 'operator' | 
 | 782 |     ConsumeBracket(); // '[' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 783 |     Loc = Tok.getLocation(); | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 784 |     ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 785 |     if (EndLoc) | 
 | 786 |       *EndLoc = Loc; | 
| Douglas Gregor | e94ca9e4 | 2008-11-18 14:39:36 +0000 | [diff] [blame] | 787 |     return OO_Subscript; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 788 |  | 
 | 789 |   default: | 
| Douglas Gregor | e94ca9e4 | 2008-11-18 14:39:36 +0000 | [diff] [blame] | 790 |     return OO_None; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 791 |   } | 
 | 792 |  | 
| Douglas Gregor | 43c7bad | 2008-11-17 16:14:12 +0000 | [diff] [blame] | 793 |   ConsumeToken(); // 'operator' | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 794 |   Loc = ConsumeAnyToken(); // the operator itself | 
 | 795 |   if (EndLoc) | 
 | 796 |     *EndLoc = Loc; | 
| Douglas Gregor | e94ca9e4 | 2008-11-18 14:39:36 +0000 | [diff] [blame] | 797 |   return Op; | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 798 | } | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 799 |  | 
 | 800 | /// ParseConversionFunctionId - Parse a C++ conversion-function-id, | 
 | 801 | /// which expresses the name of a user-defined conversion operator | 
 | 802 | /// (C++ [class.conv.fct]p1). Returns the type that this operator is | 
 | 803 | /// specifying a conversion for, or NULL if there was an error. | 
 | 804 | /// | 
 | 805 | ///        conversion-function-id: [C++ 12.3.2] | 
 | 806 | ///                   operator conversion-type-id | 
 | 807 | /// | 
 | 808 | ///        conversion-type-id: | 
 | 809 | ///                   type-specifier-seq conversion-declarator[opt] | 
 | 810 | /// | 
 | 811 | ///        conversion-declarator: | 
 | 812 | ///                   ptr-operator conversion-declarator[opt] | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 813 | Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) { | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 814 |   assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); | 
 | 815 |   ConsumeToken(); // 'operator' | 
 | 816 |  | 
 | 817 |   // Parse the type-specifier-seq. | 
 | 818 |   DeclSpec DS; | 
 | 819 |   if (ParseCXXTypeSpecifierSeq(DS)) | 
 | 820 |     return 0; | 
 | 821 |  | 
 | 822 |   // Parse the conversion-declarator, which is merely a sequence of | 
 | 823 |   // ptr-operators. | 
 | 824 |   Declarator D(DS, Declarator::TypeNameContext); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 825 |   ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 826 |   if (EndLoc) | 
 | 827 |     *EndLoc = D.getSourceRange().getEnd(); | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 828 |  | 
 | 829 |   // Finish up the type. | 
 | 830 |   Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); | 
| Douglas Gregor | 5ac8aff | 2009-01-26 22:44:13 +0000 | [diff] [blame] | 831 |   if (Result.isInvalid()) | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 832 |     return 0; | 
 | 833 |   else | 
| Douglas Gregor | 5ac8aff | 2009-01-26 22:44:13 +0000 | [diff] [blame] | 834 |     return Result.get(); | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 835 | } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 836 |  | 
 | 837 | /// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate | 
 | 838 | /// memory in a typesafe manner and call constructors. | 
| Chris Lattner | 59232d3 | 2009-01-04 21:25:24 +0000 | [diff] [blame] | 839 | ///  | 
 | 840 | /// This method is called to parse the new expression after the optional :: has | 
 | 841 | /// been already parsed.  If the :: was present, "UseGlobal" is true and "Start" | 
 | 842 | /// is its location.  Otherwise, "Start" is the location of the 'new' token. | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 843 | /// | 
 | 844 | ///        new-expression: | 
 | 845 | ///                   '::'[opt] 'new' new-placement[opt] new-type-id | 
 | 846 | ///                                     new-initializer[opt] | 
 | 847 | ///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')' | 
 | 848 | ///                                     new-initializer[opt] | 
 | 849 | /// | 
 | 850 | ///        new-placement: | 
 | 851 | ///                   '(' expression-list ')' | 
 | 852 | /// | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 853 | ///        new-type-id: | 
 | 854 | ///                   type-specifier-seq new-declarator[opt] | 
 | 855 | /// | 
 | 856 | ///        new-declarator: | 
 | 857 | ///                   ptr-operator new-declarator[opt] | 
 | 858 | ///                   direct-new-declarator | 
 | 859 | /// | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 860 | ///        new-initializer: | 
 | 861 | ///                   '(' expression-list[opt] ')' | 
 | 862 | /// [C++0x]           braced-init-list                                   [TODO] | 
 | 863 | /// | 
| Chris Lattner | 59232d3 | 2009-01-04 21:25:24 +0000 | [diff] [blame] | 864 | Parser::OwningExprResult | 
 | 865 | Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { | 
 | 866 |   assert(Tok.is(tok::kw_new) && "expected 'new' token"); | 
 | 867 |   ConsumeToken();   // Consume 'new' | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 868 |  | 
 | 869 |   // A '(' now can be a new-placement or the '(' wrapping the type-id in the | 
 | 870 |   // second form of new-expression. It can't be a new-type-id. | 
 | 871 |  | 
| Sebastian Redl | a55e52c | 2008-11-25 22:21:31 +0000 | [diff] [blame] | 872 |   ExprVector PlacementArgs(Actions); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 873 |   SourceLocation PlacementLParen, PlacementRParen; | 
 | 874 |  | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 875 |   bool ParenTypeId; | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 876 |   DeclSpec DS; | 
 | 877 |   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 878 |   if (Tok.is(tok::l_paren)) { | 
 | 879 |     // If it turns out to be a placement, we change the type location. | 
 | 880 |     PlacementLParen = ConsumeParen(); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 881 |     if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) { | 
 | 882 |       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 883 |       return ExprError(); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 884 |     } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 885 |  | 
 | 886 |     PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 887 |     if (PlacementRParen.isInvalid()) { | 
 | 888 |       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 889 |       return ExprError(); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 890 |     } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 891 |  | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 892 |     if (PlacementArgs.empty()) { | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 893 |       // Reset the placement locations. There was no placement. | 
 | 894 |       PlacementLParen = PlacementRParen = SourceLocation(); | 
 | 895 |       ParenTypeId = true; | 
 | 896 |     } else { | 
 | 897 |       // We still need the type. | 
 | 898 |       if (Tok.is(tok::l_paren)) { | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 899 |         SourceLocation LParen = ConsumeParen(); | 
 | 900 |         ParseSpecifierQualifierList(DS); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 901 |         DeclaratorInfo.SetSourceRange(DS.getSourceRange()); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 902 |         ParseDeclarator(DeclaratorInfo); | 
 | 903 |         MatchRHSPunctuation(tok::r_paren, LParen); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 904 |         ParenTypeId = true; | 
 | 905 |       } else { | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 906 |         if (ParseCXXTypeSpecifierSeq(DS)) | 
 | 907 |           DeclaratorInfo.setInvalidType(true); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 908 |         else { | 
 | 909 |           DeclaratorInfo.SetSourceRange(DS.getSourceRange()); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 910 |           ParseDeclaratorInternal(DeclaratorInfo, | 
 | 911 |                                   &Parser::ParseDirectNewDeclarator); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 912 |         } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 913 |         ParenTypeId = false; | 
 | 914 |       } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 915 |     } | 
 | 916 |   } else { | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 917 |     // A new-type-id is a simplified type-id, where essentially the | 
 | 918 |     // direct-declarator is replaced by a direct-new-declarator. | 
 | 919 |     if (ParseCXXTypeSpecifierSeq(DS)) | 
 | 920 |       DeclaratorInfo.setInvalidType(true); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 921 |     else { | 
 | 922 |       DeclaratorInfo.SetSourceRange(DS.getSourceRange()); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 923 |       ParseDeclaratorInternal(DeclaratorInfo, | 
 | 924 |                               &Parser::ParseDirectNewDeclarator); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 925 |     } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 926 |     ParenTypeId = false; | 
 | 927 |   } | 
| Chris Lattner | eaaebc7 | 2009-04-25 08:06:05 +0000 | [diff] [blame] | 928 |   if (DeclaratorInfo.isInvalidType()) { | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 929 |     SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 930 |     return ExprError(); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 931 |   } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 932 |  | 
| Sebastian Redl | a55e52c | 2008-11-25 22:21:31 +0000 | [diff] [blame] | 933 |   ExprVector ConstructorArgs(Actions); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 934 |   SourceLocation ConstructorLParen, ConstructorRParen; | 
 | 935 |  | 
 | 936 |   if (Tok.is(tok::l_paren)) { | 
 | 937 |     ConstructorLParen = ConsumeParen(); | 
 | 938 |     if (Tok.isNot(tok::r_paren)) { | 
 | 939 |       CommaLocsTy CommaLocs; | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 940 |       if (ParseExpressionList(ConstructorArgs, CommaLocs)) { | 
 | 941 |         SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 942 |         return ExprError(); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 943 |       } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 944 |     } | 
 | 945 |     ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 946 |     if (ConstructorRParen.isInvalid()) { | 
 | 947 |       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 948 |       return ExprError(); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 949 |     } | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 950 |   } | 
 | 951 |  | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 952 |   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, | 
 | 953 |                              move_arg(PlacementArgs), PlacementRParen, | 
 | 954 |                              ParenTypeId, DeclaratorInfo, ConstructorLParen, | 
 | 955 |                              move_arg(ConstructorArgs), ConstructorRParen); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 956 | } | 
 | 957 |  | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 958 | /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be | 
 | 959 | /// passed to ParseDeclaratorInternal. | 
 | 960 | /// | 
 | 961 | ///        direct-new-declarator: | 
 | 962 | ///                   '[' expression ']' | 
 | 963 | ///                   direct-new-declarator '[' constant-expression ']' | 
 | 964 | /// | 
| Chris Lattner | 59232d3 | 2009-01-04 21:25:24 +0000 | [diff] [blame] | 965 | void Parser::ParseDirectNewDeclarator(Declarator &D) { | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 966 |   // Parse the array dimensions. | 
 | 967 |   bool first = true; | 
 | 968 |   while (Tok.is(tok::l_square)) { | 
 | 969 |     SourceLocation LLoc = ConsumeBracket(); | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 970 |     OwningExprResult Size(first ? ParseExpression() | 
 | 971 |                                 : ParseConstantExpression()); | 
| Sebastian Redl | 0e9eabc | 2008-12-09 13:15:23 +0000 | [diff] [blame] | 972 |     if (Size.isInvalid()) { | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 973 |       // Recover | 
 | 974 |       SkipUntil(tok::r_square); | 
 | 975 |       return; | 
 | 976 |     } | 
 | 977 |     first = false; | 
 | 978 |  | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 979 |     SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 980 |     D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, | 
| Douglas Gregor | 7e7eb3d | 2009-07-06 15:59:29 +0000 | [diff] [blame] | 981 |                                             Size.release(), LLoc, RLoc), | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 982 |                   RLoc); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 983 |  | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 984 |     if (RLoc.isInvalid()) | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 985 |       return; | 
 | 986 |   } | 
 | 987 | } | 
 | 988 |  | 
 | 989 | /// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id. | 
 | 990 | /// This ambiguity appears in the syntax of the C++ new operator. | 
 | 991 | /// | 
 | 992 | ///        new-expression: | 
 | 993 | ///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')' | 
 | 994 | ///                                     new-initializer[opt] | 
 | 995 | /// | 
 | 996 | ///        new-placement: | 
 | 997 | ///                   '(' expression-list ')' | 
 | 998 | /// | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 999 | bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, | 
| Chris Lattner | 59232d3 | 2009-01-04 21:25:24 +0000 | [diff] [blame] | 1000 |                                          Declarator &D) { | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1001 |   // The '(' was already consumed. | 
 | 1002 |   if (isTypeIdInParens()) { | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 1003 |     ParseSpecifierQualifierList(D.getMutableDeclSpec()); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 1004 |     D.SetSourceRange(D.getDeclSpec().getSourceRange()); | 
| Sebastian Redl | cee63fb | 2008-12-02 14:43:59 +0000 | [diff] [blame] | 1005 |     ParseDeclarator(D); | 
| Chris Lattner | eaaebc7 | 2009-04-25 08:06:05 +0000 | [diff] [blame] | 1006 |     return D.isInvalidType(); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1007 |   } | 
 | 1008 |  | 
 | 1009 |   // It's not a type, it has to be an expression list. | 
 | 1010 |   // Discard the comma locations - ActOnCXXNew has enough parameters. | 
 | 1011 |   CommaLocsTy CommaLocs; | 
 | 1012 |   return ParseExpressionList(PlacementArgs, CommaLocs); | 
 | 1013 | } | 
 | 1014 |  | 
 | 1015 | /// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used | 
 | 1016 | /// to free memory allocated by new. | 
 | 1017 | /// | 
| Chris Lattner | 59232d3 | 2009-01-04 21:25:24 +0000 | [diff] [blame] | 1018 | /// This method is called to parse the 'delete' expression after the optional | 
 | 1019 | /// '::' has been already parsed.  If the '::' was present, "UseGlobal" is true | 
 | 1020 | /// and "Start" is its location.  Otherwise, "Start" is the location of the | 
 | 1021 | /// 'delete' token. | 
 | 1022 | /// | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1023 | ///        delete-expression: | 
 | 1024 | ///                   '::'[opt] 'delete' cast-expression | 
 | 1025 | ///                   '::'[opt] 'delete' '[' ']' cast-expression | 
| Chris Lattner | 59232d3 | 2009-01-04 21:25:24 +0000 | [diff] [blame] | 1026 | Parser::OwningExprResult | 
 | 1027 | Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { | 
 | 1028 |   assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword"); | 
 | 1029 |   ConsumeToken(); // Consume 'delete' | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1030 |  | 
 | 1031 |   // Array delete? | 
 | 1032 |   bool ArrayDelete = false; | 
 | 1033 |   if (Tok.is(tok::l_square)) { | 
 | 1034 |     ArrayDelete = true; | 
 | 1035 |     SourceLocation LHS = ConsumeBracket(); | 
 | 1036 |     SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS); | 
 | 1037 |     if (RHS.isInvalid()) | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 1038 |       return ExprError(); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1039 |   } | 
 | 1040 |  | 
| Sebastian Redl | 2f7ece7 | 2008-12-11 21:36:32 +0000 | [diff] [blame] | 1041 |   OwningExprResult Operand(ParseCastExpression(false)); | 
| Sebastian Redl | 0e9eabc | 2008-12-09 13:15:23 +0000 | [diff] [blame] | 1042 |   if (Operand.isInvalid()) | 
| Sebastian Redl | 20df9b7 | 2008-12-11 22:51:44 +0000 | [diff] [blame] | 1043 |     return move(Operand); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1044 |  | 
| Sebastian Redl | f53597f | 2009-03-15 17:47:39 +0000 | [diff] [blame] | 1045 |   return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand)); | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 1046 | } | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 1047 |  | 
 | 1048 | static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) | 
 | 1049 | { | 
 | 1050 |   switch(kind) { | 
 | 1051 |   default: assert(false && "Not a known unary type trait."); | 
 | 1052 |   case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign; | 
 | 1053 |   case tok::kw___has_nothrow_copy:        return UTT_HasNothrowCopy; | 
 | 1054 |   case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; | 
 | 1055 |   case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign; | 
 | 1056 |   case tok::kw___has_trivial_copy:        return UTT_HasTrivialCopy; | 
 | 1057 |   case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; | 
 | 1058 |   case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor; | 
 | 1059 |   case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor; | 
 | 1060 |   case tok::kw___is_abstract:             return UTT_IsAbstract; | 
 | 1061 |   case tok::kw___is_class:                return UTT_IsClass; | 
 | 1062 |   case tok::kw___is_empty:                return UTT_IsEmpty; | 
 | 1063 |   case tok::kw___is_enum:                 return UTT_IsEnum; | 
 | 1064 |   case tok::kw___is_pod:                  return UTT_IsPOD; | 
 | 1065 |   case tok::kw___is_polymorphic:          return UTT_IsPolymorphic; | 
 | 1066 |   case tok::kw___is_union:                return UTT_IsUnion; | 
 | 1067 |   } | 
 | 1068 | } | 
 | 1069 |  | 
 | 1070 | /// ParseUnaryTypeTrait - Parse the built-in unary type-trait | 
 | 1071 | /// pseudo-functions that allow implementation of the TR1/C++0x type traits | 
 | 1072 | /// templates. | 
 | 1073 | /// | 
 | 1074 | ///       primary-expression: | 
 | 1075 | /// [GNU]             unary-type-trait '(' type-id ')' | 
 | 1076 | /// | 
 | 1077 | Parser::OwningExprResult Parser::ParseUnaryTypeTrait() | 
 | 1078 | { | 
 | 1079 |   UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); | 
 | 1080 |   SourceLocation Loc = ConsumeToken(); | 
 | 1081 |  | 
 | 1082 |   SourceLocation LParen = Tok.getLocation(); | 
 | 1083 |   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) | 
 | 1084 |     return ExprError(); | 
 | 1085 |  | 
 | 1086 |   // FIXME: Error reporting absolutely sucks! If the this fails to parse a type | 
 | 1087 |   // there will be cryptic errors about mismatched parentheses and missing | 
 | 1088 |   // specifiers. | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 1089 |   TypeResult Ty = ParseTypeName(); | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 1090 |  | 
 | 1091 |   SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); | 
 | 1092 |  | 
| Douglas Gregor | 809070a | 2009-02-18 17:45:20 +0000 | [diff] [blame] | 1093 |   if (Ty.isInvalid()) | 
 | 1094 |     return ExprError(); | 
 | 1095 |  | 
 | 1096 |   return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen); | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 1097 | } | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1098 |  | 
 | 1099 | /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a | 
 | 1100 | /// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate | 
 | 1101 | /// based on the context past the parens. | 
 | 1102 | Parser::OwningExprResult | 
 | 1103 | Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, | 
 | 1104 |                                          TypeTy *&CastTy, | 
 | 1105 |                                          SourceLocation LParenLoc, | 
 | 1106 |                                          SourceLocation &RParenLoc) { | 
 | 1107 |   assert(getLang().CPlusPlus && "Should only be called for C++!"); | 
 | 1108 |   assert(ExprType == CastExpr && "Compound literals are not ambiguous!"); | 
 | 1109 |   assert(isTypeIdInParens() && "Not a type-id!"); | 
 | 1110 |  | 
 | 1111 |   OwningExprResult Result(Actions, true); | 
 | 1112 |   CastTy = 0; | 
 | 1113 |  | 
 | 1114 |   // We need to disambiguate a very ugly part of the C++ syntax: | 
 | 1115 |   // | 
 | 1116 |   // (T())x;  - type-id | 
 | 1117 |   // (T())*x; - type-id | 
 | 1118 |   // (T())/x; - expression | 
 | 1119 |   // (T());   - expression | 
 | 1120 |   // | 
 | 1121 |   // The bad news is that we cannot use the specialized tentative parser, since | 
 | 1122 |   // it can only verify that the thing inside the parens can be parsed as | 
 | 1123 |   // type-id, it is not useful for determining the context past the parens. | 
 | 1124 |   // | 
 | 1125 |   // The good news is that the parser can disambiguate this part without | 
| Argyrios Kyrtzidis | a558a89 | 2009-05-22 15:12:46 +0000 | [diff] [blame] | 1126 |   // making any unnecessary Action calls. | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1127 |   // | 
 | 1128 |   // It uses a scheme similar to parsing inline methods. The parenthesized | 
 | 1129 |   // tokens are cached, the context that follows is determined (possibly by | 
 | 1130 |   // parsing a cast-expression), and then we re-introduce the cached tokens | 
 | 1131 |   // into the token stream and parse them appropriately. | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1132 |  | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1133 |   ParenParseOption ParseAs;   | 
 | 1134 |   CachedTokens Toks; | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1135 |  | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1136 |   // Store the tokens of the parentheses. We will parse them after we determine | 
 | 1137 |   // the context that follows them. | 
 | 1138 |   if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) { | 
 | 1139 |     // We didn't find the ')' we expected. | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1140 |     MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
 | 1141 |     return ExprError(); | 
 | 1142 |   } | 
 | 1143 |  | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1144 |   if (Tok.is(tok::l_brace)) { | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1145 |     ParseAs = CompoundLiteral; | 
 | 1146 |   } else { | 
 | 1147 |     bool NotCastExpr; | 
| Eli Friedman | b53f08a | 2009-05-25 19:41:42 +0000 | [diff] [blame] | 1148 |     // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression | 
 | 1149 |     if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) { | 
 | 1150 |       NotCastExpr = true; | 
 | 1151 |     } else { | 
 | 1152 |       // Try parsing the cast-expression that may follow. | 
 | 1153 |       // If it is not a cast-expression, NotCastExpr will be true and no token | 
 | 1154 |       // will be consumed. | 
 | 1155 |       Result = ParseCastExpression(false/*isUnaryExpression*/, | 
 | 1156 |                                    false/*isAddressofOperand*/, | 
 | 1157 |                                    NotCastExpr); | 
 | 1158 |     } | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1159 |  | 
 | 1160 |     // If we parsed a cast-expression, it's really a type-id, otherwise it's | 
 | 1161 |     // an expression. | 
 | 1162 |     ParseAs = NotCastExpr ? SimpleExpr : CastExpr; | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1163 |   } | 
 | 1164 |  | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1165 |   // The current token should go after the cached tokens.  | 
 | 1166 |   Toks.push_back(Tok); | 
 | 1167 |   // Re-enter the stored parenthesized tokens into the token stream, so we may | 
 | 1168 |   // parse them now. | 
 | 1169 |   PP.EnterTokenStream(Toks.data(), Toks.size(), | 
 | 1170 |                       true/*DisableMacroExpansion*/, false/*OwnsTokens*/); | 
 | 1171 |   // Drop the current token and bring the first cached one. It's the same token | 
 | 1172 |   // as when we entered this function. | 
 | 1173 |   ConsumeAnyToken(); | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1174 |  | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1175 |   if (ParseAs >= CompoundLiteral) { | 
 | 1176 |     TypeResult Ty = ParseTypeName(); | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1177 |  | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1178 |     // Match the ')'. | 
 | 1179 |     if (Tok.is(tok::r_paren)) | 
 | 1180 |       RParenLoc = ConsumeParen(); | 
 | 1181 |     else | 
 | 1182 |       MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1183 |  | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1184 |     if (ParseAs == CompoundLiteral) { | 
 | 1185 |       ExprType = CompoundLiteral; | 
 | 1186 |       return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc); | 
 | 1187 |     } | 
 | 1188 |      | 
 | 1189 |     // We parsed '(' type-id ')' and the thing after it wasn't a '{'. | 
 | 1190 |     assert(ParseAs == CastExpr); | 
 | 1191 |  | 
 | 1192 |     if (Ty.isInvalid()) | 
 | 1193 |       return ExprError(); | 
 | 1194 |  | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1195 |     CastTy = Ty.get(); | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1196 |  | 
 | 1197 |     // Result is what ParseCastExpression returned earlier. | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1198 |     if (!Result.isInvalid()) | 
 | 1199 |       Result = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc,move(Result)); | 
 | 1200 |     return move(Result); | 
 | 1201 |   } | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1202 |    | 
 | 1203 |   // Not a compound literal, and not followed by a cast-expression. | 
 | 1204 |   assert(ParseAs == SimpleExpr); | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1205 |  | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1206 |   ExprType = SimpleExpr; | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1207 |   Result = ParseExpression(); | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1208 |   if (!Result.isInvalid() && Tok.is(tok::r_paren)) | 
 | 1209 |     Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result)); | 
 | 1210 |  | 
 | 1211 |   // Match the ')'. | 
 | 1212 |   if (Result.isInvalid()) { | 
 | 1213 |     SkipUntil(tok::r_paren); | 
 | 1214 |     return ExprError(); | 
 | 1215 |   } | 
| Argyrios Kyrtzidis | f40882a | 2009-05-22 21:09:47 +0000 | [diff] [blame] | 1216 |    | 
| Argyrios Kyrtzidis | f58f45e | 2009-05-22 10:24:42 +0000 | [diff] [blame] | 1217 |   if (Tok.is(tok::r_paren)) | 
 | 1218 |     RParenLoc = ConsumeParen(); | 
 | 1219 |   else | 
 | 1220 |     MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
 | 1221 |  | 
 | 1222 |   return move(Result); | 
 | 1223 | } |